Skip to content

Commit f267f62

Browse files
committed
[SILGen] Consistently use SIL asmname for foreign function/variable references
Whenever we have a reference to a foreign function/variable in SIL, use a mangled name at the SIL level with the C name in the asmname attribute. The expands the use of asmname to three kinds of cases that it hadn't been used in yet: * Declarations imported from C headers/modules * @_cdecl @implementation of C headers/modules * @_cdecl functions in general Some code within the SIL pipeline makes assumptions that the C names of various runtime functions are reflected at the SIL level. For example, the linking of Embedded Swift runtime functions is done by-name, and some of those names refer to C functions (like `swift_retain`) and others refer to Swift functions that use `@_silgen_name` (like `swift_getDefaultExecutor`). Extend the serialized module format to include a table that maps from the asmname of functions/variables over to their mangled names, so we can look up functions by asmname if we want. These tables could also be used for checking for declarations that conflict on their asmname in the future. Right now, we leave it up to LLVM or the linker to do the checking. `@_silgen_name` is not affected by these changes, nor should it be: that hidden feature is specifically meant to affect the name at the SIL level. The vast majority of test changes are SIL tests where we had expected to see the C/C++/Objective-C names in the tests for references to foreign entities, and now we see Swift mangled names (ending in To). The SIL declarations themselves will have a corresponding asmname. Notably, the IRGen tests have *not* changed, because we generally the same IR as before. It's only the modeling at the SIL lever that has changed. Another part of rdar://137014448.
1 parent 778281a commit f267f62

File tree

81 files changed

+674
-439
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+674
-439
lines changed

include/swift/AST/Attr.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3126,8 +3126,8 @@ class ExternAttr : public DeclAttribute {
31263126
}
31273127

31283128
/// Returns the C name of the given declaration.
3129-
/// \p forDecl is the func decl that the attribute belongs to.
3130-
StringRef getCName(const FuncDecl *forDecl) const;
3129+
/// \p forDecl is the decl that the attribute belongs to.
3130+
StringRef getCName(const ValueDecl *forDecl) const;
31313131

31323132
/// Find an ExternAttr with the given kind in the given DeclAttributes.
31333133
static const ExternAttr *find(const DeclAttributes &attrs, ExternKind kind);

