Skip to content

Commit de7e5ef

Browse files
committed
[SILGen] Add SILDeclRef for main entry-point
Allow SILDeclRef to refer to the main program entry-point, which will either be for a main SourceFile, or a synthetic main such as an `@main` decl. Adjust the various SILDeclRef related functions to handle this new case, and change the emission to go through `emitFunctionDefinition`. This change will allow the entry-point for an `@main` decl (and eventually a main SourceFile) to be emitted on-demand from its symbol name.
1 parent e4624aa commit de7e5ef

File tree

9 files changed

+153
-95
lines changed

9 files changed

+153
-95
lines changed

include/swift/SIL/SILDeclRef.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ struct SILDeclRef {
152152
/// References the function used to initialize a property wrapper storage
153153
/// instance from a projected value.
154154
PropertyWrapperInitFromProjectedValue,
155+
156+
/// The main entry-point function. This may reference a SourceFile for a
157+
/// top-level main, or a decl for e.g an @main decl.
158+
EntryPoint,
155159
};
156160

157161
/// The AST node represented by this SILDeclRef.
@@ -220,6 +224,12 @@ struct SILDeclRef {
220224
/// Produce a SIL constant for a default argument generator.
221225
static SILDeclRef getDefaultArgGenerator(Loc loc, unsigned defaultArgIndex);
222226

227+
/// Produces a SILDeclRef for a synthetic main entry-point such as @main.
228+
static SILDeclRef getMainDeclEntryPoint(ValueDecl *decl);
229+
230+
/// Produces a SILDeclRef for the entry-point of a main FileUnit.
231+
static SILDeclRef getMainFileEntryPoint(FileUnit *file);
232+
223233
bool isNull() const { return loc.isNull(); }
224234
explicit operator bool() const { return !isNull(); }
225235

@@ -236,7 +246,13 @@ struct SILDeclRef {
236246
AutoClosureExpr *getAutoClosureExpr() const;
237247
FuncDecl *getFuncDecl() const;
238248
AbstractFunctionDecl *getAbstractFunctionDecl() const;
239-
249+
FileUnit *getFileUnit() const {
250+
return loc.get<FileUnit *>();
251+
}
252+
253+
/// Retrieves the ASTContext from the underlying AST node being stored.
254+
ASTContext &getASTContext() const;
255+
240256
llvm::Optional<AnyFunctionRef> getAnyFunctionRef() const;
241257

242258
SILLocation getAsRegularLocation() const;

lib/IRGen/GenObjC.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,7 @@ namespace {
473473
case SILDeclRef::Kind::GlobalAccessor:
474474
case SILDeclRef::Kind::PropertyWrapperBackingInitializer:
475475
case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue:
476+
case SILDeclRef::Kind::EntryPoint:
476477
llvm_unreachable("Method does not have a selector");
477478

478479
case SILDeclRef::Kind::Destroyer:

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "swift/AST/AnyFunctionRef.h"
1717
#include "swift/AST/Initializer.h"
1818
#include "swift/AST/ParameterList.h"
19+
#include "swift/AST/SourceFile.h"
1920
#include "swift/ClangImporter/ClangImporter.h"
2021
#include "swift/ClangImporter/ClangModule.h"
2122
#include "swift/SIL/SILLinkage.h"
@@ -183,6 +184,18 @@ Optional<AnyFunctionRef> SILDeclRef::getAnyFunctionRef() const {
183184
llvm_unreachable("Unhandled case in switch");
184185
}
185186

187+
ASTContext &SILDeclRef::getASTContext() const {
188+
switch (getLocKind()) {
189+
case LocKind::Decl:
190+
return getDecl()->getASTContext();
191+
case LocKind::Closure:
192+
return getAbstractClosureExpr()->getASTContext();
193+
case LocKind::File:
194+
return getFileUnit()->getASTContext();
195+
}
196+
llvm_unreachable("Unhandled case in switch");
197+
}
198+
186199
bool SILDeclRef::isThunk() const {
187200
return isForeignToNativeThunk() || isNativeToForeignThunk();
188201
}
@@ -252,6 +265,10 @@ SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
252265
return isSerialized() ? SILLinkage::Shared : SILLinkage::Private;
253266
}
254267

268+
// The main entry-point is public.
269+
if (kind == Kind::EntryPoint)
270+
return SILLinkage::Public;
271+
255272
// Add External to the linkage (e.g. Public -> PublicExternal) if this is a
256273
// declaration not a definition.
257274
auto maybeAddExternal = [&](SILLinkage linkage) {
@@ -417,6 +434,23 @@ SILDeclRef SILDeclRef::getDefaultArgGenerator(Loc loc,
417434
return result;
418435
}
419436

437+
SILDeclRef SILDeclRef::getMainDeclEntryPoint(ValueDecl *decl) {
438+
auto *file = cast<FileUnit>(decl->getDeclContext()->getModuleScopeContext());
439+
assert(file->getMainDecl() == decl);
440+
SILDeclRef result;
441+
result.loc = decl;
442+
result.kind = Kind::EntryPoint;
443+
return result;
444+
}
445+
446+
SILDeclRef SILDeclRef::getMainFileEntryPoint(FileUnit *file) {
447+
assert(file->hasEntryPoint() && !file->getMainDecl());
448+
SILDeclRef result;
449+
result.loc = file;
450+
result.kind = Kind::EntryPoint;
451+
return result;
452+
}
453+
420454
bool SILDeclRef::hasClosureExpr() const {
421455
return loc.is<AbstractClosureExpr *>()
422456
&& isa<ClosureExpr>(getAbstractClosureExpr());
@@ -500,6 +534,9 @@ IsSerialized_t SILDeclRef::isSerialized() const {
500534
return IsNotSerialized;
501535
}
502536

537+
if (kind == Kind::EntryPoint)
538+
return IsNotSerialized;
539+
503540
if (isIVarInitializerOrDestroyer())
504541
return IsNotSerialized;
505542

@@ -872,6 +909,10 @@ std::string SILDeclRef::mangle(ManglingKind MKind) const {
872909
case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue:
873910
return mangler.mangleInitFromProjectedValueEntity(cast<VarDecl>(getDecl()),
874911
SKind);
912+
913+
case SILDeclRef::Kind::EntryPoint: {
914+
return getASTContext().getEntryPointFunctionName();
915+
}
875916
}
876917

877918
llvm_unreachable("bad entity kind!");
@@ -1190,7 +1231,12 @@ SubclassScope SILDeclRef::getSubclassScope() const {
11901231
}
11911232

11921233
unsigned SILDeclRef::getParameterListCount() const {
1193-
if (!hasDecl() || kind == Kind::DefaultArgGenerator)
1234+
// Only decls can introduce currying.
1235+
if (!hasDecl())
1236+
return 1;
1237+
1238+
// Always uncurried even if the underlying function is curried.
1239+
if (kind == Kind::DefaultArgGenerator || kind == Kind::EntryPoint)
11941240
return 1;
11951241

11961242
auto *vd = getDecl();

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2512,6 +2512,9 @@ static CanSILFunctionType getNativeSILFunctionType(
25122512
DefaultConventions(NormalParameterConvention::Guaranteed));
25132513
case SILDeclRef::Kind::Deallocator:
25142514
return getSILFunctionTypeForConventions(DeallocatorConventions());
2515+
2516+
case SILDeclRef::Kind::EntryPoint:
2517+
llvm_unreachable("Handled by getSILFunctionTypeForAbstractCFunction");
25152518
}
25162519
}
25172520
}
@@ -3038,6 +3041,7 @@ static ObjCSelectorFamily getObjCSelectorFamily(SILDeclRef c) {
30383041
case SILDeclRef::Kind::StoredPropertyInitializer:
30393042
case SILDeclRef::Kind::PropertyWrapperBackingInitializer:
30403043
case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue:
3044+
case SILDeclRef::Kind::EntryPoint:
30413045
llvm_unreachable("Unexpected Kind of foreign SILDeclRef");
30423046
}
30433047

@@ -3300,6 +3304,9 @@ TypeConverter::getDeclRefRepresentation(SILDeclRef c) {
33003304
case SILDeclRef::Kind::IVarInitializer:
33013305
case SILDeclRef::Kind::IVarDestroyer:
33023306
return SILFunctionTypeRepresentation::Method;
3307+
3308+
case SILDeclRef::Kind::EntryPoint:
3309+
return SILFunctionTypeRepresentation::CFunctionPointer;
33033310
}
33043311

33053312
llvm_unreachable("Unhandled SILDeclRefKind in switch.");
@@ -4127,6 +4134,7 @@ static AbstractFunctionDecl *getBridgedFunction(SILDeclRef declRef) {
41274134
case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue:
41284135
case SILDeclRef::Kind::IVarInitializer:
41294136
case SILDeclRef::Kind::IVarDestroyer:
4137+
case SILDeclRef::Kind::EntryPoint:
41304138
return nullptr;
41314139
}
41324140
llvm_unreachable("bad SILDeclRef kind");

lib/SIL/IR/SILPrinter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ void SILDeclRef::print(raw_ostream &OS) const {
315315

316316
switch (kind) {
317317
case SILDeclRef::Kind::Func:
318+
case SILDeclRef::Kind::EntryPoint:
318319
break;
319320
case SILDeclRef::Kind::Allocator:
320321
OS << "!allocator";

lib/SIL/IR/TypeLowering.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2577,6 +2577,45 @@ getFunctionInterfaceTypeWithCaptures(TypeConverter &TC,
25772577
innerExtInfo);
25782578
}
25792579

2580+
static CanAnyFunctionType getEntryPointInterfaceType(ASTContext &C) {
2581+
// Use standard library types if we have them; otherwise, fall back to
2582+
// builtins.
2583+
CanType Int32Ty;
2584+
if (auto Int32Decl = C.getInt32Decl()) {
2585+
Int32Ty = Int32Decl->getDeclaredInterfaceType()->getCanonicalType();
2586+
} else {
2587+
Int32Ty = CanType(BuiltinIntegerType::get(32, C));
2588+
}
2589+
2590+
CanType PtrPtrInt8Ty = C.TheRawPointerType;
2591+
if (auto PointerDecl = C.getUnsafeMutablePointerDecl()) {
2592+
if (auto Int8Decl = C.getInt8Decl()) {
2593+
Type Int8Ty = Int8Decl->getDeclaredInterfaceType();
2594+
Type PointerInt8Ty = BoundGenericType::get(PointerDecl,
2595+
nullptr,
2596+
Int8Ty);
2597+
Type OptPointerInt8Ty = OptionalType::get(PointerInt8Ty);
2598+
PtrPtrInt8Ty = BoundGenericType::get(PointerDecl,
2599+
nullptr,
2600+
OptPointerInt8Ty)
2601+
->getCanonicalType();
2602+
}
2603+
}
2604+
2605+
using Param = FunctionType::Param;
2606+
Param params[] = {Param(Int32Ty), Param(PtrPtrInt8Ty)};
2607+
2608+
auto rep = FunctionTypeRepresentation::CFunctionPointer;
2609+
auto *clangTy = C.getClangFunctionType(params, Int32Ty, rep);
2610+
auto extInfo = FunctionType::ExtInfoBuilder()
2611+
.withRepresentation(rep)
2612+
.withClangFunctionType(clangTy)
2613+
.build();
2614+
2615+
return CanAnyFunctionType::get(/*genericSig*/ nullptr,
2616+
llvm::makeArrayRef(params), Int32Ty, extInfo);
2617+
}
2618+
25802619
CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) {
25812620
if (auto *derivativeId = c.getDerivativeFunctionIdentifier()) {
25822621
auto originalFnTy =
@@ -2654,6 +2693,8 @@ CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) {
26542693
case SILDeclRef::Kind::IVarDestroyer:
26552694
return getIVarInitDestroyerInterfaceType(cast<ClassDecl>(vd),
26562695
c.isForeign, true);
2696+
case SILDeclRef::Kind::EntryPoint:
2697+
return getEntryPointInterfaceType(Context);
26572698
}
26582699

26592700
llvm_unreachable("Unhandled SILDeclRefKind in switch.");
@@ -2689,6 +2730,8 @@ TypeConverter::getConstantGenericSignature(SILDeclRef c) {
26892730
case SILDeclRef::Kind::PropertyWrapperBackingInitializer:
26902731
case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue:
26912732
return vd->getDeclContext()->getGenericSignatureOfContext();
2733+
case SILDeclRef::Kind::EntryPoint:
2734+
llvm_unreachable("Doesn't have generic signature");
26922735
}
26932736

26942737
llvm_unreachable("Unhandled SILDeclRefKind in switch.");

0 commit comments

Comments
 (0)