Commit Graph

47 Commits

Author SHA1 Message Date
Egor Zhdan
ba8ba57c77 [cxx-interop] Layout reference types that use tail padding of their bases correctly
This is a follow-up to d3e43bbe which resolved the issue for value types, but not for foreign reference types.

This change teaches IRGen that a base type of a C++ type might occupy less memory than its `sizeof`, specifically, it might only use `dsize` amount of memory.

rdar://147527755
2025-03-27 16:03:51 +00:00
Egor Zhdan
57c7ecd244 [cxx-interop] Fix memory layout for structs with out-of-order base types
In C++, a primary base class that is placed in the beginning of the type's memory layout isn't always the type that is the first in the list of bases – the base types might be laid out in memory in a different order.

This makes sure that IRGen handles base types of C++ structs in the correct order.

This fixes an assertion in asserts-enabled compilers, and an out-of-memory error in asserts-disabled compilers. The issue was happening for both value types and foreign reference types. This change also includes a small refactoring to reuse the logic between the two code paths.

rdar://140848603
2024-12-16 15:53:43 +00:00
Alex Lorenz
af36238004 Merge pull request #74640 from hyp/eng/virtual-destructor-vtable-ref-irgen-linux-android
[cxx-interop] ensure that the body of implicit virtual destructor is …
2024-06-26 10:32:51 -07:00
Alex Lorenz
781a9fc1aa [cxx-interop] ensure destructors referenced only by the exception cleanup landing pad in the constructor's initializer are picked up to be candidates for potential emission into one LLVM IR module
A C++ record destructor that is called implicitly in the landing pad cleanup code of a constructor after a field is initialized might only be referenced there, so the Clang decl finder should pick it up when scanning the AST for interesting Decls that might have to be emitted into one LLVM IR module.
2024-06-25 22:13:19 -07:00
Alex Lorenz
f4949bd8dc fix 2024-06-25 18:22:40 -07:00
Alex Lorenz
cd1ca50c63 [cxx-interop] ensure that the body of implicit virtual destructor is defined before emitting the clang decl for it
This ensures that the destructor definition is emitted into the module's LLVM IR, fixing a linker error.
2024-06-21 17:00:15 -07:00
Egor Zhdan
f56fa41ac6 [cxx-interop] Always instantiate the default destructor
This fixes a linker error when using `std::function` from Swift.

rdar://103979602
2024-06-13 16:09:44 +01:00
Egor Zhdan
494474b021 [cxx-interop] Support C++ default arguments
This allows calling a C++ function with default arguments from Swift without having to explicitly specify the values of all arguments.

rdar://103975014
2024-01-10 16:37:42 +00:00
Hamish Knight
ccd32eb452 NFC: Remove ClangModuleLoader.h include from ExtInfo.h
This was unnecessarily pulling in a whole bunch
of Clang headers when all was needed was a
forward declaration.
2023-10-09 20:29:03 +01:00
zoecarver
6868ae29dc [cxx-interop] Break when we find a linkage specification when traversing all decls in IRGen. 2023-07-10 18:18:18 -07:00
Egor Zhdan
21745e52c4 [cxx-interop] Do not emit IR for C++20 requires expr
This fixes a compiler crash when emitting IR for a for-in loop over a C++ `std::vector` in C++20 mode.

rdar://108810356
2023-05-05 17:21:38 +01:00
Alex Lorenz
b5766fd215 [interop] do not assume we need to IRGen destructors of fields inside a record with an explicit destructor 2023-03-26 12:24:57 -07:00
Alex Lorenz
7320cd877c [interop] ensure IRGen reaches code referenced through destructor invoked using the 'delete' statement in C++ 2023-03-20 17:25:29 -07:00
Alex Lorenz
8d7799a324 [interop] do not traverse type locs when IRGening clang decls from Swift 2023-03-14 14:24:28 -07:00
Alex Lorenz
0e7d525234 [interop] do not stop traversal when looking for clang symbols to IRGen when hitting noexcept expression 2023-03-09 20:19:39 -08:00
Alex Lorenz
cd03a2f8eb [interop] ensure IRGen traverses inherited C++ constructors correctly 2023-03-09 14:46:45 -08:00
Egor Zhdan
1965e74b74 [cxx-interop] Emit IR for templated static members with an out-of-line definition
This fixes https://github.com/apple/swift/issues/63055.

rdar://101539308
2023-01-17 12:09:11 +00:00
Alex Lorenz
934183f854 [cxx-interop] Emit IR for std::get in structured bindings declaration 2022-12-07 15:54:11 -08:00
Egor Zhdan
c307ccc37f [cxx-interop] Emit IR for custom operator new
Fixes https://github.com/apple/swift/issues/62182
2022-11-23 13:15:50 +00:00
Egor Zhdan
6ca60b075e [cxx-interop] Emit IR for virtual methods
Even if a virtual method is not used directly from Swift, it might get emitted into the vtable, and in that case the IR for it should be emitted to avoid linker errors.

Fixes https://github.com/apple/swift/issues/61730.
2022-11-01 13:10:44 -07:00
Egor Zhdan
93e7427ed2 [cxx-interop] Emit IR for destructors of temporary C++ values
This fixes the "undefined reference" linker errors.

rdar://101092732
2022-10-21 15:34:04 +01:00
Egor Zhdan
1b41703b6b [cxx-interop] Do not instantiate templates in unevaluated contexts
Previously we tried to instantiate templates in unevaluated contexts. Some of these templates might not be instantiatable, which caused compile errors, while the equivalent C++ code compiles and runs with no issue.

This was problematic for `std::vector` with libstdc++ on Linux.

Fixes https://github.com/apple/swift/issues/61547.
2022-10-12 19:04:47 +01:00
Josh Soref
9fa14ca215 Spelling irgen (#42470)
* spelling: abstractable

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: across

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: clazz

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: command

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: components

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: current

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: declared

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: discrimination

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: entities

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: except

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: existential

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: generic

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: initialization

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: initialize

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: inserted

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: instantiate

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: instantiation

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: interfere

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: interferes

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: intrinsic

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: metadata

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: might

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: multiple

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: necessary

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: objective

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: occurrences

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: outlined

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: parameters

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: payload

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: rearchitecting

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: replaceable

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: reverse

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: rewritable

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: shareably

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: specializations

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: speedup

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: template

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: that

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: the

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: transferred

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: uninitialized

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: witness

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

Co-authored-by: Josh Soref <jsoref@users.noreply.github.com>
2022-04-21 14:02:03 -07:00
Egor Zhdan
e9b0c8d705 [cxx-interop] Fix linker errors when a template is used from different modules
If a templated C++ class is used from two different C++ modules, and those modules are included in Swift, Clang will create different two different redecls for the class & its methods.

For each of the methods, only one of the redecls would actually have a body, the other would have empty bodies. That prevents `ClangDeclFinder` from properly finding the symbols referenced from a method body, leading to a linker error in some cases, when the first redecl is missing a body.

This prevents `std::string` from being used on Linux:
```
/tmp/use-std-string-2dd593.o:use-std-string-2dd593.o:function void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char*>(char*, char*, std::forward_iterator_tag): error: undefined reference to 'bool __gnu_cxx::__is_null_pointer<char>(char*)'
/tmp/use-std-string-2dd593.o:use-std-string-2dd593.o:function void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char*>(char*, char*, std::forward_iterator_tag): error: undefined reference to 'std::iterator_traits<char*>::difference_type std::distance<char*>(char*, char*)'
clang-13: error: linker command failed with exit code 1 (use -v to see invocation)
<unknown>:0: error: link command failed with exit code 1 (use -v to see invocation)
```
2022-04-07 20:31:12 +01:00
Alex
93c4c621b7 [cxx-interop] Walk initializer decls when walking constructor decls (#41584)
This addresses SR-15272.

When you have a function (e.g. 'foo') which is used in a constructor
initializer (e.g. constructor of some class 'Bar'), and you use the
constructor from swift code without directly using the function (e.g.
Bar's ctor is used from swift but foo isn't, foo is used from Bar's ctor),
you will get a link error. My fix is as follows:

When walking the clangAST to be imported, make sure you look at each
CXXCtorInitializer for each CXXConstructorDecl you see.
2022-03-14 09:56:55 -07:00
zoecarver
323e2b16a7 [cxx-interop] Fix linker errors when using std-vector.
Adds tests for using std-vector and some other interesting types.

This patch fixes four mis conceptions that the compiler was previously making:

	1. Implicit destructors have no side effects. (Yes, this means we were not cleaning up some objects.)
	2. Implicit destructors have bodies. (Technically they do, but the body doesn't include CallExprs that they make when lowered to IR.)
	3. Functions other than methods can be uninstantiated templates.
	4. Uninstantiated templates may have executable code. (I.e., we can never take the fast path.)

And makes sure that we visit the destructor of any VarDecl (including parameters).
2022-01-17 11:56:15 -08:00
zoecarver
b280d26a7b [cxx-interop] Fix class template instantiation.
Lazily instantiate class template members. This means we no longer
reject some programs that clang accepts, such as the following:

```
template<class T> struct Foo { void fail(T value) { value.fail(); } };
using Bar = Foo<int>;
```

The above program will not error so long as `Bar::fail` isn't called.
(Previously, we'd fail to import `Bar`.)
2021-02-24 11:25:45 -08:00
Slava Pestov
c0aa20298b IRGen: Only emit PragmaCommentDecls if building for Windows, or LTO is enabled
clang::DeclContext::decls_begin() deserializes all the pre-compiled headers
imported into the current translation unit, which is expensive.

Workaround this by disabling the emission of PragmaCommentDecls unless we're
building for a Windows target, or LTO is enabled.

A better fix would be to serialize a separate index for PragmaCommentDecls
so that they can be deserialized without deserializing everything else.
I filed rdar://problem/74036099 to track the longer-term fix.

Fixes rdar://problem/73951264.
2021-02-05 15:34:39 -05:00
scentini
0b3990c141 [cxx-interop] Generate IR for decls called from members (#35056)
Currently the following code doesn't work when `callConstructor()` is called from Swift:
```cc
inline int increment(int value) {
  return value + 1;
}

struct Incrementor {
  int incrementee;
  Incrementor(int value) : incrementee(increment(value)) {}
}

int callConstructor(int value) {
  return Incrementor(value).incrementee;
}
```

The issue is that we don't generate `IR` for the `increment()` function when it's only called from a constructor or a method.
Swift is aware of the existence of `increment()` and we see it in `IR` as `declare incrementEi`, however, as we don't to emit a definition, we get the following error:
```
Incrementor::Incrementor(int): error: undefined reference to 'increment(int)'
```

This PR fixes this by visiting constructors and methods in `IRGen` and calling `HandleTopLevelDecl()` with all used declarations, which results in emitting definitions for the used declarations.

Co-authored-by: Marcel Hlopko <hlopko@google.com>
2021-01-21 10:16:25 +01:00
3405691582
38dd7d8192 [IRGen] Fix asserting local extern declarations.
emitClangDecl interacts with clang and LLVM to achieve C interop. On the
LLVM side, CodeGenModule::EmitGlobal asserts if the decl eventually
passed to it is not a "file scoped" via VarDecl::isFileVarDecl.

LLVM currently asserts on local extern variables in C headers passed to
Swift when the definition exists outside that header. To fix this, we
need to ensure that we are only passing Decls that do not trip the
assertion but not unduly limit local extern variables when the
corresponding definition exists inside that header.

We can do that fairly simply by checking for isFileVarDecl just before
we hand-off to clang. When the definition for the local extern variable
exists inside the header, isFileVarDecl is true, and if it exists
elsewhere, it is false. This matches up with the assert expectation on
the LLVM side exactly.

This indirectly addresses #28968, since that contains the only part of
the Swift stdlib that uses a local extern variable, but any header that
is used with Swift that contains a local extern variable will cause the
compiler to assert when built with assertions enabled.
2020-09-02 00:49:39 -04:00
Martin Boehme
6bf0f26ecd Emit /DEFAULTLIB directive for #pragma comment(lib, ...) in a C module.
This is important, for example, for linking correctly to the C++
standard library on Windows, which uses `#pragma comment(lib, ...)` in
its headers to specify the correct library to link against.
2020-05-20 15:28:12 +02:00
martinboehme
0e75f374d4 Merge branch 'master' into optimize-emit-clang-decl 2020-04-24 17:33:38 +02:00
Martin Boehme
cd7f205ade [IRGen] Check as early as possible for Clang decls we've seen before.
Previously, we were only doing this after the fast-path code that
handles decls without any executable code. This meant, however, that we
were potentially processing these decls multiple times. This is
definitely inefficient; it may even be a correctness issue, depending on
what amount of checking `HandleTopLevelDecl` does to see if it has
processed a particular decl before (which I'm not sure about either
way).
2020-04-24 17:19:19 +02:00
Martin Boehme
d98f8d3a3d Also emit inline functions that are used in variable initializers. 2020-04-17 12:53:06 +02:00
Martin Boehme
6a5722058b Respond to review comment by @rjmccall.
Reinstate fast path where declaration is not a ValueDecl.
2020-04-16 10:52:08 +02:00
Martin Boehme
839c4e05ad Bug fix: Emit code for C++ inline function called from another inline function.
Adds a test that fails without the fix.

The fix consists simply of removing a return statement; as a result, we
now always emit code for functions referenced from the function we are
currently emitting.

Previously, this was not done for externally visible functions. This
goes all the way back to when `GenClangDecl.cpp` was originally introduced here:

ee22004b84

I speculate that the reason for doing this was that in C and Objective-C, we
can assume that an externally visible function will be provided by some
`.o` file we're linking against (though I'm not sure if this is in fact
true for C99 inline functions). At any rate, this assumption is no longer true
for C++ inline functions.
2020-04-15 09:18:22 +02:00
Arnold Schwaighofer
9ddf115b0a IRGen: Don't try to emit non-global variables of imported inline c functions
The previous check would fail because isExternallyVisible() is false for local
static variables with internal linkage.

rdar://29937443
2017-01-18 11:05:20 -08:00
practicalswift
6d1ae2a39c [gardening] 2016 → 2017 2017-01-06 16:41:22 +01:00
practicalswift
797b80765f [gardening] Use the correct base URL (https://swift.org) in references to the Swift website
Remove all references to the old non-TLS enabled base URL (http://swift.org)
2016-11-20 17:36:03 +01:00
John McCall
79c83c7303 Teach IRGen to tell Clang to emit lazy definitions on demand.
Previously, we had hacks in place to eagerly emit everything in
the global ExternalDefinitions list.  These can now be removed,
at least at the IRGen layer.
2016-05-18 22:48:45 -07:00
Michael Gottesman
0ff76575aa Respond to upstream change in clang r253949. 2016-02-06 11:22:25 -08:00
Zach Panzarino
e3a4147ac9 Update copyright date 2015-12-31 23:28:40 +00:00
Arnold Schwaighofer
15ff698409 IRGen: Give ClangCodeGen a chance to emit its translation unit's global state
We need this because that global state includes tables like llvm[.compiler].used
which would otherwise be sorely missed.

This fixes an issue of the clang importer that would cause us to fail whenever
we imported a function (say it is marked as static inline) that performs an
objective-c method call and we optimize the code. The optimizer would not see
the objective-c selector global variable (which is marked private) as being
"used by unkown i.e the objc runtime" and would rightly assume it could
propagate the value of the global variable's initializer value as a constant to
loads of the global variable.

Now we call the ClangCodeGenerators translation unit finalization code which
will emit these tables and other module flags. We need to take care that we
merge those datastrutures with datastructures that we emit from swift's IRGen.

rdar://21115194

Swift SVN r29176
2015-05-31 00:01:29 +00:00
Jordan Rose
f4a1841218 [IRGen] Properly track whether we've emitted an imported static function.
...by using the canonical decl in all cases, i.e. "the declaration meant
for when you want to unique things".

rdar://problem/19480333

Swift SVN r24950
2015-02-04 08:10:52 +00:00
Jordan Rose
4fae1f664f [IRGen] Remove the AST walk that looks for local type decls.
Per the previous commit we are no longer using this. Minor save in
simplicity and maybe a bit of compilation time as well.

In the long run IRGen probably shouldn't be pulling information from the
AST at all; the SILModule should be able to tell it what types it needs
to emit information for. But this is still an improvement for now.

No functionality change (that was the previous commit).

Swift SVN r24840
2015-01-30 03:54:08 +00:00
Jordan Rose
06f283f310 [IRGen] Always use the definition of a static inline C function.
...rather than whatever declaration happened to be referenced by a
DeclRefExpr in another function's body.

rdar://problem/18448699

Swift SVN r23877
2014-12-12 03:14:09 +00:00
Jordan Rose
ee22004b84 [IRGen] Walk inlineable Clang functions and emit their dependencies.
This handles things like NSSwapHostLongLongToBig and MKMapRectMake that
are static inline functions that themselves call other static inline
functions.

<rdar://problem/17227237>

Swift SVN r21080
2014-08-06 23:21:17 +00:00