Skip to content

[SILGen] Enable alternative entry point name. #35595

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1151,6 +1151,10 @@ class ASTContext final {
/// standard library's String implementation.
bool isASCIIString(StringRef s) const;

/// Retrieve the name of to be used for the entry point, either main or an
/// alternative specified via the -entry-point-function-name frontend flag.
std::string getEntryPointFunctionName() const;

private:
friend Decl;
Optional<RawComment> getRawComment(const Decl *D);
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ namespace swift {
/// The target variant SDK version, if known.
Optional<llvm::VersionTuple> VariantSDKVersion;

/// The alternate name to use for the entry point instead of main.
std::string entryPointFunctionName = "main";

///
/// Language features
///
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,9 @@ def disable_interface_lockfile : Flag<["-"], "disable-interface-lock">,
def bridging_header_directory_for_print: Separate<["-"], "bridging-header-directory-for-print">, MetaVarName<"<path>">,
HelpText<"Directory for bridging header to be printed in compatibility header">;

def entry_point_function_name: Separate<["-"], "entry-point-function-name">, MetaVarName<"<string>">,
HelpText<"Name of the entry point function">;

def target_sdk_version : Separate<["-"], "target-sdk-version">,
HelpText<"The version of target SDK used for compilation">;

Expand Down
3 changes: 0 additions & 3 deletions include/swift/SIL/SILFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@
#include "swift/SIL/SILLinkage.h"
#include "swift/SIL/SILPrintContext.h"

/// The symbol name used for the program entry point function.
#define SWIFT_ENTRY_POINT_FUNCTION "main"

namespace swift {

class ASTContext;
Expand Down
4 changes: 4 additions & 0 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4811,6 +4811,10 @@ ASTContext::SILTransformCtors ASTContext::getIRGenSILTransforms() const {
return passes;
}

std::string ASTContext::getEntryPointFunctionName() const {
return LangOpts.entryPointFunctionName;
}

SILLayout *SILLayout::get(ASTContext &C,
CanGenericSignature Generics,
ArrayRef<SILField> Fields) {
Expand Down
4 changes: 4 additions & 0 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,10 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
}
}

if (const Arg *A = Args.getLastArg(OPT_entry_point_function_name)) {
Opts.entryPointFunctionName = A->getValue();
}

if (FrontendOpts.RequestedAction == FrontendOptions::ActionType::EmitSyntax) {
Opts.BuildSyntaxTree = true;
Opts.VerifySyntaxTree = true;
Expand Down
9 changes: 5 additions & 4 deletions lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -590,9 +590,9 @@ void IRGenModule::emitRuntimeRegistration() {
return;

// Find the entry point.
SILFunction *EntryPoint =
getSILModule().lookUpFunction(SWIFT_ENTRY_POINT_FUNCTION);
SILFunction *EntryPoint = getSILModule().lookUpFunction(
getSILModule().getASTContext().getEntryPointFunctionName());

// If we're debugging (and not in the REPL), we don't have a
// main. Find a function marked with the LLDBDebuggerFunction
// attribute instead.
Expand Down Expand Up @@ -1894,7 +1894,8 @@ static std::string getEntryPointSection(IRGenModule &IGM) {

void IRGenerator::emitEntryPointInfo() {
SILFunction *entrypoint = nullptr;
if (!(entrypoint = SIL.lookUpFunction(SWIFT_ENTRY_POINT_FUNCTION))) {
if (!(entrypoint = SIL.lookUpFunction(
SIL.getASTContext().getEntryPointFunctionName()))) {
return;
}
auto &IGM = *getGenModule(entrypoint);
Expand Down
15 changes: 10 additions & 5 deletions lib/IRGen/IRGenDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
llvm::DIFile *MainFile = nullptr;
/// The current module.
llvm::DIModule *MainModule = nullptr;
/// Scope of SWIFT_ENTRY_POINT_FUNCTION.
/// Scope of entry point function (main by default).
llvm::DIScope *EntryPointFn = nullptr;
/// The artificial type decls for named archetypes.
llvm::StringMap<TypeAliasDecl *> MetadataTypeDeclCache;
Expand Down Expand Up @@ -2084,7 +2084,8 @@ llvm::DIScope *IRGenDebugInfoImpl::getEntryPointFn() {
// Lazily create EntryPointFn.
if (!EntryPointFn) {
EntryPointFn = DBuilder.createReplaceableCompositeType(
llvm::dwarf::DW_TAG_subroutine_type, SWIFT_ENTRY_POINT_FUNCTION,
llvm::dwarf::DW_TAG_subroutine_type,
IGM.getSILModule().getASTContext().getEntryPointFunctionName(),
MainFile, MainFile, 0);
}
return EntryPointFn;
Expand Down Expand Up @@ -2219,7 +2220,8 @@ IRGenDebugInfoImpl::emitFunction(const SILDebugScope *DS, llvm::Function *Fn,
Scope = getOrCreateContext(SILFn->getDeclContext()->getParent());

// We know that main always comes from MainFile.
if (LinkageName == SWIFT_ENTRY_POINT_FUNCTION) {
if (LinkageName ==
IGM.getSILModule().getASTContext().getEntryPointFunctionName()) {
File = MainFile;
Line = 1;
Name = LinkageName;
Expand All @@ -2242,7 +2244,9 @@ IRGenDebugInfoImpl::emitFunction(const SILDebugScope *DS, llvm::Function *Fn,
// have a Swift name, does appear prominently in the source code.
// ObjC thunks should also not show up in the linetable, because we
// never want to set a breakpoint there.
if ((Name.empty() && LinkageName != SWIFT_ENTRY_POINT_FUNCTION &&
if ((Name.empty() &&
LinkageName !=
IGM.getSILModule().getASTContext().getEntryPointFunctionName() &&
!isExplicitClosure(SILFn)) ||
(Rep == SILFunctionTypeRepresentation::ObjCMethod) ||
isAllocatingConstructor(Rep, DeclCtx)) {
Expand Down Expand Up @@ -2279,7 +2283,8 @@ IRGenDebugInfoImpl::emitFunction(const SILDebugScope *DS, llvm::Function *Fn,
Fn->setSubprogram(SP);

// RAUW the entry point function forward declaration with the real thing.
if (LinkageName == SWIFT_ENTRY_POINT_FUNCTION) {
if (LinkageName ==
IGM.getSILModule().getASTContext().getEntryPointFunctionName()) {
if (EntryPointFn) {
assert(EntryPointFn->isTemporary() &&
"more than one entry point function");
Expand Down
4 changes: 2 additions & 2 deletions lib/IRGen/IRGenDebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,10 @@ class IRGenDebugInfo {
/// artificial inline location pointing to the user's instruction.
void setInlinedTrapLocation(IRBuilder &Builder, const SILDebugScope *Scope);

/// Set the location for SWIFT_ENTRY_POINT_FUNCTION.
/// Set the location for entry point function (main by default).
void setEntryPointLoc(IRBuilder &Builder);

/// Return the scope for SWIFT_ENTRY_POINT_FUNCTION.
/// Return the scope for the entry point function (main by default).
llvm::DIScope *getEntryPointFn();

/// Translate a SILDebugScope into an llvm::DIDescriptor.
Expand Down
4 changes: 2 additions & 2 deletions lib/IRGen/TypeLayoutVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,8 @@ void IRGenModule::emitTypeVerifier() {
return;

// Find the entry point.
SILFunction *EntryPoint =
getSILModule().lookUpFunction(SWIFT_ENTRY_POINT_FUNCTION);
SILFunction *EntryPoint = getSILModule().lookUpFunction(
getSILModule().getASTContext().getEntryPointFunctionName());

if (!EntryPoint)
return;
Expand Down
13 changes: 8 additions & 5 deletions lib/SILGen/SILGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -569,9 +569,10 @@ SILFunction *SILGenModule::emitTopLevelFunction(SILLocation Loc) {
SubstitutionMap(), SubstitutionMap(),
C);

auto name = getASTContext().getEntryPointFunctionName();
SILGenFunctionBuilder builder(*this);
return builder.createFunction(
SILLinkage::Public, SWIFT_ENTRY_POINT_FUNCTION, topLevelType, nullptr,
SILLinkage::Public, name, topLevelType, nullptr,
Loc, IsBare, IsNotTransparent, IsNotSerialized, IsNotDynamic,
ProfileCounter(), IsNotThunk, SubclassScope::NotApplicable);
}
Expand Down Expand Up @@ -1817,8 +1818,9 @@ class SourceFileScope {
// If this is the script-mode file for the module, create a toplevel.
if (sf->isScriptMode()) {
assert(!sgm.TopLevelSGF && "already emitted toplevel?!");
assert(!sgm.M.lookUpFunction(SWIFT_ENTRY_POINT_FUNCTION)
&& "already emitted toplevel?!");
assert(!sgm.M.lookUpFunction(
sgm.getASTContext().getEntryPointFunctionName()) &&
"already emitted toplevel?!");

RegularLocation TopLevelLoc = RegularLocation::getModuleLocation();
SILFunction *toplevel = sgm.emitTopLevelFunction(TopLevelLoc);
Expand Down Expand Up @@ -1940,8 +1942,9 @@ class SourceFileScope {
// If the source file contains an artificial main, emit the implicit
// toplevel code.
if (auto mainDecl = sf->getMainDecl()) {
assert(!sgm.M.lookUpFunction(SWIFT_ENTRY_POINT_FUNCTION)
&& "already emitted toplevel before main class?!");
assert(!sgm.M.lookUpFunction(
sgm.getASTContext().getEntryPointFunctionName()) &&
"already emitted toplevel before main class?!");

RegularLocation TopLevelLoc = RegularLocation::getModuleLocation();
SILFunction *toplevel = sgm.emitTopLevelFunction(TopLevelLoc);
Expand Down
3 changes: 2 additions & 1 deletion lib/TBDGen/TBDGenVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ class TBDGenVisitor : public ASTVisitor<TBDGenVisitor> {
// TBD for, and not for any statically linked libraries.
// FIXME: We should have a SymbolSource for main.
if (file->hasEntryPoint() && file->getParentModule() == SwiftModule)
addSymbol("main", SymbolSource::forUnknown());
addSymbol(SwiftModule->getASTContext().getEntryPointFunctionName(),
SymbolSource::forUnknown());
}

/// Adds the global symbols associated with the first file.
Expand Down
5 changes: 5 additions & 0 deletions test/SILGen/Inputs/forward-to-foobar.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
extern int foobar(int argc, char *argv[]);

int main(int argc, char *argv[]) {
return foobar(argc, argv);
}
9 changes: 9 additions & 0 deletions test/SILGen/other-entry-point-function-name.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// RUN: %empty-directory(%t)
// RUN: %target-clang -c --language=c %S/Inputs/forward-to-foobar.c -o %t/forward.o
// RUN: %target-build-swift %s %t/forward.o -Xfrontend -entry-point-function-name -Xfrontend foobar -o %t/main
// RUN: %target-run %t/main | %FileCheck %s

// CHECK: howdy from foobar
print("howdy from foobar")