Skip to content

Commit 6697dfd

Browse files
authored
Merge pull request #3604 from eeckstein/clang-import
SIL: Print+parse the clang node owner of SILFunctions.
2 parents 182e721 + d17f539 commit 6697dfd

File tree

5 files changed

+118
-66
lines changed

5 files changed

+118
-66
lines changed

lib/Parse/ParseSIL.cpp

Lines changed: 59 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,12 @@ namespace {
239239
SmallVector<ValueDecl *, 4> values;
240240
return parseSILDottedPath(Decl, values);
241241
}
242+
bool parseSILDottedPathWithoutPound(ValueDecl *&Decl,
243+
SmallVectorImpl<ValueDecl *> &values);
244+
bool parseSILDottedPathWithoutPound(ValueDecl *&Decl) {
245+
SmallVector<ValueDecl *, 4> values;
246+
return parseSILDottedPathWithoutPound(Decl, values);
247+
}
242248
/// At the time of calling this function, we may not have the type of the
243249
/// Decl yet. So we return a SILDeclRef on the first lookup result and also
244250
/// return all the lookup results. After parsing the expected type, the
@@ -676,75 +682,83 @@ static bool parseDeclSILOptional(bool *isTransparent, bool *isFragile,
676682
Inline_t *inlineStrategy, bool *isLet,
677683
SmallVectorImpl<std::string> *Semantics,
678684
SmallVectorImpl<ParsedSpecAttr> *SpecAttrs,
679-
EffectsKind *MRK, Parser &P) {
680-
while (P.consumeIf(tok::l_square)) {
681-
if (isLet && P.Tok.is(tok::kw_let)) {
685+
ValueDecl **ClangDecl,
686+
EffectsKind *MRK, SILParser &SP) {
687+
while (SP.P.consumeIf(tok::l_square)) {
688+
if (isLet && SP.P.Tok.is(tok::kw_let)) {
682689
*isLet = true;
683-
P.consumeToken(tok::kw_let);
684-
P.parseToken(tok::r_square, diag::expected_in_attribute_list);
690+
SP.P.consumeToken(tok::kw_let);
691+
SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
685692
continue;
686693
}
687-
else if (P.Tok.isNot(tok::identifier)) {
688-
P.diagnose(P.Tok, diag::expected_in_attribute_list);
694+
else if (SP.P.Tok.isNot(tok::identifier)) {
695+
SP.P.diagnose(SP.P.Tok, diag::expected_in_attribute_list);
689696
return true;
690-
} else if (isTransparent && P.Tok.getText() == "transparent")
697+
} else if (isTransparent && SP.P.Tok.getText() == "transparent")
691698
*isTransparent = true;
692-
else if (isFragile && P.Tok.getText() == "fragile")
699+
else if (isFragile && SP.P.Tok.getText() == "fragile")
693700
*isFragile = true;
694-
else if (isThunk && P.Tok.getText() == "thunk")
701+
else if (isThunk && SP.P.Tok.getText() == "thunk")
695702
*isThunk = IsThunk;
696-
else if (isThunk && P.Tok.getText() == "reabstraction_thunk")
703+
else if (isThunk && SP.P.Tok.getText() == "reabstraction_thunk")
697704
*isThunk = IsReabstractionThunk;
698-
else if (isGlobalInit && P.Tok.getText() == "global_init")
705+
else if (isGlobalInit && SP.P.Tok.getText() == "global_init")
699706
*isGlobalInit = true;
700-
else if (inlineStrategy && P.Tok.getText() == "noinline")
707+
else if (inlineStrategy && SP.P.Tok.getText() == "noinline")
701708
*inlineStrategy = NoInline;
702-
else if (inlineStrategy && P.Tok.getText() == "always_inline")
709+
else if (inlineStrategy && SP.P.Tok.getText() == "always_inline")
703710
*inlineStrategy = AlwaysInline;
704-
else if (MRK && P.Tok.getText() == "readnone")
711+
else if (MRK && SP.P.Tok.getText() == "readnone")
705712
*MRK = EffectsKind::ReadNone;
706-
else if (MRK && P.Tok.getText() == "readonly")
713+
else if (MRK && SP.P.Tok.getText() == "readonly")
707714
*MRK = EffectsKind::ReadOnly;
708-
else if (MRK && P.Tok.getText() == "readwrite")
715+
else if (MRK && SP.P.Tok.getText() == "readwrite")
709716
*MRK = EffectsKind::ReadWrite;
710-
else if (Semantics && P.Tok.getText() == "_semantics") {
711-
P.consumeToken(tok::identifier);
712-
if (P.Tok.getKind() != tok::string_literal) {
713-
P.diagnose(P.Tok, diag::expected_in_attribute_list);
717+
else if (Semantics && SP.P.Tok.getText() == "_semantics") {
718+
SP.P.consumeToken(tok::identifier);
719+
if (SP.P.Tok.getKind() != tok::string_literal) {
720+
SP.P.diagnose(SP.P.Tok, diag::expected_in_attribute_list);
714721
return true;
715722
}
716723

717724
// Drop the double quotes.
718-
StringRef rawString = P.Tok.getText().drop_front().drop_back();
725+
StringRef rawString = SP.P.Tok.getText().drop_front().drop_back();
719726
Semantics->push_back(rawString);
720-
P.consumeToken(tok::string_literal);
727+
SP.P.consumeToken(tok::string_literal);
721728

722-
P.parseToken(tok::r_square, diag::expected_in_attribute_list);
729+
SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
723730
continue;
724731
}
725-
else if (SpecAttrs && P.Tok.getText() == "_specialize") {
726-
P.consumeToken(tok::identifier);
732+
else if (SpecAttrs && SP.P.Tok.getText() == "_specialize") {
733+
SP.P.consumeToken(tok::identifier);
727734

728735
/// Parse a specialized attributed, building a parsed substitution list
729736
/// and pushing a new ParsedSpecAttr on the SpecAttrs list. Conformances
730737
/// cannot be generated until the function declaration is fully parsed so
731738
/// that the function's generic signature can be consulted.
732-
SILParser SpecAttrState(P);
733739
ParsedSpecAttr SpecAttr;
734-
if (SpecAttrState.parseApplySubstitutions(SpecAttr.subs))
740+
if (SP.parseApplySubstitutions(SpecAttr.subs))
735741
return true;
736742

737743
SpecAttrs->emplace_back(SpecAttr);
738744

739-
P.parseToken(tok::r_square, diag::expected_in_attribute_list);
745+
SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
746+
continue;
747+
}
748+
else if (ClangDecl && SP.P.Tok.getText() == "clang") {
749+
SP.P.consumeToken(tok::identifier);
750+
if (SP.parseSILDottedPathWithoutPound(*ClangDecl))
751+
return true;
752+
753+
SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
740754
continue;
741755
}
742756
else {
743-
P.diagnose(P.Tok, diag::expected_in_attribute_list);
757+
SP.P.diagnose(SP.P.Tok, diag::expected_in_attribute_list);
744758
return true;
745759
}
746-
P.consumeToken(tok::identifier);
747-
P.parseToken(tok::r_square, diag::expected_in_attribute_list);
760+
SP.P.consumeToken(tok::identifier);
761+
SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
748762
}
749763
return false;
750764
}
@@ -875,7 +889,11 @@ bool SILParser::parseSILDottedPath(ValueDecl *&Decl,
875889
SmallVectorImpl<ValueDecl *> &values) {
876890
if (P.parseToken(tok::pound, diag::expected_sil_constant))
877891
return true;
892+
return parseSILDottedPathWithoutPound(Decl, values);
893+
}
878894

895+
bool SILParser::parseSILDottedPathWithoutPound(ValueDecl *&Decl,
896+
SmallVectorImpl<ValueDecl *> &values) {
879897
// Handle sil-dotted-path.
880898
Identifier Id;
881899
SmallVector<Identifier, 4> FullName;
@@ -3858,11 +3876,12 @@ bool Parser::parseDeclSIL() {
38583876
Inline_t inlineStrategy = InlineDefault;
38593877
SmallVector<std::string, 1> Semantics;
38603878
SmallVector<ParsedSpecAttr, 4> SpecAttrs;
3879+
ValueDecl *ClangDecl = nullptr;
38613880
EffectsKind MRK = EffectsKind::Unspecified;
38623881
if (parseSILLinkage(FnLinkage, *this) ||
38633882
parseDeclSILOptional(&isTransparent, &isFragile, &isThunk, &isGlobalInit,
38643883
&inlineStrategy, nullptr, &Semantics, &SpecAttrs,
3865-
&MRK, *this) ||
3884+
&ClangDecl, &MRK, FunctionState) ||
38663885
parseToken(tok::at_sign, diag::expected_sil_function_name) ||
38673886
parseIdentifier(FnName, FnNameLoc, diag::expected_sil_function_name) ||
38683887
parseToken(tok::colon, diag::expected_sil_type))
@@ -3889,6 +3908,8 @@ bool Parser::parseDeclSIL() {
38893908
FunctionState.F->setGlobalInit(isGlobalInit);
38903909
FunctionState.F->setInlineStrategy(inlineStrategy);
38913910
FunctionState.F->setEffectsKind(MRK);
3911+
if (ClangDecl)
3912+
FunctionState.F->setClangNodeOwner(ClangDecl);
38923913
for (auto &Attr : Semantics) {
38933914
FunctionState.F->addSemanticsAttr(Attr);
38943915
}
@@ -3997,15 +4018,16 @@ bool Parser::parseSILGlobal() {
39974018
// Inform the lexer that we're lexing the body of the SIL declaration.
39984019
Lexer::SILBodyRAII Tmp(*L);
39994020
Scope S(this, ScopeKind::TopLevel);
4021+
SILParser State(*this);
40004022
if (parseSILLinkage(GlobalLinkage, *this) ||
40014023
parseDeclSILOptional(nullptr, &isFragile, nullptr, nullptr,
4002-
nullptr, &isLet, nullptr, nullptr, nullptr, *this) ||
4024+
nullptr, &isLet, nullptr, nullptr, nullptr,
4025+
nullptr, State) ||
40034026
parseToken(tok::at_sign, diag::expected_sil_value_name) ||
40044027
parseIdentifier(GlobalName, NameLoc, diag::expected_sil_value_name) ||
40054028
parseToken(tok::colon, diag::expected_sil_type))
40064029
return true;
40074030

4008-
SILParser State(*this);
40094031
if (State.parseSILType(GlobalType))
40104032
return true;
40114033

@@ -4342,7 +4364,8 @@ bool Parser::parseSILWitnessTable() {
43424364

43434365
bool isFragile = false;
43444366
if (parseDeclSILOptional(nullptr, &isFragile, nullptr, nullptr,
4345-
nullptr, nullptr, nullptr, nullptr, nullptr, *this))
4367+
nullptr, nullptr, nullptr, nullptr, nullptr,
4368+
nullptr, WitnessState))
43464369
return true;
43474370

43484371
Scope S(this, ScopeKind::TopLevel);

lib/SIL/SILPrinter.cpp

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,16 @@ static void printFullContext(const DeclContext *Context, raw_ostream &Buffer) {
229229
llvm_unreachable("bad decl context");
230230
}
231231

232+
static void printValueDecl(ValueDecl *Decl, raw_ostream &OS) {
233+
printFullContext(Decl->getDeclContext(), OS);
234+
assert(Decl->hasName());
235+
236+
if (Decl->isOperator())
237+
OS << '"' << Decl->getName() << '"';
238+
else
239+
OS << Decl->getName();
240+
}
241+
232242
/// SILDeclRef uses sigil "#" and prints the fully qualified dotted path.
233243
void SILDeclRef::print(raw_ostream &OS) const {
234244
OS << "#";
@@ -242,53 +252,42 @@ void SILDeclRef::print(raw_ostream &OS) const {
242252
OS << "<anonymous function>";
243253
} else if (kind == SILDeclRef::Kind::Func) {
244254
auto *FD = cast<FuncDecl>(getDecl());
245-
ValueDecl *decl = FD;
246-
const char *Suffix;
247255
switch (FD->getAccessorKind()) {
248256
case AccessorKind::IsWillSet:
249-
Suffix = "!willSet";
250-
decl = FD->getAccessorStorageDecl();
257+
printValueDecl(FD->getAccessorStorageDecl(), OS);
258+
OS << "!willSet";
251259
break;
252260
case AccessorKind::IsDidSet:
253-
Suffix = "!didSet";
254-
decl = FD->getAccessorStorageDecl();
261+
printValueDecl(FD->getAccessorStorageDecl(), OS);
262+
OS << "!didSet";
255263
break;
256264
case AccessorKind::NotAccessor:
257-
Suffix = "";
265+
printValueDecl(FD, OS);
258266
isDot = false;
259267
break;
260268
case AccessorKind::IsGetter:
261-
Suffix = "!getter";
262-
decl = FD->getAccessorStorageDecl();
269+
printValueDecl(FD->getAccessorStorageDecl(), OS);
270+
OS << "!getter";
263271
break;
264272
case AccessorKind::IsSetter:
265-
Suffix = "!setter";
266-
decl = FD->getAccessorStorageDecl();
273+
printValueDecl(FD->getAccessorStorageDecl(), OS);
274+
OS << "!setter";
267275
break;
268276
case AccessorKind::IsMaterializeForSet:
269-
Suffix = "!materializeForSet";
270-
decl = FD->getAccessorStorageDecl();
277+
printValueDecl(FD->getAccessorStorageDecl(), OS);
278+
OS << "!materializeForSet";
271279
break;
272280
case AccessorKind::IsAddressor:
273-
Suffix = "!addressor";
274-
decl = FD->getAccessorStorageDecl();
281+
printValueDecl(FD->getAccessorStorageDecl(), OS);
282+
OS << "!addressor";
275283
break;
276284
case AccessorKind::IsMutableAddressor:
277-
Suffix = "!mutableAddressor";
278-
decl = FD->getAccessorStorageDecl();
285+
printValueDecl(FD->getAccessorStorageDecl(), OS);
286+
OS << "!mutableAddressor";
279287
break;
280288
}
281-
282-
printFullContext(decl->getDeclContext(), OS);
283-
assert(decl->hasName());
284-
285-
if (decl->isOperator())
286-
OS << '"' << decl->getName() << '"' << Suffix;
287-
else
288-
OS << decl->getName() << Suffix;
289289
} else {
290-
printFullContext(getDecl()->getDeclContext(), OS);
291-
OS << getDecl()->getName();
290+
printValueDecl(getDecl(), OS);
292291
}
293292
switch (kind) {
294293
case SILDeclRef::Kind::Func:
@@ -1748,6 +1747,14 @@ void SILFunction::print(SILPrintContext &PrintCtx) const {
17481747
for (auto *Attr : getSpecializeAttrs()) {
17491748
OS << "[_specialize "; Attr->print(OS); OS << "] ";
17501749
}
1750+
1751+
// TODO: Handle clang node owners which don't have a name.
1752+
if (hasClangNode() && getClangNodeOwner()->hasName()) {
1753+
OS << "[clang ";
1754+
printValueDecl(getClangNodeOwner(), OS);
1755+
OS << "] ";
1756+
}
1757+
17511758
printName(OS);
17521759
OS << " : $";
17531760

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
static inline int c_inline_func(int x) {
3+
return x + 27;
4+
}
5+

test/ClangModules/const_and_pure.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ func testit() {
88
normal_function()
99
}
1010

11-
// CHECK: sil [readnone] @const_function : $@convention(c) () -> ()
12-
// CHECK: sil [readonly] @pure_function : $@convention(c) () -> ()
13-
// CHECK: sil @normal_function : $@convention(c) () -> ()
11+
// CHECK: sil [readnone] [clang const_function] @const_function : $@convention(c) () -> ()
12+
// CHECK: sil [readonly] [clang pure_function] @pure_function : $@convention(c) () -> ()
13+
// CHECK: sil [clang normal_function] @normal_function : $@convention(c) () -> ()
1414

1515

test/ClangModules/static_inline.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: rm -rf %t && mkdir -p %t
2+
3+
// Check if SIL printing+parsing of a clang imported function works.
4+
5+
// RUN: %target-swift-frontend -parse-as-library -module-name=test -emit-sil %s -import-objc-header %S/Inputs/static_inline.h -o %t/test.sil
6+
// RUN: FileCheck < %t/test.sil %s
7+
// RUN: %target-swift-frontend -parse-as-library -module-name=test -O -emit-ir %t/test.sil -import-objc-header %S/Inputs/static_inline.h | FileCheck --check-prefix=CHECK-IR %s
8+
9+
// CHECK: sil shared [clang c_inline_func] @c_inline_func : $@convention(c) (Int32) -> Int32
10+
11+
// CHECK-IR-LABEL: define{{.*}} i32 @_TF4test6testitFT1xVs5Int32_S0_(i32)
12+
// CHECK-IR: = add {{.*}}, 27
13+
// CHECK-IR: ret
14+
15+
public func testit(x: Int32) -> Int32 {
16+
return c_inline_func(x)
17+
}

0 commit comments

Comments
 (0)