[@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.
unsigned RefCount = 0;
/// The function's semantics attribute.
std::string SemanticsAttr;
SILFunction(SILModule &module, SILLinkage linkage,
StringRef mangledName, CanSILFunctionType loweredType,
GenericParamList *contextGenericParams,
@@ -214,6 +217,9 @@ public:
bool isGlobalInit() const { return GlobalInitFlag; }
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
/// of the function.
///

View File

@@ -40,7 +40,7 @@ const uint16_t VERSION_MAJOR = 0;
/// Serialized module format minor version number.
///
/// 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 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,
bool &isNoinline, Parser &P) {
bool &isNoinline, std::string &Semantics,
Parser &P) {
while (P.consumeIf(tok::l_square)) {
if (P.Tok.isNot(tok::identifier)) {
P.diagnose(P.Tok, diag::expected_in_attribute_list);
@@ -678,6 +679,21 @@ static bool parseDeclSILOptional(bool &isTransparent, bool &isGlobalInit,
isGlobalInit = true;
else if (P.Tok.getText() == "noinline")
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 {
P.diagnose(P.Tok, diag::expected_in_attribute_list);
return true;
@@ -2937,8 +2953,10 @@ bool Parser::parseDeclSIL() {
Scope S(this, ScopeKind::TopLevel);
bool isTransparent = false;
bool isGlobalInit = false, isNoinline = false;
std::string Semantics;
if (parseSILLinkage(FnLinkage, *this) ||
parseDeclSILOptional(isTransparent, isGlobalInit, isNoinline, *this) ||
parseDeclSILOptional(isTransparent, isGlobalInit, isNoinline, Semantics,
*this) ||
parseToken(tok::at_sign, diag::expected_sil_function_name) ||
parseIdentifier(FnName, FnNameLoc, diag::expected_sil_function_name) ||
parseToken(tok::colon, diag::expected_sil_type))
@@ -2962,6 +2980,8 @@ bool Parser::parseDeclSIL() {
FunctionState.F->setTransparent(IsTransparent_t(isTransparent));
FunctionState.F->setGlobalInit(isGlobalInit);
FunctionState.F->setNoinline(isNoinline);
if (!Semantics.empty())
FunctionState.F->setSemanticsAttr(Semantics);
// 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())
OS << "[noinline] ";
if (!getSemanticsAttr().empty())
OS << "[semantics \"" << getSemanticsAttr() << "\"] ";
printName(OS);
OS << " : $";

View File

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

View File

@@ -548,11 +548,13 @@ DeadParamCloner::initCloned(SILFunction *Orig,
assert((Orig->isTransparent() || Orig->isBare() || Orig->getDebugScope())
&& "SILFunction missing DebugScope");
assert(!Orig->isGlobalInit() && "Global initializer cannot be cloned");
return SILFunction::create(M, Orig->getLinkage(), ClonedName, ClonedTy,
Orig->getContextGenericParams(),
Orig->getLocation(), Orig->isBare(),
IsNotTransparent, Orig->isNoinline(), Orig,
Orig->getDebugScope());
auto Fn = SILFunction::create(M, Orig->getLinkage(), ClonedName, ClonedTy,
Orig->getContextGenericParams(),
Orig->getLocation(), Orig->isBare(),
IsNotTransparent, Orig->isNoinline(), Orig,
Orig->getDebugScope());
Fn->setSemanticsAttr(Orig->getSemanticsAttr());
return Fn;
}
/// \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");
assert(!Orig->isGlobalInit() && "Global initializer cannot be cloned");
// This inserts the new cloned function before the original function.
return SILFunction::create(M, Orig->getLinkage(), ClonedName, ClonedTy,
Orig->getContextGenericParams(),
Orig->getLocation(), Orig->isBare(),
IsNotTransparent, Orig->isNoinline(), Orig,
Orig->getDebugScope());
auto Fn = SILFunction::create(M, Orig->getLinkage(), ClonedName, ClonedTy,
Orig->getContextGenericParams(),
Orig->getLocation(), Orig->isBare(),
IsNotTransparent, Orig->isNoinline(), Orig,
Orig->getDebugScope());
Fn->setSemanticsAttr(Orig->getSemanticsAttr());
return Fn;
}
/// \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(),
Orig.isBare(), Orig.isTransparent(), Orig.isNoinline(),
0, Orig.getDebugScope(), Orig.getDeclContext());
NewF->setSemanticsAttr(Orig.getSemanticsAttr());
// Return our newly created F for cloning.
return NewF;

View File

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

View File

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

View File

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

View File

@@ -217,12 +217,15 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) {
<< " FnID " << FnID << "\n");
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,
toStableSILLinkage(F.getLinkage()),
(unsigned)F.isTransparent(),
(unsigned)F.isGlobalInit(),
(unsigned)F.isNoinline(),
FnID);
FnID, SemanticsID);
if (DeclOnly || F.isAvailableExternally() || F.isExternalDeclaration())
return;

View File

@@ -1111,6 +1111,13 @@ entry(%0 : $Class1):
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: #Foo.subscript!getter.1: _TC3tmp3Foo9subscriptFT1xSi1ySi_Sig
// 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 () -> ()
@noinline
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
// 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_int64_float32 : $@thin (Int, Float32) -> ()
@@ -1190,6 +1197,7 @@ bb0:
%107 = function_ref @test_assign : $@thin (Int, @inout Int) -> ()
%109 = function_ref @test_transparent : $@thin () -> ()
%130 = function_ref @noinline_callee : $@thin () -> Int
%131 = function_ref @test_semantics : $@thin () -> ()
%111 = function_ref @test_partial_apply : $@thin Float32 -> @callee_owned Int -> ()
%113 = function_ref @test_dynamic_lookup_br : $@thin (AnyObject) -> ()
%115 = function_ref @test_mark_fn_escape : $@thin () -> ()