-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Driver: add support for the WebAssembly toolchain #39299
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
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,246 @@ | ||
//===---- WebAssemblyToolChains.cpp - Job invocations (WebAssembly-specific) | ||
//------===// | ||
// | ||
// This source file is part of the Swift.org open source project | ||
// | ||
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors | ||
// Licensed under Apache License v2.0 with Runtime Library Exception | ||
// | ||
// See https://swift.org/LICENSE.txt for license information | ||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "ToolChains.h" | ||
|
||
#include "swift/ABI/System.h" | ||
#include "swift/AST/DiagnosticsDriver.h" | ||
#include "swift/Basic/LLVM.h" | ||
#include "swift/Basic/Platform.h" | ||
#include "swift/Basic/Range.h" | ||
#include "swift/Config.h" | ||
#include "swift/Driver/Compilation.h" | ||
#include "swift/Driver/Driver.h" | ||
#include "swift/Driver/Job.h" | ||
#include "swift/Option/Options.h" | ||
#include "swift/Option/SanitizerOptions.h" | ||
#include "clang/Basic/Version.h" | ||
#include "clang/Driver/Util.h" | ||
#include "llvm/ADT/StringSwitch.h" | ||
#include "llvm/Option/Arg.h" | ||
#include "llvm/Option/ArgList.h" | ||
#include "llvm/ProfileData/InstrProf.h" | ||
#include "llvm/Support/FileSystem.h" | ||
#include "llvm/Support/Path.h" | ||
#include "llvm/Support/Process.h" | ||
#include "llvm/Support/Program.h" | ||
|
||
using namespace swift; | ||
using namespace swift::driver; | ||
using namespace llvm::opt; | ||
|
||
std::string | ||
toolchains::WebAssembly::sanitizerRuntimeLibName(StringRef Sanitizer, | ||
bool shared) const { | ||
return (Twine("clang_rt.") + Sanitizer + "-" + | ||
this->getTriple().getArchName() + ".lib") | ||
.str(); | ||
} | ||
|
||
ToolChain::InvocationInfo toolchains::WebAssembly::constructInvocation( | ||
const AutolinkExtractJobAction &job, const JobContext &context) const { | ||
assert(context.Output.getPrimaryOutputType() == file_types::TY_AutolinkFile); | ||
|
||
InvocationInfo II{"swift-autolink-extract"}; | ||
ArgStringList &Arguments = II.Arguments; | ||
II.allowsResponseFiles = true; | ||
|
||
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args, | ||
file_types::TY_Object); | ||
addInputsOfType(Arguments, context.InputActions, file_types::TY_Object); | ||
|
||
Arguments.push_back("-o"); | ||
Arguments.push_back( | ||
context.Args.MakeArgString(context.Output.getPrimaryOutputFilename())); | ||
|
||
return II; | ||
} | ||
|
||
ToolChain::InvocationInfo | ||
toolchains::WebAssembly::constructInvocation(const DynamicLinkJobAction &job, | ||
const JobContext &context) const { | ||
assert(context.Output.getPrimaryOutputType() == file_types::TY_Image && | ||
"Invalid linker output type."); | ||
|
||
ArgStringList Arguments; | ||
|
||
std::string Target = getTriple().str(); | ||
if (!Target.empty()) { | ||
Arguments.push_back("-target"); | ||
Arguments.push_back(context.Args.MakeArgString(Target)); | ||
} | ||
|
||
switch (job.getKind()) { | ||
case LinkKind::None: | ||
llvm_unreachable("invalid link kind"); | ||
case LinkKind::Executable: | ||
// Default case, nothing extra needed. | ||
break; | ||
case LinkKind::DynamicLibrary: | ||
llvm_unreachable("WebAssembly doesn't support dynamic library yet"); | ||
case LinkKind::StaticLibrary: | ||
llvm_unreachable("invalid link kind"); | ||
} | ||
|
||
// Select the linker to use. | ||
std::string Linker; | ||
if (const Arg *A = context.Args.getLastArg(options::OPT_use_ld)) { | ||
Linker = A->getValue(); | ||
} | ||
if (!Linker.empty()) | ||
Arguments.push_back(context.Args.MakeArgString("-fuse-ld=" + Linker)); | ||
|
||
const char *Clang = "clang"; | ||
if (const Arg *A = context.Args.getLastArg(options::OPT_tools_directory)) { | ||
StringRef toolchainPath(A->getValue()); | ||
|
||
// If there is a clang in the toolchain folder, use that instead. | ||
if (auto tool = llvm::sys::findProgramByName("clang", {toolchainPath})) | ||
Clang = context.Args.MakeArgString(tool.get()); | ||
} | ||
|
||
SmallVector<std::string, 4> RuntimeLibPaths; | ||
getRuntimeLibraryPaths(RuntimeLibPaths, context.Args, context.OI.SDKPath, | ||
/*Shared=*/false); | ||
|
||
SmallString<128> SharedResourceDirPath; | ||
getResourceDirPath(SharedResourceDirPath, context.Args, /*Shared=*/false); | ||
|
||
SmallString<128> swiftrtPath = SharedResourceDirPath; | ||
llvm::sys::path::append(swiftrtPath, | ||
swift::getMajorArchitectureName(getTriple())); | ||
llvm::sys::path::append(swiftrtPath, "swiftrt.o"); | ||
Arguments.push_back(context.Args.MakeArgString(swiftrtPath)); | ||
|
||
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args, | ||
file_types::TY_Object); | ||
addInputsOfType(Arguments, context.InputActions, file_types::TY_Object); | ||
addInputsOfType(Arguments, context.InputActions, file_types::TY_LLVM_BC); | ||
|
||
if (!context.OI.SDKPath.empty()) { | ||
Arguments.push_back("--sysroot"); | ||
Arguments.push_back(context.Args.MakeArgString(context.OI.SDKPath)); | ||
} | ||
|
||
// Add any autolinking scripts to the arguments | ||
for (const Job *Cmd : context.Inputs) { | ||
auto &OutputInfo = Cmd->getOutput(); | ||
if (OutputInfo.getPrimaryOutputType() == file_types::TY_AutolinkFile) | ||
Arguments.push_back(context.Args.MakeArgString( | ||
Twine("@") + OutputInfo.getPrimaryOutputFilename())); | ||
} | ||
|
||
// Add the runtime library link paths. | ||
for (auto path : RuntimeLibPaths) { | ||
Arguments.push_back("-L"); | ||
Arguments.push_back(context.Args.MakeArgString(path)); | ||
} | ||
// Link the standard library. In two paths, we do this using a .lnk file; | ||
// if we're going that route, we'll set `linkFilePath` to the path to that | ||
// file. | ||
SmallString<128> linkFilePath; | ||
getResourceDirPath(linkFilePath, context.Args, /*Shared=*/false); | ||
llvm::sys::path::append(linkFilePath, "static-executable-args.lnk"); | ||
|
||
auto linkFile = linkFilePath.str(); | ||
if (llvm::sys::fs::is_regular_file(linkFile)) { | ||
Arguments.push_back(context.Args.MakeArgString(Twine("@") + linkFile)); | ||
} else { | ||
llvm::report_fatal_error(linkFile + " not found"); | ||
} | ||
|
||
// Delegate to Clang for sanitizers. It will figure out the correct linker | ||
// options. | ||
if (job.getKind() == LinkKind::Executable && context.OI.SelectedSanitizers) { | ||
Arguments.push_back(context.Args.MakeArgString( | ||
"-fsanitize=" + getSanitizerList(context.OI.SelectedSanitizers))); | ||
} | ||
|
||
if (context.Args.hasArg(options::OPT_profile_generate)) { | ||
SmallString<128> LibProfile(SharedResourceDirPath); | ||
llvm::sys::path::remove_filename(LibProfile); // remove platform name | ||
llvm::sys::path::append(LibProfile, "clang", "lib"); | ||
|
||
llvm::sys::path::append(LibProfile, getTriple().getOSName(), | ||
Twine("libclang_rt.profile-") + | ||
getTriple().getArchName() + ".a"); | ||
Arguments.push_back(context.Args.MakeArgString(LibProfile)); | ||
Arguments.push_back(context.Args.MakeArgString( | ||
Twine("-u", llvm::getInstrProfRuntimeHookVarName()))); | ||
} | ||
|
||
// Run clang++ in verbose mode if "-v" is set | ||
if (context.Args.hasArg(options::OPT_v)) { | ||
Arguments.push_back("-v"); | ||
} | ||
|
||
// WebAssembly doesn't reserve low addresses But without "extra inhabitants" | ||
// of the pointer representation, runtime performance and memory footprint are | ||
// worse. So assume that compiler driver uses wasm-ld and --global-base=1024 | ||
// to reserve low 1KB. | ||
Arguments.push_back("-Xlinker"); | ||
|
||
// These custom arguments should be right before the object file at the end. | ||
context.Args.AddAllArgs(Arguments, options::OPT_linker_option_Group); | ||
context.Args.AddAllArgs(Arguments, options::OPT_Xlinker); | ||
context.Args.AddAllArgValues(Arguments, options::OPT_Xclang_linker); | ||
|
||
// This should be the last option, for convenience in checking output. | ||
Arguments.push_back("-o"); | ||
Arguments.push_back( | ||
context.Args.MakeArgString(context.Output.getPrimaryOutputFilename())); | ||
|
||
InvocationInfo II{Clang, Arguments}; | ||
II.allowsResponseFiles = true; | ||
|
||
return II; | ||
} | ||
|
||
void validateLinkerArguments(DiagnosticEngine &diags, | ||
ArgStringList linkerArgs) { | ||
for (auto arg : linkerArgs) { | ||
if (StringRef(arg).startswith("--global-base=")) { | ||
diags.diagnose(SourceLoc(), diag::error_wasm_doesnt_support_global_base); | ||
} | ||
} | ||
} | ||
void toolchains::WebAssembly::validateArguments(DiagnosticEngine &diags, | ||
const llvm::opt::ArgList &args, | ||
StringRef defaultTarget) const { | ||
ArgStringList linkerArgs; | ||
args.AddAllArgValues(linkerArgs, options::OPT_Xlinker); | ||
validateLinkerArguments(diags, linkerArgs); | ||
} | ||
|
||
ToolChain::InvocationInfo | ||
toolchains::WebAssembly::constructInvocation(const StaticLinkJobAction &job, | ||
const JobContext &context) const { | ||
assert(context.Output.getPrimaryOutputType() == file_types::TY_Image && | ||
"Invalid linker output type."); | ||
|
||
ArgStringList Arguments; | ||
|
||
const char *AR = "llvm-ar"; | ||
Arguments.push_back("crs"); | ||
|
||
Arguments.push_back( | ||
context.Args.MakeArgString(context.Output.getPrimaryOutputFilename())); | ||
|
||
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args, | ||
file_types::TY_Object); | ||
addInputsOfType(Arguments, context.InputActions, file_types::TY_Object); | ||
|
||
InvocationInfo II{AR, Arguments}; | ||
|
||
return II; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
// RUN: %swiftc_driver -driver-print-jobs -target wasm32-unknown-wasi -v %s 2>&1 | %FileCheck %s -check-prefix=CHECK-WASM | ||
|
||
// CHECK-WASM: swift{{.*}} -frontend -c -primary-file {{.*}} -target wasm32-unknown-wasi -disable-objc-interop | ||
// CHECK-WASM: clang{{.*}} -lswiftCore --target=wasm32-unknown-wasi -v {{.*}}-o |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.