mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[@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:
@@ -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.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -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>;
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -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 << " : $";
|
||||||
|
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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() {}
|
||||||
|
|||||||
@@ -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 () -> ()
|
||||||
|
|||||||
Reference in New Issue
Block a user