Skip to content

Commit 3e1ea3c

Browse files
committed
[SIL] Add asmname attribute to SIL functions and global variables
The asmname attribute allows one to specify the name that will be used when lowering a given SIL declaration to LLVM IR. It is not currently exposed in the surface language. Make sure this attribute round-trips through the parser and serialization. Part of rdar://137014448O.
1 parent 232323a commit 3e1ea3c

File tree

12 files changed

+210
-20
lines changed

12 files changed

+210
-20
lines changed

docs/SIL/FunctionAttributes.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,3 +228,11 @@ Specifies that the optimizer and IRGen must not add runtime calls which
228228
are not in the function originally. This attribute is set for functions
229229
with performance constraints or functions which are called from
230230
functions with performance constraints.
231+
232+
### Naming
233+
234+
```
235+
sil-function-attribute :: '[' asmname "' identifier '" ']'
236+
```
237+
238+
Specifies that the SIL function should be lowered to LLVM IR with the given function name.

include/swift/SIL/SILFunction.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,11 @@ class SILFunction
320320
/// The function's remaining set of specialize attributes.
321321
std::vector<SILSpecializeAttr*> SpecializeAttrSet;
322322

323+
/// The name that this function should have when it is lowered to LLVM IR.
324+
///
325+
/// If empty, use the SIL function's name directly.
326+
StringRef AsmName;
327+
323328
/// Name of a section if @_section attribute was used, otherwise empty.
324329
StringRef Section;
325330

@@ -1423,6 +1428,10 @@ class SILFunction
14231428
bool markedAsUsed() const { return MarkedAsUsed; }
14241429
void setMarkedAsUsed(bool value) { MarkedAsUsed = value; }
14251430

1431+
/// Return custom assembler name, otherwise empty.
1432+
StringRef asmName() const { return AsmName; }
1433+
void setAsmName(StringRef value) { AsmName = value; }
1434+
14261435
/// Return custom section name if @_section was used, otherwise empty
14271436
StringRef section() const { return Section; }
14281437
void setSection(StringRef value) { Section = value; }

include/swift/SIL/SILGlobalVariable.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ class SILGlobalVariable
6060
/// binary. A pointer into the module's lookup table.
6161
StringRef Name;
6262

63+
/// The name that this variable should have when lowered to LLVM IR. If empty,
64+
/// the mangled name of the variable will be used instead.
65+
StringRef AsmName;
66+
6367
/// The lowered type of the variable.
6468
SILType LoweredType;
6569

@@ -150,7 +154,11 @@ class SILGlobalVariable
150154
}
151155

152156
StringRef getName() const { return Name; }
153-
157+
158+
/// Return custom assembler name, otherwise empty.
159+
StringRef asmName() const { return AsmName; }
160+
void setAsmName(StringRef value) { AsmName = value; }
161+
154162
void setDeclaration(bool isD) { IsDeclaration = isD; }
155163

156164
/// True if this is a definition of the variable.

lib/IRGen/Linking.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,10 @@ std::string LinkEntity::mangleAsString(ASTContext &Ctx) const {
408408
}
409409

410410
case Kind::SILFunction: {
411+
auto asmName = getSILFunction()->asmName();
412+
if (!asmName.empty())
413+
return asmName.str();
414+
411415
std::string Result(getSILFunction()->getName());
412416
if (isDynamicallyReplaceable()) {
413417
Result.append("TI");
@@ -465,8 +469,13 @@ std::string LinkEntity::mangleAsString(ASTContext &Ctx) const {
465469
return Result;
466470
}
467471

468-
case Kind::SILGlobalVariable:
472+
case Kind::SILGlobalVariable: {
473+
auto asmName = getSILGlobalVariable()->asmName();
474+
if (!asmName.empty())
475+
return asmName.str();
476+
469477
return getSILGlobalVariable()->getName().str();
478+
}
470479

471480
case Kind::ReadOnlyGlobalObject:
472481
return getSILGlobalVariable()->getName().str() + "r";

lib/SIL/IR/SILPrinter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3709,6 +3709,9 @@ void SILFunction::print(SILPrintContext &PrintCtx) const {
37093709
if (!section().empty())
37103710
OS << "[section \"" << section() << "\"] ";
37113711

3712+
if (!asmName().empty())
3713+
OS << "[asmname \"" << asmName() << "\"] ";
3714+
37123715
// TODO: Handle clang node owners which don't have a name.
37133716
if (hasClangNode() && getClangNodeOwner()->hasName()) {
37143717
OS << "[clang ";
@@ -3777,6 +3780,9 @@ void SILGlobalVariable::print(llvm::raw_ostream &OS, bool Verbose) const {
37773780
if (markedAsUsed())
37783781
OS << "[used] ";
37793782

3783+
if (!asmName().empty())
3784+
OS << "[asmname \"" << asmName() << "\"] ";
3785+
37803786
printName(OS);
37813787
OS << " : " << LoweredType;
37823788

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,8 @@ static bool parseDeclSILOptional(
679679
SILFunction **usedAdHocRequirementWitness, Identifier *objCReplacementFor,
680680
SILFunction::Purpose *specialPurpose, Inline_t *inlineStrategy,
681681
OptimizationMode *optimizationMode, PerformanceConstraints *perfConstraints,
682-
bool *isPerformanceConstraint, bool *markedAsUsed, StringRef *section,
682+
bool *isPerformanceConstraint, bool *markedAsUsed, StringRef *asmName,
683+
StringRef *section,
683684
bool *isLet, bool *isWeakImported, bool *needStackProtection,
684685
bool *isSpecialized, AvailabilityRange *availability,
685686
bool *isWithoutActuallyEscapingThunk,
@@ -807,6 +808,20 @@ static bool parseDeclSILOptional(
807808
}
808809
*actorIsolation = *optIsolation;
809810
SP.P.consumeToken(tok::string_literal);
811+
SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
812+
continue;
813+
} else if (asmName && SP.P.Tok.getText() == "asmname") {
814+
SP.P.consumeToken(tok::identifier);
815+
if (SP.P.Tok.getKind() != tok::string_literal) {
816+
SP.P.diagnose(SP.P.Tok, diag::expected_in_attribute_list);
817+
return true;
818+
}
819+
820+
// Drop the double quotes.
821+
StringRef rawString = SP.P.Tok.getText().drop_front().drop_back();
822+
*asmName = SP.P.Context.getIdentifier(rawString).str();
823+
SP.P.consumeToken(tok::string_literal);
824+
810825
SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
811826
continue;
812827
} else if (section && SP.P.Tok.getText() == "section") {
@@ -7288,6 +7303,7 @@ bool SILParserState::parseDeclSIL(Parser &P) {
72887303
PerformanceConstraints perfConstr = PerformanceConstraints::None;
72897304
bool isPerformanceConstraint = false;
72907305
bool markedAsUsed = false;
7306+
StringRef asmName;
72917307
StringRef section;
72927308
SmallVector<std::string, 1> Semantics;
72937309
SmallVector<ParsedSpecAttr, 4> SpecAttrs;
@@ -7306,7 +7322,7 @@ bool SILParserState::parseDeclSIL(Parser &P) {
73067322
&DynamicallyReplacedFunction, &AdHocWitnessFunction,
73077323
&objCReplacementFor, &specialPurpose, &inlineStrategy,
73087324
&optimizationMode, &perfConstr, &isPerformanceConstraint,
7309-
&markedAsUsed, &section, nullptr, &isWeakImported,
7325+
&markedAsUsed, &asmName, &section, nullptr, &isWeakImported,
73107326
&needStackProtection, nullptr, &availability,
73117327
&isWithoutActuallyEscapingThunk, &Semantics, &SpecAttrs, &ClangDecl,
73127328
&MRK, &actorIsolation, FunctionState, M) ||
@@ -7363,6 +7379,9 @@ bool SILParserState::parseDeclSIL(Parser &P) {
73637379
FunctionState.F->setPerfConstraints(perfConstr);
73647380
FunctionState.F->setIsPerformanceConstraint(isPerformanceConstraint);
73657381
FunctionState.F->setEffectsKind(MRK);
7382+
FunctionState.F->setMarkedAsUsed(markedAsUsed);
7383+
FunctionState.F->setAsmName(asmName);
7384+
FunctionState.F->setSection(section);
73667385

73677386
if (ClangDecl)
73687387
FunctionState.F->setClangNodeOwner(ClangDecl);
@@ -7557,17 +7576,18 @@ bool SILParserState::parseSILGlobal(Parser &P) {
75577576
SourceLoc NameLoc;
75587577
SerializedKind_t isSerialized = IsNotSerialized;
75597578
bool isMarkedAsUsed = false;
7579+
StringRef asmName;
75607580
bool isLet = false;
75617581

75627582
SILParser State(P);
75637583
if (parseSILLinkage(GlobalLinkage, P) ||
75647584
parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr, nullptr,
75657585
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
75667586
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7567-
nullptr, nullptr, nullptr, &isMarkedAsUsed, nullptr,
7568-
&isLet, nullptr, nullptr, nullptr, nullptr, nullptr,
7569-
nullptr, nullptr, nullptr, nullptr, nullptr, State,
7570-
M) ||
7587+
nullptr, nullptr, nullptr, &isMarkedAsUsed, &asmName,
7588+
nullptr, &isLet, nullptr, nullptr, nullptr, nullptr,
7589+
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7590+
State, M) ||
75717591
P.parseToken(tok::at_sign, diag::expected_sil_value_name) ||
75727592
P.parseIdentifier(GlobalName, NameLoc, /*diagnoseDollarPrefix=*/false,
75737593
diag::expected_sil_value_name) ||
@@ -7594,6 +7614,8 @@ bool SILParserState::parseSILGlobal(Parser &P) {
75947614

75957615
GV->setLet(isLet);
75967616
GV->setMarkedAsUsed(isMarkedAsUsed);
7617+
GV->setAsmName(asmName);
7618+
75977619
// Parse static initializer if exists.
75987620
if (State.P.consumeIf(tok::equal) && State.P.consumeIf(tok::l_brace)) {
75997621
SILBuilder B(GV);
@@ -7621,7 +7643,7 @@ bool SILParserState::parseSILProperty(Parser &P) {
76217643
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
76227644
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
76237645
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7624-
nullptr, nullptr, nullptr, nullptr, SP, M))
7646+
nullptr, nullptr, nullptr, nullptr, nullptr, SP, M))
76257647
return true;
76267648

76277649
ValueDecl *VD;
@@ -7691,7 +7713,8 @@ bool SILParserState::parseSILVTable(Parser &P) {
76917713
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
76927714
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
76937715
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7694-
nullptr, nullptr, nullptr, nullptr, VTableState, M))
7716+
nullptr, nullptr, nullptr, nullptr, nullptr,
7717+
VTableState, M))
76957718
return true;
76967719

76977720

@@ -7814,7 +7837,7 @@ bool SILParserState::parseSILMoveOnlyDeinit(Parser &parser) {
78147837
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
78157838
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
78167839
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7817-
nullptr, nullptr, nullptr, nullptr,
7840+
nullptr, nullptr, nullptr, nullptr, nullptr,
78187841
moveOnlyDeinitTableState, M))
78197842
return true;
78207843

@@ -8359,8 +8382,9 @@ bool SILParserState::parseSILWitnessTable(Parser &P) {
83598382
nullptr, &isSerialized, nullptr, nullptr, nullptr, nullptr, nullptr,
83608383
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
83618384
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
8362-
nullptr, nullptr, nullptr, nullptr, &isSpecialized, nullptr, nullptr,
8363-
nullptr, nullptr, nullptr, nullptr, nullptr, WitnessState, M))
8385+
nullptr, nullptr, nullptr, nullptr, nullptr, &isSpecialized,
8386+
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
8387+
WitnessState, M))
83648388
return true;
83658389

