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

Conversation

nate-chandler
Copy link
Contributor

Previously, the name of the entry point function was always main. Here, a new frontend flag is added to enable an arbitrary name to be specified.

rdar://58275758

@nate-chandler
Copy link
Contributor Author

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 3590dcd4d28f55a8c3927cae9992fff8b3bd3173

@nate-chandler
Copy link
Contributor Author

@swift-ci please clean test

@nate-chandler
Copy link
Contributor Author

@swift-ci please asan test

@nate-chandler nate-chandler force-pushed the other-main branch 2 times, most recently from 4342e3f to e552c15 Compare January 26, 2021 02:52
@nate-chandler
Copy link
Contributor Author

@swift-ci please clean test

@nate-chandler
Copy link
Contributor Author

@swift-ci please asan test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - e552c1521f325208bbe45803068e5e80394539e1

@nate-chandler
Copy link
Contributor Author

@swift-ci please clean test

@nate-chandler
Copy link
Contributor Author

@swift-ci please asan test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 652c26ca9fbcbc19769b880d7fb08ecda57e6887

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 652c26ca9fbcbc19769b880d7fb08ecda57e6887

@nate-chandler
Copy link
Contributor Author

@swift-ci please test macos platform

1 similar comment
@nate-chandler
Copy link
Contributor Author

@swift-ci please test macos platform

@@ -0,0 +1,9 @@
// RUN: %target-run-simple-swift(-Xfrontend -entry-point-function-name -Xfrontend foobar -Xlinker -e -Xlinker _foobar) | %FileCheck %s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably isn't a great test because -e controls the name of start, not the name of main, and we still want dynamic linker and C runtime initialization to happen before we enter main. Maybe link against a little stub .o file that provides a main and forwards to _foobar? That should also be more portable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How's https://github.com/apple/swift/pull/35595/files#diff-a8bcdd22afab25318feddb2667ef722aa57064b5fc9c8bd406de22ad34c1e162R4 for the source for the .o file that provides main and forwards to _foobar?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that envp is the third argument, at least on some platforms?

I wonder how easy it will be to create a portable stub that works on all platforms. It shouldn't be super-difficult, but there might have to be some on-going engineering due to subtleties.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Swift's generated main doesn't use any arguments other than argc or argv, so I think this should be OK.

Copy link
Member

@compnerd compnerd Jan 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

main on Windows is definitely more interesting:

int main(int argc, char *argv[], char *envp[]);
int wmain(int argc, wchar_t *argv[], wchar_t *envp[]);
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nCmdShow);
int wWinMain(HINSTANCE hINstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow);

In general, on Windows, you want to use the wide variant to handle unicode (the non-wide variant is limited to ASCII).

Copy link
Contributor Author

@nate-chandler nate-chandler Jan 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@compnerd Which of those entry points are currently used for Swift's generated main on Windows?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jckarter Were there other changes to the test? It is using the .o file generated from the source linked above to forward main to _foobar (and runs on all platforms). https://github.com/apple/swift/pull/35595/files#diff-a522629ea40edb88675159bc50bd75bae5a0cf4ab8038c781df4790a270af888R3

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@compnerd But we don't ever generate anything other than the standard main today, do we? This should be fine for now, since we'd probably have some opt-in way to use alternative entry points in the future.

@nate-chandler
Copy link
Contributor Author

@swift-ci please test

@nate-chandler
Copy link
Contributor Author

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 3cd71e32d73d777e6b3f63717c19b0bb14dcd96f

Previously, the name of the entry point function was always main.  Here,
a new frontend flag is added to enable an arbitrary name to be
specified.

rdar://58275758
@nate-chandler
Copy link
Contributor Author

@swift-ci please test

@abertelrud
Copy link
Contributor

Thank you very much for your work on this, @nate-chandler! The semantics of the change looks good to me, with the only question being what is the best way is for SwiftPM (and any IDEs that use libSwiftPM) to construct the stub that calls main for the case where an executable does need to be produced.

@tbkka
Copy link
Contributor

tbkka commented Jan 26, 2021

@abertelrud You just need to write out a short source file and compile it to generate the stub. In C, that generated source would look like this:

extern int _foo_main(int, char **);
int main(int argc, char **argv) {
   return _foo_main(argc, argv);
}

You should also be able to write out a main.swift file with appropriate attributes to get the C linkage and compiling that. I think that looks something like this, though I'm certain I've mixed up some details:

// Declare `foo_main_impl` as the Swift name used to call the C function `_foo_main`
@_silgen_name("_foo_main")
func foo_main_impl(_: Int, _: UnsafeMutablePointer<UnsafeMutablePointer<UTF8.CodeUnit>>) -> Int

// Call that function, forwarding the C argc, argv values
foo_main_impl(C_ARGC, C_ARGV)

@abertelrud
Copy link
Contributor

@abertelrud You just need to write out a short source file and compile it to generate the stub. In C, that generated source would look like this:

extern int _foo_main(int, char **);
int main(int argc, char **argv) {
   return _foo_main(argc, argv);
}

You should also be able to write out a main.swift file with appropriate attributes to get the C linkage and compiling that. I think that looks something like this, though I'm certain I've mixed up some details:

// Declare `foo_main_impl` as the Swift name used to call the C function `_foo_main`
@_silgen_name("_foo_main")
func foo_main_impl(_: Int, _: UnsafeMutablePointer<UnsafeMutablePointer<UTF8.CodeUnit>>) -> Int

// Call that function, forwarding the C argc, argv values
foo_main_impl(C_ARGC, C_ARGV)

Thanks for the details! It sounds as if this might still not be quite enough for Windows, based on earlier comments in the PR. I'm mildly concerned that this might be something that has to be customized per platform, and also that each client of libSwiftPM will need to implement this source generation, but I don't see a good way to avoid it given the goal of being able to link unit tests against the main modules of executables.

@nate-chandler
Copy link
Contributor Author

@abertelrud It sounds like just supporting main should be enough since the other entry points aren't currently being emitted. It also sounds like just passing argc and argv should be sufficient on all platforms. Do those two things together mean that this isn't something that needs to be customized per platform?

@abertelrud
Copy link
Contributor

Thanks @nate-chandler and @tbkka!

So just to summarize, with this option SwiftPM would be able to build the main module of the executable to have its _main instead named (say) _foo_main, which means that a test could link against it without problem. When building the actual executable, SwiftPM (and IDEs using libSwiftPM) would also generate and compile a stub containing:

extern int _foo_main(int, char **);
int main(int argc, char **argv) {
   return _foo_main(argc, argv);
}

This is expected to work on all platforms. SwiftPM already generates stub sources for things like the resource bundle accessor, so this would be in line with that.

Sounds as if this solution will work, especially in light of the comment above that the envp parameter isn't used by the generated _main today. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants