Skip to content

Commit de4872b

Browse files
Merge pull request #33246 from nate-chandler/emit-main-into-entry-segment
[IRGen] Add main() to __swift5_entry.
2 parents 2840f4f + 28cc144 commit de4872b

File tree

5 files changed

+106
-2
lines changed

5 files changed

+106
-2
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,8 @@ void IRGenerator::emitGlobalTopLevel(
11181118
IRGenModule *IGM = Iter.second;
11191119
IGM->finishEmitAfterTopLevel();
11201120
}
1121+
1122+
emitEntryPointInfo();
11211123
}
11221124

11231125
void IRGenModule::finishEmitAfterTopLevel() {
@@ -1805,6 +1807,44 @@ void IRGenModule::emitVTableStubs() {
18051807
}
18061808
}
18071809

1810+
static std::string getEntryPointSection(IRGenModule &IGM) {
1811+
std::string sectionName;
1812+
switch (IGM.TargetInfo.OutputObjectFormat) {
1813+
case llvm::Triple::UnknownObjectFormat:
1814+
llvm_unreachable("Don't know how to emit field records table for "
1815+
"the selected object format.");
1816+
case llvm::Triple::MachO:
1817+
sectionName = "__TEXT, __swift5_entry, regular, no_dead_strip";
1818+
break;
1819+
case llvm::Triple::ELF:
1820+
case llvm::Triple::Wasm:
1821+
sectionName = "swift5_entry";
1822+
break;
1823+
case llvm::Triple::XCOFF:
1824+
case llvm::Triple::COFF:
1825+
sectionName = ".sw5entr$B";
1826+
break;
1827+
}
1828+
return sectionName;
1829+
}
1830+
1831+
void IRGenerator::emitEntryPointInfo() {
1832+
SILFunction *entrypoint = nullptr;
1833+
if (!(entrypoint = SIL.lookUpFunction(SWIFT_ENTRY_POINT_FUNCTION))) {
1834+
return;
1835+
}
1836+
auto &IGM = *getGenModule(entrypoint);
1837+
ConstantInitBuilder builder(IGM);
1838+
auto entrypointInfo = builder.beginStruct();
1839+
entrypointInfo.addRelativeAddress(
1840+
IGM.getAddrOfSILFunction(entrypoint, NotForDefinition));
1841+
auto var = entrypointInfo.finishAndCreateGlobal(
1842+
"\x01l_entry_point", Alignment(4),
1843+
/*isConstant*/ true, llvm::GlobalValue::PrivateLinkage);
1844+
var->setSection(getEntryPointSection(IGM));
1845+
IGM.addUsedGlobal(var);
1846+
}
1847+
18081848
static IRLinkage
18091849
getIRLinkage(const UniversalLinkageInfo &info, SILLinkage linkage,
18101850
ForDefinition_t isDefinition, bool isWeakImported,

lib/IRGen/IRGenModule.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,9 @@ class IRGenerator {
400400
// Emit the code to replace dynamicReplacement(for:) functions.
401401
void emitDynamicReplacements();
402402

403+
// Emit info that describes the entry point to the module, if it has one.
404+
void emitEntryPointInfo();
405+
403406
/// Checks if metadata for this type can be emitted lazily. This is true for
404407
/// non-public types as well as imported types, except for classes and
405408
/// protocols which are always emitted eagerly.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@main
2+
struct Entry {
3+
static func main() {
4+
print("howdy mundo")
5+
}
6+
}

test/IRGen/entrypoint-section-run.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %clang %s -isysroot %sdk -o %t/main
3+
// RUN: %target-codesign %t/main
4+
// RUN: %target-build-swift %S/Inputs/at-main-struct-simple.swift -O -parse-as-library -emit-library -o %t/libHowdy.dylib -module-name Howdy
5+
// RUN: %target-run %t/main %t/libHowdy.dylib | %FileCheck %s
6+
7+
// REQUIRES: OS=macosx,CPU=x86_64
8+
// REQUIRES: executable_test
9+
// UNSUPPORTED: remote_run
10+
11+
#include <dlfcn.h>
12+
#include <mach-o/dyld.h>
13+
#include <mach-o/getsect.h>
14+
#include <stdio.h>
15+
#include <string.h>
16+
17+
int main(int argc, char *argv[]) {
18+
if (argc != 2) {
19+
printf("no argument!\n");
20+
return 1;
21+
}
22+
auto *dylibPath = argv[1];
23+
auto *handle = dlopen(dylibPath, RTLD_LAZY);
24+
if (!handle) {
25+
printf("no library!\n");
26+
return 1;
27+
}
28+
29+
using MainFunction = void(int, char *[]);
30+
MainFunction *mainFunction = nullptr;
31+
for (int index = 0; index < _dyld_image_count(); ++index) {
32+
auto *imageName = _dyld_get_image_name(index);
33+
if (strcmp(dylibPath, imageName)) {
34+
printf("skipping %s\n", imageName);
35+
continue;
36+
}
37+
auto *header =
38+
reinterpret_cast<const mach_header_64 *>(_dyld_get_image_header(index));
39+
size_t size;
40+
auto *data = getsectiondata(header, "__TEXT", "__swift5_entry", &size);
41+
int32_t offset = *reinterpret_cast<int32_t *>(data);
42+
mainFunction = reinterpret_cast<MainFunction *>(
43+
reinterpret_cast<int64_t>(data) + offset);
44+
45+
break;
46+
}
47+
if (!mainFunction) {
48+
printf("no function!");
49+
return 1;
50+
}
51+
mainFunction(argc, argv); // CHECK: howdy mundo
52+
}

test/IRGen/unused.sil

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,11 @@ bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>
5252
return %3 : $Int32 // id: %4
5353
}
5454

55-
// CHECK-macho: @llvm.used = appending global [3 x i8*] [i8* bitcast (void ()* @frieda to i8*), i8* bitcast (i32 (i32, i8**)* @main to i8*), i8* bitcast (i16* @__swift_reflection_version to i8*)], section "llvm.metadata"
56-
// CHECK-elf: @llvm.used = appending global [4 x i8*] [i8* bitcast (void ()* @frieda to i8*), i8* bitcast (i32 (i32, i8**)* @main to i8*), i8* bitcast (i16* @__swift_reflection_version to i8*), i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @_swift1_autolink_entries, i32 0, i32 0)], section "llvm.metadata"
55+
// CHECK-macho: @"\01l_entry_point" = private constant { i32 } { i32 trunc (i64 sub (i64 ptrtoint (i32 (i32, i8**)* @main to i64), i64 ptrtoint ({ i32 }* @"\01l_entry_point" to i64)) to i32) }, section "__TEXT, __swift5_entry, regular, no_dead_strip", align 4
56+
// CHECK-elf: @"\01l_entry_point" = private constant { i32 } { i32 trunc (i64 sub (i64 ptrtoint (i32 (i32, i8**)* @main to i64), i64 ptrtoint ({ i32 }* @"\01l_entry_point" to i64)) to i32) }, section "swift5_entry", align 4
57+
58+
// CHECK-macho: @llvm.used = appending global [4 x i8*] [i8* bitcast (void ()* @frieda to i8*), i8* bitcast (i32 (i32, i8**)* @main to i8*), i8* bitcast ({ i32 }* @"\01l_entry_point" to i8*), i8* bitcast (i16* @__swift_reflection_version to i8*)], section "llvm.metadata", align 8
59+
// CHECK-elf: @llvm.used = appending global [5 x i8*] [i8* bitcast (void ()* @frieda to i8*), i8* bitcast (i32 (i32, i8**)* @main to i8*), i8* bitcast ({ i32 }* @"\01l_entry_point" to i8*), i8* bitcast (i16* @__swift_reflection_version to i8*), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @_swift1_autolink_entries, i32 0, i32 0)], section "llvm.metadata", align 8
5760

5861
// CHECK: define linkonce_odr hidden swiftcc void @qux()
5962
// CHECK: define hidden swiftcc void @fred()

0 commit comments

Comments
 (0)