Skip to content

Commit c925246

Browse files
hamishknightetcwilde
authored andcommitted
[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 f47f47f commit c925246

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
@@ -144,6 +144,10 @@ struct SILDeclRef {
144144
/// References the function used to initialize a property wrapper storage
145145
/// instance from a projected value.
146146
PropertyWrapperInitFromProjectedValue,
147+
148+
/// The main entry-point function. This may reference a SourceFile for a
149+
/// top-level main, or a decl for e.g an @main decl.
150+
EntryPoint,
147151
};
148152

149153
/// The ValueDecl or AbstractClosureExpr represented by this SILDeclRef.
@@ -201,6 +205,12 @@ struct SILDeclRef {
201205
/// Produce a SIL constant for a default argument generator.
202206
static SILDeclRef getDefaultArgGenerator(Loc loc, unsigned defaultArgIndex);
203207

208+
/// Produces a SILDeclRef for a synthetic main entry-point such as @main.
209+
static SILDeclRef getMainDeclEntryPoint(ValueDecl *decl);
210+
211+
/// Produces a SILDeclRef for the entry-point of a main FileUnit.
212+
static SILDeclRef getMainFileEntryPoint(FileUnit *file);
213+
204214
bool isNull() const { return loc.isNull(); }
205215
explicit operator bool() const { return !isNull(); }
206216

@@ -217,7 +227,13 @@ struct SILDeclRef {
217227
AutoClosureExpr *getAutoClosureExpr() const;
218228
FuncDecl *getFuncDecl() const;
219229
AbstractFunctionDecl *getAbstractFunctionDecl() const;
220-
230+
FileUnit *getFileUnit() const {
231+
return loc.get<FileUnit *>();
232+
}
233+
234+
/// Retrieves the ASTContext from the underlying AST node being stored.
235+
ASTContext &getASTContext() const;
236+
221237
llvm::Optional<AnyFunctionRef> getAnyFunctionRef() const;
222238

223239
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"
@@ -180,6 +181,18 @@ Optional<AnyFunctionRef> SILDeclRef::getAnyFunctionRef() const {
180181
return AnyFunctionRef(loc.get<AbstractClosureExpr*>());
181182
}
182183

184+
ASTContext &SILDeclRef::getASTContext() const {
185+
switch (getLocKind()) {
186+
case LocKind::Decl:
187+
return getDecl()->getASTContext();
188+
case LocKind::Closure:
189+
return getAbstractClosureExpr()->getASTContext();
190+
case LocKind::File:
191+
return getFileUnit()->getASTContext();
192+
}
193+
llvm_unreachable("Unhandled case in switch");
194+
}
195+
183196
bool SILDeclRef::isThunk() const {
184197
return isForeignToNativeThunk() || isNativeToForeignThunk();
185198
}
@@ -242,6 +255,10 @@ SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
242255
return isSerialized() ? SILLinkage::Shared : SILLinkage::Private;
243256
}
244257

258+
// The main entry-point is public.
259+
if (kind == Kind::EntryPoint)
260+
return SILLinkage::Public;
261+
245262
// Add External to the linkage (e.g. Public -> PublicExternal) if this is a
246263
// declaration not a definition.
247264
auto maybeAddExternal = [&](SILLinkage linkage) {
@@ -407,6 +424,23 @@ SILDeclRef SILDeclRef::getDefaultArgGenerator(Loc loc,
407424
return result;
408425
}
409426

427+
SILDeclRef SILDeclRef::getMainDeclEntryPoint(ValueDecl *decl) {
428+
auto *file = cast<FileUnit>(decl->getDeclContext()->getModuleScopeContext());
429+
assert(file->getMainDecl() == decl);
430+
SILDeclRef result;
431+
result.loc = decl;
432+
result.kind = Kind::EntryPoint;
433+
return result;
434+
}
435+
436+
SILDeclRef SILDeclRef::getMainFileEntryPoint(FileUnit *file) {
437+
assert(file->hasEntryPoint() && !file->getMainDecl());
438+
SILDeclRef result;
439+
result.loc = file;
440+
result.kind = Kind::EntryPoint;
441+
return result;
442+
}
443+
410444
bool SILDeclRef::hasClosureExpr() const {
411445
return loc.is<AbstractClosureExpr *>()
412446
&& isa<ClosureExpr>(getAbstractClosureExpr());
@@ -490,6 +524,9 @@ IsSerialized_t SILDeclRef::isSerialized() const {
490524
return IsNotSerialized;
491525
}
492526

527+
if (kind == Kind::EntryPoint)
528+
return IsNotSerialized;
529+
493530
if (isIVarInitializerOrDestroyer())
494531
return IsNotSerialized;
495532

@@ -856,6 +893,10 @@ std::string SILDeclRef::mangle(ManglingKind MKind) const {
856893
case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue:
857894
return mangler.mangleInitFromProjectedValueEntity(cast<VarDecl>(getDecl()),
858895
SKind);
896+
897+
case SILDeclRef::Kind::EntryPoint: {
898+
return getASTContext().getEntryPointFunctionName();
899+
}
859900
}
860901

861902
llvm_unreachable("bad entity kind!");
@@ -1168,7 +1209,12 @@ SubclassScope SILDeclRef::getSubclassScope() const {
11681209
}
11691210

11701211
unsigned SILDeclRef::getParameterListCount() const {
1171-
if (!hasDecl() || kind == Kind::DefaultArgGenerator)
1212+
// Only decls can introduce currying.
1213+
if (!hasDecl())
1214+
return 1;
1215+
1216+
// Always uncurried even if the underlying function is curried.
1217+
if (kind == Kind::DefaultArgGenerator || kind == Kind::EntryPoint)
11721218
return 1;
11731219

11741220
auto *vd = getDecl();

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2496,6 +2496,9 @@ static CanSILFunctionType getNativeSILFunctionType(
24962496
DefaultConventions(NormalParameterConvention::Guaranteed));
24972497
case SILDeclRef::Kind::Deallocator:
24982498
return getSILFunctionTypeForConventions(DeallocatorConventions());
2499+
2500+
case SILDeclRef::Kind::EntryPoint:
2501+
llvm_unreachable("Handled by getSILFunctionTypeForAbstractCFunction");
24992502
}
25002503
}
25012504
}
@@ -3023,6 +3026,7 @@ static ObjCSelectorFamily getObjCSelectorFamily(SILDeclRef c) {
30233026
case SILDeclRef::Kind::StoredPropertyInitializer:
30243027
case SILDeclRef::Kind::PropertyWrapperBackingInitializer:
30253028
case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue:
3029+
case SILDeclRef::Kind::EntryPoint:
30263030
llvm_unreachable("Unexpected Kind of foreign SILDeclRef");
30273031
}
30283032

@@ -3283,6 +3287,9 @@ TypeConverter::getDeclRefRepresentation(SILDeclRef c) {
32833287
case SILDeclRef::Kind::IVarInitializer:
32843288
case SILDeclRef::Kind::IVarDestroyer:
32853289
return SILFunctionTypeRepresentation::Method;
3290+
3291+
case SILDeclRef::Kind::EntryPoint:
3292+
return SILFunctionTypeRepresentation::CFunctionPointer;
32863293
}
32873294

32883295
llvm_unreachable("Unhandled SILDeclRefKind in switch.");
@@ -4110,6 +4117,7 @@ static AbstractFunctionDecl *getBridgedFunction(SILDeclRef declRef) {
41104117
case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue:
41114118
case SILDeclRef::Kind::IVarInitializer:
41124119
case SILDeclRef::Kind::IVarDestroyer:
4120+
case SILDeclRef::Kind::EntryPoint:
41134121
return nullptr;
41144122
}
41154123
llvm_unreachable("bad SILDeclRef kind");

lib/SIL/IR/SILPrinter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ void SILDeclRef::print(raw_ostream &OS) const {
311311
}
312312
switch (kind) {
313313
case SILDeclRef::Kind::Func:
314+
case SILDeclRef::Kind::EntryPoint:
314315
break;
315316
case SILDeclRef::Kind::Allocator:
316317
OS << "!allocator";

lib/SIL/IR/TypeLowering.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2553,6 +2553,45 @@ getFunctionInterfaceTypeWithCaptures(TypeConverter &TC,
25532553
innerExtInfo);
25542554
}
25552555

2556+
static CanAnyFunctionType getEntryPointInterfaceType(ASTContext &C) {
2557+
// Use standard library types if we have them; otherwise, fall back to
2558+
// builtins.
2559+
CanType Int32Ty;
2560+
if (auto Int32Decl = C.getInt32Decl()) {
2561+
Int32Ty = Int32Decl->getDeclaredInterfaceType()->getCanonicalType();
2562+
} else {
2563+
Int32Ty = CanType(BuiltinIntegerType::get(32, C));
2564+
}
2565+
2566+
CanType PtrPtrInt8Ty = C.TheRawPointerType;
2567+
if (auto PointerDecl = C.getUnsafeMutablePointerDecl()) {
2568+
if (auto Int8Decl = C.getInt8Decl()) {
2569+
Type Int8Ty = Int8Decl->getDeclaredInterfaceType();
2570+
Type PointerInt8Ty = BoundGenericType::get(PointerDecl,
2571+
nullptr,
2572+
Int8Ty);
2573+
Type OptPointerInt8Ty = OptionalType::get(PointerInt8Ty);
2574+
PtrPtrInt8Ty = BoundGenericType::get(PointerDecl,
2575+
nullptr,
2576+
OptPointerInt8Ty)
2577+
->getCanonicalType();
2578+
}
2579+
}
2580+
2581+
using Param = FunctionType::Param;
2582+
Param params[] = {Param(Int32Ty), Param(PtrPtrInt8Ty)};
2583+
2584+
auto rep = FunctionTypeRepresentation::CFunctionPointer;
2585+
auto *clangTy = C.getClangFunctionType(params, Int32Ty, rep);
2586+
auto extInfo = FunctionType::ExtInfoBuilder()
2587+
.withRepresentation(rep)
2588+
.withClangFunctionType(clangTy)
2589+
.build();
2590+
2591+
return CanAnyFunctionType::get(/*genericSig*/ nullptr,
2592+
llvm::makeArrayRef(params), Int32Ty, extInfo);
2593+
}
2594+
25562595
CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) {
25572596
if (auto *derivativeId = c.getDerivativeFunctionIdentifier()) {
25582597
auto originalFnTy =
@@ -2627,6 +2666,8 @@ CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) {
26272666
case SILDeclRef::Kind::IVarDestroyer:
26282667
return getIVarInitDestroyerInterfaceType(cast<ClassDecl>(vd),
26292668
c.isForeign, true);
2669+
case SILDeclRef::Kind::EntryPoint:
2670+
return getEntryPointInterfaceType(Context);
26302671
}
26312672

26322673
llvm_unreachable("Unhandled SILDeclRefKind in switch.");
@@ -2678,6 +2719,8 @@ TypeConverter::getConstantGenericSignature(SILDeclRef c) {
26782719
case SILDeclRef::Kind::GlobalAccessor:
26792720
case SILDeclRef::Kind::StoredPropertyInitializer:
26802721
return vd->getDeclContext()->getGenericSignatureOfContext();
2722+
case SILDeclRef::Kind::EntryPoint:
2723+
llvm_unreachable("Doesn't have generic signature");
26812724
}
26822725

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

0 commit comments

Comments
 (0)