83668390
// Parse the protocol conformance.

lib/Serialization/DeserializeSIL.cpp

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,9 @@ llvm::Expected<SILFunction *> SILDeserializer::readSILFunctionChecked(
984984
assert(next.Kind == llvm::BitstreamEntry::Record);
985985

986986
scratch.clear();
987-
llvm::Expected<unsigned> maybeKind = SILCursor.readRecord(next.ID, scratch);
987+
StringRef blobData;
988+
llvm::Expected<unsigned> maybeKind = SILCursor.readRecord(next.ID, scratch,
989+
&blobData);
988990
if (!maybeKind)
989991
return maybeKind.takeError();
990992
unsigned kind = maybeKind.get();
@@ -1010,6 +1012,18 @@ llvm::Expected<SILFunction *> SILDeserializer::readSILFunctionChecked(
10101012
continue;
10111013
}
10121014

1015+
if (kind == SIL_EXTRA_STRING) {
1016+
unsigned stringFlavor;
1017+
SILExtraStringLayout::readRecord(scratch, stringFlavor);
1018+
1019+
switch (static_cast<ExtraStringFlavor>(stringFlavor)) {
1020+
case ExtraStringFlavor::AsmName:
1021+
fn->setAsmName(blobData);
1022+
break;
1023+
}
1024+
continue;
1025+
}
1026+
10131027
assert(kind == SIL_SPECIALIZE_ATTR && "Missing specialization attribute");
10141028

10151029
unsigned exported;
@@ -4080,8 +4094,10 @@ SILGlobalVariable *SILDeserializer::readGlobalVar(StringRef Name) {
40804094
DeclID dID;
40814095
ModuleID parentModuleID;
40824096
unsigned rawLinkage, serializedKind, IsDeclaration, IsLet, IsUsed;
4097+
unsigned numTrailingRecords;
40834098
SILGlobalVarLayout::readRecord(scratch, rawLinkage, serializedKind,
4084-
IsDeclaration, IsLet, IsUsed, TyID, dID,
4099+
IsDeclaration, IsLet, IsUsed,
4100+
numTrailingRecords, TyID, dID,
40854101
parentModuleID);
40864102
if (TyID == 0) {
40874103
LLVM_DEBUG(llvm::dbgs() << "SILGlobalVariable typeID is 0.\n");
@@ -4124,6 +4140,39 @@ SILGlobalVariable *SILDeserializer::readGlobalVar(StringRef Name) {
41244140
Callback->didDeserialize(MF->getAssociatedModule(), v);
41254141

41264142
scratch.clear();
4143+
4144+
// Read trailing reecords.
4145+
for (unsigned recordIdx = 0; recordIdx < numTrailingRecords; ++recordIdx) {
4146+
StringRef blobData;
4147+
llvm::Expected<llvm::BitstreamEntry> maybeNext =
4148+
SILCursor.advance(AF_DontPopBlockAtEnd);
4149+
if (!maybeNext)
4150+
return nullptr;
4151+
llvm::BitstreamEntry next = maybeNext.get();
4152+
assert(next.Kind == llvm::BitstreamEntry::Record);
4153+
4154+
scratch.clear();
4155+
llvm::Expected<unsigned> maybeKind = SILCursor.readRecord(next.ID, scratch,
4156+
&blobData);
4157+
if (!maybeKind)
4158+
return nullptr;
4159+
unsigned kind = maybeKind.get();
4160+
4161+
if (kind == SIL_EXTRA_STRING) {
4162+
unsigned stringFlavor;
4163+
SILExtraStringLayout::readRecord(scratch, stringFlavor);
4164+
4165+
switch (static_cast<ExtraStringFlavor>(stringFlavor)) {
4166+
case ExtraStringFlavor::AsmName:
4167+
v->setAsmName(blobData);
4168+
break;
4169+
}
4170+
continue;
4171+
}
4172+
4173+
return nullptr;
4174+
}
4175+
41274176
maybeEntry = SILCursor.advance(AF_DontPopBlockAtEnd);
41284177
if (!maybeEntry)
41294178
MF->fatal(maybeEntry.takeError());

lib/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 965; // WriteImplKindField and ReadWriteImplKindField size
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 966; // SIL asmname
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///

lib/Serialization/SILFormat.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ enum class KeyPathComputedComponentIdKindEncoding : uint8_t {
8181
DeclRef,
8282
};
8383

84+
enum class ExtraStringFlavor : uint8_t {
85+
/// asmname attributes
86+
AsmName,
87+
};
88+
8489
/// The record types within the "sil-index" block.
8590
///
8691
/// \sa SIL_INDEX_BLOCK_ID
@@ -186,6 +191,7 @@ namespace sil_block {
186191
SIL_SOURCE_LOC_REF,
187192
SIL_DEBUG_VALUE_DELIMITER,
188193
SIL_DEBUG_VALUE,
194+
SIL_EXTRA_STRING,
189195
};
190196

191197
using SILInstNoOperandLayout = BCRecordLayout<
@@ -295,6 +301,7 @@ namespace sil_block {
295301
BCFixed<1>, // Is this a declaration.
296302
BCFixed<1>, // Is this a let variable.
297303
BCFixed<1>, // Is this marked as "used".
304+
BCVBR<8>, // # of trailing records
298305
TypeIDField,
299306
DeclIDField,
300307
ModuleIDField // Parent ModuleDecl *
@@ -378,7 +385,7 @@ namespace sil_block {
378385
BCFixed<1>, // hasCReferences
379386
BCFixed<1>, // markedAsUsed
380387
BCFixed<3>, // side effect info.
381-
BCVBR<8>, // number of specialize attributes
388+
BCVBR<8>, // number of trailing records
382389
BCFixed<1>, // has qualified ownership
383390
BCFixed<1>, // force weak linking
384391
BC_AVAIL_TUPLE, // availability for weak linking
@@ -419,6 +426,14 @@ namespace sil_block {
419426
BCFixed<1> // isDerived
420427
>;
421428

429+
/// Used for additional strings that can be associated with a record,
430+
/// written out as records that trail
431+
using SILExtraStringLayout =
432+
BCRecordLayout<SIL_EXTRA_STRING,
433+
BCFixed<8>, // string flavor
434+
BCBlob // string data
435+
>;
436+
422437
// Has an optional argument list where each argument is a typed valueref.
423438
using SILBasicBlockLayout = BCRecordLayout<
424439
SIL_BASIC_BLOCK,

0 commit comments

Comments
 (0)