include/swift/SIL/SILDeclRef.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ struct SILDeclRef {
335335

336336
/// If the symbol has a specific name for use at the LLVM IR level,
337337
/// produce that name. This may be different than the mangled name in SIL.
338-
std::optional<StringRef> getAsmName() const;
338+
std::optional<std::string> getAsmName() const;
339339

340340
/// True if the SILDeclRef references a function.
341341
bool isFunc() const {

include/swift/SIL/SILFunction.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1430,7 +1430,7 @@ class SILFunction
14301430

14311431
/// Return custom assembler name, otherwise empty.
14321432
StringRef asmName() const { return AsmName; }
1433-
void setAsmName(StringRef value) { AsmName = value; }
1433+
void setAsmName(StringRef value);
14341434

14351435
/// Return custom section name if @section was used, otherwise empty
14361436
StringRef section() const { return Section; }

include/swift/SIL/SILGlobalVariable.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ class SILGlobalVariable
160160

161161
/// Return custom assembler name, otherwise empty.
162162
StringRef asmName() const { return AsmName; }
163-
void setAsmName(StringRef value) { AsmName = value; }
163+
void setAsmName(StringRef value);
164164

165165
/// Return custom section name if @section was used, otherwise empty
166166
StringRef section() const { return Section; }

include/swift/SIL/SILModule.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,10 @@ class SILModule {
235235
llvm::StringMap<SILFunction *> FunctionTable;
236236
llvm::StringMap<SILFunction *> ZombieFunctionTable;
237237

238+
/// Lookup table for SIL functions by their asmnames, for those that
239+
/// have them.
240+
llvm::StringMap<SILFunction *> FunctionByAsmNameTable;
241+
238242
/// The list of SILFunctions in the module.
239243
FunctionListType functions;
240244

@@ -310,6 +314,9 @@ class SILModule {
310314
/// Lookup table for SIL Global Variables.
311315
llvm::StringMap<SILGlobalVariable *> GlobalVariableMap;
312316

317+
/// Lookup table for SIL Global Variables, indexed by their asmnames.
318+
llvm::StringMap<SILGlobalVariable *> GlobalVariableByAsmNameMap;
319+
313320
/// The list of SILGlobalVariables in the module.
314321
GlobalListType silGlobals;
315322

@@ -822,14 +829,20 @@ class SILModule {
822829
/// Look for a global variable by name.
823830
///
824831
/// \return null if this module has no such global variable
825-
SILGlobalVariable *lookUpGlobalVariable(StringRef name) const {
832+
SILGlobalVariable *lookUpGlobalVariable(StringRef name,
833+
bool byAsmName = false) const {
834+
if (byAsmName)
835+
return GlobalVariableByAsmNameMap.lookup(name);
836+
826837
return GlobalVariableMap.lookup(name);
827838
}
828839

829840
/// Look for a function by name.
830841
///
831842
/// \return null if this module has no such function
832-
SILFunction *lookUpFunction(StringRef name) const {
843+
SILFunction *lookUpFunction(StringRef name, bool byAsmName = false) const {
844+
if (byAsmName)
845+
return FunctionByAsmNameTable.lookup(name);
833846
return FunctionTable.lookup(name);
834847
}
835848

include/swift/Serialization/SerializedSILLoader.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,10 @@ class SerializedSILLoader {
6262

6363
SILFunction *lookupSILFunction(SILFunction *Callee, bool onlyUpdateLinkage);
6464
SILFunction *lookupSILFunction(StringRef Name,
65-
std::optional<SILLinkage> linkage);
66-
SILGlobalVariable *lookupSILGlobalVariable(StringRef Name);
65+
std::optional<SILLinkage> linkage,
66+
bool byAsmName = false);
67+
SILGlobalVariable *lookupSILGlobalVariable(StringRef Name,
68+
bool byAsmName = false);
6769
bool hasSILFunction(StringRef Name,
6870
std::optional<SILLinkage> linkage = std::nullopt);
6971
SILVTable *lookupVTable(const ClassDecl *C);

lib/AST/Attr.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3273,11 +3273,11 @@ bool MacroRoleAttr::hasNameKind(MacroIntroducedDeclNameKind kind) const {
32733273
}) != getNames().end();
32743274
}
32753275

3276-
StringRef ExternAttr::getCName(const FuncDecl *D) const {
3276+
StringRef ExternAttr::getCName(const ValueDecl *D) const {
32773277
if (auto cName = this->Name)
32783278
return cName.value();
32793279
// If no name was specified, fall back on the Swift base name without mangling.
3280-
// Base name is always available and non-empty for FuncDecl.
3280+
// Base name is always available and non-empty for functions and variables.
32813281
return D->getBaseIdentifier().str();
32823282
}
32833283

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 27 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1386,18 +1386,6 @@ std::string SILDeclRef::mangle(ManglingKind MKind) const {
13861386
silConfig);
13871387
}
13881388

1389-
// As a special case, Clang functions and globals don't get mangled at all
1390-
// - except \c objc_direct decls.
1391-
if (hasDecl() && !isDefaultArgGenerator()) {
1392-
if (getDecl()->getClangDecl()) {
1393-
if (!isForeignToNativeThunk() && !isNativeToForeignThunk()) {
1394-
auto clangMangling = mangleClangDecl(getDecl(), isForeign);
1395-
if (!clangMangling.empty())
1396-
return clangMangling;
1397-
}
1398-
}
1399-
}
1400-
14011389
// Mangle prespecializations.
14021390
if (getSpecializedSignature()) {
14031391
SILDeclRef nonSpecializedDeclRef = *this;
@@ -1443,23 +1431,6 @@ std::string SILDeclRef::mangle(ManglingKind MKind) const {
14431431
return NameA->Name.str();
14441432
}
14451433

1446-
// Use a given cdecl name for native-to-foreign thunks. Don't do this
1447-
// for functions that only have a C entrypoint.
1448-
if (getDecl()->getAttrs().hasAttribute<CDeclAttr>() &&
1449-
!(getDecl()->hasOnlyCEntryPoint() &&
1450-
!getDecl()->getImplementedObjCDecl())) {
1451-
if (isNativeToForeignThunk() || isForeign) {
1452-
// If this is an @implementation @_cdecl, mangle it like the clang
1453-
// function it implements.
1454-
if (auto objcInterface = getDecl()->getImplementedObjCDecl()) {
1455-
auto clangMangling = mangleClangDecl(objcInterface, isForeign);
1456-
if (!clangMangling.empty())
1457-
return clangMangling;
1458-
}
1459-
return getDecl()->getCDeclName().str();
1460-
}
1461-
}
1462-
14631434
if (SKind == ASTMangler::SymbolKind::DistributedThunk) {
14641435
return mangler.mangleDistributedThunk(cast<FuncDecl>(getDecl()));
14651436
}
@@ -1547,13 +1518,33 @@ std::string SILDeclRef::mangle(ManglingKind MKind) const {
15471518
llvm_unreachable("bad entity kind!");
15481519
}
15491520

1550-
std::optional<StringRef> SILDeclRef::getAsmName() const {
1551-
if (isForeign && isFunc()) {
1552-
auto func = getFuncDecl();
1553-
if (auto *EA = ExternAttr::find(func->getAttrs(), ExternKind::C))
1554-
return EA->getCName(func);
1555-
if (func->hasOnlyCEntryPoint() && !func->getImplementedObjCDecl())
1556-
return func->getCDeclName();
1521+
std::optional<std::string> SILDeclRef::getAsmName() const {
1522+
if (isAutoDiffDerivativeFunction())
1523+
return std::nullopt;
1524+
1525+
if (hasDecl() && !isDefaultArgGenerator() &&
1526+
(getDecl()->getClangDecl() || getDecl()->getImplementedObjCDecl())) {
1527+
// If there is a Clang declaration, use its mangled name.
1528+
if (isNativeToForeignThunk() || isForeign) {
1529+
auto decl = getDecl();
1530+
auto hasClangDecl = decl->getClangDecl()
1531+
? decl : decl->getImplementedObjCDecl();
1532+
auto clangMangling = mangleClangDecl(hasClangDecl, isForeign);
1533+
if (!clangMangling.empty())
1534+
return clangMangling;
1535+
}
1536+
}
1537+
1538+
if (isForeign && hasDecl()) {
1539+
// @_extern(c)
1540+
auto decl = getDecl();
1541+
if (auto *EA = ExternAttr::find(decl->getAttrs(), ExternKind::C))
1542+
if (auto VD = dyn_cast<ValueDecl>(decl))
1543+
return std::string(EA->getCName(VD));
1544+
1545+
// @c/@_cdecl
1546+
if (decl->getAttrs().hasAttribute<CDeclAttr>())
1547+
return std::string(decl->getCDeclName());
15571548
}
15581549

15591550
return std::nullopt;

lib/SIL/IR/SILFunction.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,16 @@ bool SILFunction::hasForeignBody() const {
442442
return SILDeclRef::isClangGenerated(getClangNode());
443443
}
444444

445+
void SILFunction::setAsmName(StringRef value) {
446+
assert((AsmName.empty() || value == AsmName) && "Cannot change asmname");
447+
AsmName = value;
448+
449+
if (!value.empty()) {
450+
// Update the function-by-asm-name-table.
451+
getModule().FunctionByAsmNameTable.insert({AsmName, this});
452+
}
453+
}
454+
445455
const SILFunction *SILFunction::getOriginOfSpecialization() const {
446456
if (!isSpecialization())
447457
return nullptr;
@@ -1049,7 +1059,8 @@ bool SILFunction::isSwiftRuntimeFunction(
10491059
}
10501060

10511061
bool SILFunction::isSwiftRuntimeFunction() const {
1052-
return isSwiftRuntimeFunction(getName(), getParentModule());
1062+
return isSwiftRuntimeFunction(asmName(), getParentModule()) ||
1063+
isSwiftRuntimeFunction(getName(), getParentModule());
10531064
}
10541065

10551066
bool

lib/SIL/IR/SILFunctionBuilder.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ void SILFunctionBuilder::addFunctionAttributes(
128128
}
129129

130130
if (auto asmName = constant.getAsmName()) {
131-
F->setAsmName(*asmName);
131+
F->setAsmName(M.getASTContext().AllocateCopy(*asmName));
132132
}
133133
}
134134

@@ -177,16 +177,18 @@ void SILFunctionBuilder::addFunctionAttributes(
177177
if (Attrs.hasAttribute<CDeclAttr>()) {
178178
// If the function is marked with @c, expose only C compatible
179179
// thunk function.
180-
shouldExportDecl = constant.isNativeToForeignThunk();
180+
shouldExportDecl = constant.isNativeToForeignThunk() || constant.isForeign;
181181
}
182182
if (EA->getExposureKind() == ExposureKind::Wasm && shouldExportDecl) {
183183
// A wasm-level exported function must be retained if it appears in a
184184
// compilation unit.
185185
F->setMarkedAsUsed(true);
186-
if (EA->Name.empty())
187-
F->setWasmExportName(F->getName());
188-
else
186+
if (!EA->Name.empty())
189187
F->setWasmExportName(EA->Name);
188+
else if (!F->asmName().empty())
189+
F->setWasmExportName(F->asmName());
190+
else
191+
F->setWasmExportName(F->getName());
190192
}
191193
}
192194

0 commit comments

Comments
 (0)