[@semantics] add SemanticsAttr to SILFunction.

Enable SIL parsing and SIL serialization of semantics.

We add one more field to SILFunctionLayout for semantics. We should refactor
handling of attributes at SIL level, right now they are in SILFunction as bool
or std::string and in SIL serializer as a 1-bit field or an ID field.

rdar://17525564


Swift SVN r19434
This commit is contained in:
Manman Ren
2014-07-01 22:49:46 +00:00
parent 7dae30f755
commit ae9f2e25ae
15 changed files with 81 additions and 16 deletions

View File

@@ -91,6 +91,9 @@ private:
/// This is the number of uses of this SILFunction. /// This is the number of uses of this SILFunction.
unsigned RefCount = 0; unsigned RefCount = 0;
/// The function's semantics attribute.
std::string SemanticsAttr;
SILFunction(SILModule &module, SILLinkage linkage, SILFunction(SILModule &module, SILLinkage linkage,
StringRef mangledName, CanSILFunctionType loweredType, StringRef mangledName, CanSILFunctionType loweredType,
GenericParamList *contextGenericParams, GenericParamList *contextGenericParams,
@@ -214,6 +217,9 @@ public:
bool isGlobalInit() const { return GlobalInitFlag; } bool isGlobalInit() const { return GlobalInitFlag; }
void setGlobalInit(bool isGI) { GlobalInitFlag = isGI; } void setGlobalInit(bool isGI) { GlobalInitFlag = isGI; }
StringRef getSemanticsAttr() const { return SemanticsAttr; }
void setSemanticsAttr(StringRef attr) { SemanticsAttr = attr; }
/// Retrieve the generic parameter list containing the contextual archetypes /// Retrieve the generic parameter list containing the contextual archetypes
/// of the function. /// of the function.
/// ///

View File

@@ -40,7 +40,7 @@ const uint16_t VERSION_MAJOR = 0;
/// Serialized module format minor version number. /// Serialized module format minor version number.
/// ///
/// When the format changes IN ANY WAY, this number should be incremented. /// When the format changes IN ANY WAY, this number should be incremented.
const uint16_t VERSION_MINOR = 109; const uint16_t VERSION_MINOR = 110;
using DeclID = Fixnum<31>; using DeclID = Fixnum<31>;
using DeclIDField = BCFixed<31>; using DeclIDField = BCFixed<31>;

View File

@@ -667,7 +667,8 @@ static bool parseSILOptional(bool &Result, SILParser &SP, StringRef Expected) {
} }
static bool parseDeclSILOptional(bool &isTransparent, bool &isGlobalInit, static bool parseDeclSILOptional(bool &isTransparent, bool &isGlobalInit,
bool &isNoinline, Parser &P) { bool &isNoinline, std::string &Semantics,
Parser &P) {
while (P.consumeIf(tok::l_square)) { while (P.consumeIf(tok::l_square)) {
if (P.Tok.isNot(tok::identifier)) { if (P.Tok.isNot(tok::identifier)) {
P.diagnose(P.Tok, diag::expected_in_attribute_list); P.diagnose(P.Tok, diag::expected_in_attribute_list);
@@ -678,6 +679,21 @@ static bool parseDeclSILOptional(bool &isTransparent, bool &isGlobalInit,
isGlobalInit = true; isGlobalInit = true;
else if (P.Tok.getText() == "noinline") else if (P.Tok.getText() == "noinline")
isNoinline = true; isNoinline = true;
else if (P.Tok.getText() == "semantics") {
P.consumeToken(tok::identifier);
if (P.Tok.getKind() != tok::string_literal) {
P.diagnose(P.Tok, diag::expected_in_attribute_list);
return true;
}
// Drop the double quotes.
StringRef rawString = P.Tok.getText().drop_front().drop_back();
Semantics = rawString;
P.consumeToken(tok::string_literal);
P.parseToken(tok::r_square, diag::expected_in_attribute_list);
continue;
}
else { else {
P.diagnose(P.Tok, diag::expected_in_attribute_list); P.diagnose(P.Tok, diag::expected_in_attribute_list);
return true; return true;
@@ -2937,8 +2953,10 @@ bool Parser::parseDeclSIL() {
Scope S(this, ScopeKind::TopLevel); Scope S(this, ScopeKind::TopLevel);
bool isTransparent = false; bool isTransparent = false;
bool isGlobalInit = false, isNoinline = false; bool isGlobalInit = false, isNoinline = false;
std::string Semantics;
if (parseSILLinkage(FnLinkage, *this) || if (parseSILLinkage(FnLinkage, *this) ||
parseDeclSILOptional(isTransparent, isGlobalInit, isNoinline, *this) || parseDeclSILOptional(isTransparent, isGlobalInit, isNoinline, Semantics,
*this) ||
parseToken(tok::at_sign, diag::expected_sil_function_name) || parseToken(tok::at_sign, diag::expected_sil_function_name) ||
parseIdentifier(FnName, FnNameLoc, diag::expected_sil_function_name) || parseIdentifier(FnName, FnNameLoc, diag::expected_sil_function_name) ||
parseToken(tok::colon, diag::expected_sil_type)) parseToken(tok::colon, diag::expected_sil_type))
@@ -2962,6 +2980,8 @@ bool Parser::parseDeclSIL() {
FunctionState.F->setTransparent(IsTransparent_t(isTransparent)); FunctionState.F->setTransparent(IsTransparent_t(isTransparent));
FunctionState.F->setGlobalInit(isGlobalInit); FunctionState.F->setGlobalInit(isGlobalInit);
FunctionState.F->setNoinline(isNoinline); FunctionState.F->setNoinline(isNoinline);
if (!Semantics.empty())
FunctionState.F->setSemanticsAttr(Semantics);
// Now that we have a SILFunction parse the body, if present. // Now that we have a SILFunction parse the body, if present.

View File

@@ -1308,6 +1308,9 @@ void SILFunction::print(llvm::raw_ostream &OS, bool Verbose) const {
if (isNoinline()) if (isNoinline())
OS << "[noinline] "; OS << "[noinline] ";
if (!getSemanticsAttr().empty())
OS << "[semantics \"" << getSemanticsAttr() << "\"] ";
printName(OS); printName(OS);
OS << " : $"; OS << " : $";

View File

@@ -271,6 +271,10 @@ SILFunction *SILGenModule::getFunction(SILDeclRef constant,
constant.isNoinline()); constant.isNoinline());
F->setGlobalInit(constant.isGlobal()); F->setGlobalInit(constant.isGlobal());
if (constant.hasDecl())
if (auto SemanticsA =
constant.getDecl()->getAttrs().getAttribute<SemanticsAttr>())
F->setSemanticsAttr(SemanticsA->Value);
ValueDecl *VD = nullptr; ValueDecl *VD = nullptr;
if (constant.hasDecl()) if (constant.hasDecl())

View File

@@ -548,11 +548,13 @@ DeadParamCloner::initCloned(SILFunction *Orig,
assert((Orig->isTransparent() || Orig->isBare() || Orig->getDebugScope()) assert((Orig->isTransparent() || Orig->isBare() || Orig->getDebugScope())
&& "SILFunction missing DebugScope"); && "SILFunction missing DebugScope");
assert(!Orig->isGlobalInit() && "Global initializer cannot be cloned"); assert(!Orig->isGlobalInit() && "Global initializer cannot be cloned");
return SILFunction::create(M, Orig->getLinkage(), ClonedName, ClonedTy, auto Fn = SILFunction::create(M, Orig->getLinkage(), ClonedName, ClonedTy,
Orig->getContextGenericParams(), Orig->getContextGenericParams(),
Orig->getLocation(), Orig->isBare(), Orig->getLocation(), Orig->isBare(),
IsNotTransparent, Orig->isNoinline(), Orig, IsNotTransparent, Orig->isNoinline(), Orig,
Orig->getDebugScope()); Orig->getDebugScope());
Fn->setSemanticsAttr(Orig->getSemanticsAttr());
return Fn;
} }
/// \brief Populate the body of the cloned closure, modifying instructions as /// \brief Populate the body of the cloned closure, modifying instructions as

View File

@@ -320,11 +320,13 @@ ClosureCloner::initCloned(SILFunction *Orig, IndicesSet &PromotableIndices) {
&& "SILFunction missing DebugScope"); && "SILFunction missing DebugScope");
assert(!Orig->isGlobalInit() && "Global initializer cannot be cloned"); assert(!Orig->isGlobalInit() && "Global initializer cannot be cloned");
// This inserts the new cloned function before the original function. // This inserts the new cloned function before the original function.
return SILFunction::create(M, Orig->getLinkage(), ClonedName, ClonedTy, auto Fn = SILFunction::create(M, Orig->getLinkage(), ClonedName, ClonedTy,
Orig->getContextGenericParams(), Orig->getContextGenericParams(),
Orig->getLocation(), Orig->isBare(), Orig->getLocation(), Orig->isBare(),
IsNotTransparent, Orig->isNoinline(), Orig, IsNotTransparent, Orig->isNoinline(), Orig,
Orig->getDebugScope()); Orig->getDebugScope());
Fn->setSemanticsAttr(Orig->getSemanticsAttr());
return Fn;
} }
/// \brief Populate the body of the cloned closure, modifying instructions as /// \brief Populate the body of the cloned closure, modifying instructions as

View File

@@ -250,6 +250,7 @@ SILFunction *FunctionSignatureOptCloner::initCloned(
M, OptimizedLinkage, NewName, NewFTy, nullptr, Orig.getLocation(), M, OptimizedLinkage, NewName, NewFTy, nullptr, Orig.getLocation(),
Orig.isBare(), Orig.isTransparent(), Orig.isNoinline(), Orig.isBare(), Orig.isTransparent(), Orig.isNoinline(),
0, Orig.getDebugScope(), Orig.getDeclContext()); 0, Orig.getDebugScope(), Orig.getDeclContext());
NewF->setSemanticsAttr(Orig.getSemanticsAttr());
// Return our newly created F for cloning. // Return our newly created F for cloning.
return NewF; return NewF;

View File

@@ -94,6 +94,7 @@ SILFunction *SpecializingCloner::initCloned(SILFunction *Orig,
Orig->getLocation(), Orig->isBare(), Orig->getLocation(), Orig->isBare(),
Orig->isTransparent(), Orig->isNoinline(), 0, Orig->isTransparent(), Orig->isNoinline(), 0,
Orig->getDebugScope(), Orig->getDeclContext()); Orig->getDebugScope(), Orig->getDeclContext());
NewF->setSemanticsAttr(Orig->getSemanticsAttr());
NumSpecialized++; NumSpecialized++;
return NewF; return NewF;

View File

@@ -366,8 +366,9 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID,
TypeID funcTyID; TypeID funcTyID;
unsigned rawLinkage, isTransparent, isGlobal, isNoinline; unsigned rawLinkage, isTransparent, isGlobal, isNoinline;
IdentifierID SemanticsID;
SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isGlobal, SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isGlobal,
isNoinline, funcTyID); isNoinline, funcTyID, SemanticsID);
if (funcTyID == 0) { if (funcTyID == 0) {
DEBUG(llvm::dbgs() << "SILFunction typeID is 0.\n"); DEBUG(llvm::dbgs() << "SILFunction typeID is 0.\n");
@@ -416,6 +417,8 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID,
fn->setTransparent(IsTransparent_t(isTransparent == 1)); fn->setTransparent(IsTransparent_t(isTransparent == 1));
fn->setGlobalInit(isGlobal == 1); fn->setGlobalInit(isGlobal == 1);
fn->setNoinline(isNoinline == 1); fn->setNoinline(isNoinline == 1);
if (SemanticsID)
fn->setSemanticsAttr(MF->getIdentifier(SemanticsID).str());
if (Callback) Callback->didDeserialize(MF->getAssociatedModule(), fn); if (Callback) Callback->didDeserialize(MF->getAssociatedModule(), fn);
} }

View File

@@ -216,7 +216,8 @@ namespace sil_block {
BCFixed<1>, // transparent BCFixed<1>, // transparent
BCFixed<1>, // global_init BCFixed<1>, // global_init
BCFixed<1>, // noinline BCFixed<1>, // noinline
TypeIDField TypeIDField,
IdentifierIDField // Semantics Attribute
// followed by generic param list, if any // followed by generic param list, if any
>; >;

View File

@@ -217,12 +217,15 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) {
<< " FnID " << FnID << "\n"); << " FnID " << FnID << "\n");
DEBUG(llvm::dbgs() << "Serialized SIL:\n"; F.dump()); DEBUG(llvm::dbgs() << "Serialized SIL:\n"; F.dump());
IdentifierID SemanticsID =
F.getSemanticsAttr().empty() ? (IdentifierID)0 :
S.addIdentifierRef(Ctx.getIdentifier(F.getSemanticsAttr()));
SILFunctionLayout::emitRecord(Out, ScratchRecord, abbrCode, SILFunctionLayout::emitRecord(Out, ScratchRecord, abbrCode,
toStableSILLinkage(F.getLinkage()), toStableSILLinkage(F.getLinkage()),
(unsigned)F.isTransparent(), (unsigned)F.isTransparent(),
(unsigned)F.isGlobalInit(), (unsigned)F.isGlobalInit(),
(unsigned)F.isNoinline(), (unsigned)F.isNoinline(),
FnID); FnID, SemanticsID);
if (DeclOnly || F.isAvailableExternally() || F.isExternalDeclaration()) if (DeclOnly || F.isAvailableExternally() || F.isExternalDeclaration())
return; return;

View File

@@ -1111,6 +1111,13 @@ entry(%0 : $Class1):
return %3 : $(Class2, Int) return %3 : $(Class2, Int)
} }
// CHECK-LABEL: sil [semantics "foo"] @test_semantics : $@thin () -> () {
sil [semantics "foo"] @test_semantics : $@thin () -> () {
bb0:
%0 = tuple ()
return %0 : $()
}
// CHECK-LABEL: sil_vtable Foo { // CHECK-LABEL: sil_vtable Foo {
// CHECK: #Foo.subscript!getter.1: _TC3tmp3Foo9subscriptFT1xSi1ySi_Sig // CHECK: #Foo.subscript!getter.1: _TC3tmp3Foo9subscriptFT1xSi1ySi_Sig
// CHECK: #Foo.subscript!setter.1: _TC3tmp3Foo9subscriptFT1xSi1ySi_Sis // CHECK: #Foo.subscript!setter.1: _TC3tmp3Foo9subscriptFT1xSi1ySi_Sis

View File

@@ -525,3 +525,7 @@ func blockToFunc(x: @objc_block () -> ()) -> () -> () {
// CHECK-LABEL: sil [noinline] @_TF9functions15noinline_calleeFT_T_ : $@thin () -> () // CHECK-LABEL: sil [noinline] @_TF9functions15noinline_calleeFT_T_ : $@thin () -> ()
@noinline @noinline
func noinline_callee() {} func noinline_callee() {}
// CHECK-LABEL: sil [semantics "foo"] @_TF9functions9semanticsFT_T_ : $@thin () -> ()
@semantics("foo")
func semantics() {}

View File

@@ -818,6 +818,13 @@ bb0:
} }
sil [transparent] @_TFSi33_convertFromBuiltinIntegerLiteralfMSiFBi2048_Si : $@thin (Builtin.Int2048, @thin Int.Type) -> Int sil [transparent] @_TFSi33_convertFromBuiltinIntegerLiteralfMSiFBi2048_Si : $@thin (Builtin.Int2048, @thin Int.Type) -> Int
// CHECK-LABEL: [semantics "foo"] @test_semantics : $@thin () -> ()
sil [semantics "foo"] @test_semantics : $@thin () -> () {
bb0:
%2 = tuple ()
%3 = return %2 : $()
}
sil @takes_unnamed_closure : $@thin (@callee_owned () -> Int) -> @callee_owned () -> @callee_owned () -> Int sil @takes_unnamed_closure : $@thin (@callee_owned () -> Int) -> @callee_owned () -> @callee_owned () -> Int
sil @takes_int64_float32 : $@thin (Int, Float32) -> () sil @takes_int64_float32 : $@thin (Int, Float32) -> ()
@@ -1190,6 +1197,7 @@ bb0:
%107 = function_ref @test_assign : $@thin (Int, @inout Int) -> () %107 = function_ref @test_assign : $@thin (Int, @inout Int) -> ()
%109 = function_ref @test_transparent : $@thin () -> () %109 = function_ref @test_transparent : $@thin () -> ()
%130 = function_ref @noinline_callee : $@thin () -> Int %130 = function_ref @noinline_callee : $@thin () -> Int
%131 = function_ref @test_semantics : $@thin () -> ()
%111 = function_ref @test_partial_apply : $@thin Float32 -> @callee_owned Int -> () %111 = function_ref @test_partial_apply : $@thin Float32 -> @callee_owned Int -> ()
%113 = function_ref @test_dynamic_lookup_br : $@thin (AnyObject) -> () %113 = function_ref @test_dynamic_lookup_br : $@thin (AnyObject) -> ()
%115 = function_ref @test_mark_fn_escape : $@thin () -> () %115 = function_ref @test_mark_fn_escape : $@thin () -> ()