[clang] 00072c0 - [WebAssembly] Mangle the argc/argv `main` as `__wasm_argc_argv`.
Dan Gohman via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 27 07:56:07 PST 2020
Author: Dan Gohman
Date: 2020-02-27T07:55:36-08:00
New Revision: 00072c08c75050ae2c835b7bb0e505475dbcd7b9
URL: https://github.com/llvm/llvm-project/commit/00072c08c75050ae2c835b7bb0e505475dbcd7b9
DIFF: https://github.com/llvm/llvm-project/commit/00072c08c75050ae2c835b7bb0e505475dbcd7b9.diff
LOG: [WebAssembly] Mangle the argc/argv `main` as `__wasm_argc_argv`.
WebAssembly enforces a rule that caller and callee signatures must
match. This means that the traditional technique of passing `main`
`argc` and `argv` even when it doesn't need them doesn't work.
Currently the backend renames `main` to `__original_main`, however this
doesn't interact well with LTO'ing libc, and the name isn't intuitive.
This patch allows us to transition to `__main_argc_argv` instead.
This implements the proposal in
https://github.com/WebAssembly/tool-conventions/pull/134
with a flag to disable it when targeting Emscripten, though this is
expected to be temporary, as discussed in the proposal comments.
Differential Revision: https://reviews.llvm.org/D70700
Added:
clang/test/CodeGen/wasm-call-main.c
clang/test/CodeGen/wasm-main.c
clang/test/CodeGen/wasm-main_argc_argv.c
Modified:
clang/lib/AST/Mangle.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/CodeGen/CodeGenModule.h
clang/lib/Frontend/InitHeaderSearch.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 6fd1840905b3..1a2cb29f0ec7 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -50,7 +50,8 @@ enum CCMangling {
CCM_Fast,
CCM_RegCall,
CCM_Vector,
- CCM_Std
+ CCM_Std,
+ CCM_WasmMainArgcArgv
};
static bool isExternC(const NamedDecl *ND) {
@@ -63,6 +64,16 @@ static CCMangling getCallingConvMangling(const ASTContext &Context,
const NamedDecl *ND) {
const TargetInfo &TI = Context.getTargetInfo();
const llvm::Triple &Triple = TI.getTriple();
+
+ // On wasm, the argc/argv form of "main" is renamed so that the startup code
+ // can call it with the correct function signature.
+ // On Emscripten, users may be exporting "main" and expecting to call it
+ // themselves, so we can't mangle it.
+ if (Triple.isWasm() && !Triple.isOSEmscripten())
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
+ if (FD->isMain() && FD->hasPrototype() && FD->param_size() == 2)
+ return CCM_WasmMainArgcArgv;
+
if (!Triple.isOSWindows() || !Triple.isX86())
return CCM_Other;
@@ -143,6 +154,12 @@ void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) {
const ASTContext &ASTContext = getASTContext();
CCMangling CC = getCallingConvMangling(ASTContext, D);
+
+ if (CC == CCM_WasmMainArgcArgv) {
+ Out << "__main_argc_argv";
+ return;
+ }
+
bool MCXX = shouldMangleCXXName(D);
const TargetInfo &TI = Context.getTargetInfo();
if (CC == CCM_Other || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) {
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 652efd857064..faff623a2973 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -448,6 +448,10 @@ void CodeGenModule::Release() {
CodeGenFunction(*this).EmitCfiCheckStub();
}
emitAtAvailableLinkGuard();
+ if (Context.getTargetInfo().getTriple().isWasm() &&
+ !Context.getTargetInfo().getTriple().isOSEmscripten()) {
+ EmitMainVoidAlias();
+ }
emitLLVMUsed();
if (SanStats)
SanStats->finish();
@@ -5600,6 +5604,17 @@ void CodeGenModule::EmitDeferredUnusedCoverageMappings() {
}
}
+void CodeGenModule::EmitMainVoidAlias() {
+ // In order to transition away from "__original_main" gracefully, emit an
+ // alias for "main" in the no-argument case so that libc can detect when
+ // new-style no-argument main is in used.
+ if (llvm::Function *F = getModule().getFunction("main")) {
+ if (!F->isDeclaration() && F->arg_size() == 0 && !F->isVarArg() &&
+ F->getReturnType()->isIntegerTy(Context.getTargetInfo().getIntWidth()))
+ addUsedGlobal(llvm::GlobalAlias::create("__main_void", F));
+ }
+}
+
/// Turns the given pointer into a constant.
static llvm::Constant *GetPointerConstant(llvm::LLVMContext &Context,
const void *Ptr) {
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index e8162fcfc0cd..48a3938ceeec 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -1023,6 +1023,9 @@ class CodeGenModule : public CodeGenTypeCache {
/// for the uninstrumented functions.
void EmitDeferredUnusedCoverageMappings();
+ /// Emit an alias for "main" if it has no arguments (needed for wasm).
+ void EmitMainVoidAlias();
+
/// Tell the consumer that this variable has been instantiated.
void HandleCXXStaticMemberVarInstantiation(VarDecl *VD);
diff --git a/clang/lib/Frontend/InitHeaderSearch.cpp b/clang/lib/Frontend/InitHeaderSearch.cpp
index 851f5a4cc05c..159cd47f7831 100644
--- a/clang/lib/Frontend/InitHeaderSearch.cpp
+++ b/clang/lib/Frontend/InitHeaderSearch.cpp
@@ -433,8 +433,7 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang,
break;
case llvm::Triple::UnknownOS:
- if (triple.getArch() == llvm::Triple::wasm32 ||
- triple.getArch() == llvm::Triple::wasm64)
+ if (triple.isWasm())
return;
break;
}
diff --git a/clang/test/CodeGen/wasm-call-main.c b/clang/test/CodeGen/wasm-call-main.c
new file mode 100644
index 000000000000..f22ba651c9b1
--- /dev/null
+++ b/clang/test/CodeGen/wasm-call-main.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple wasm32 -o - -emit-llvm %s | FileCheck %s
+
+// Mangle argc/argv main even when it's not defined in this TU.
+
+#include <stddef.h>
+
+int main(int argc, char *argv[]);
+
+int foo(void) {
+ return main(0, NULL);
+}
+
+// CHECK: call i32 @__main_argc_argv(
diff --git a/clang/test/CodeGen/wasm-main.c b/clang/test/CodeGen/wasm-main.c
new file mode 100644
index 000000000000..33dbdac2a5ba
--- /dev/null
+++ b/clang/test/CodeGen/wasm-main.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -triple wasm32 -o - -emit-llvm %s | FileCheck %s
+
+// Don't mangle the no-arg form of main.
+
+int main(void) {
+ return 0;
+}
+
+// CHECK-LABEL: define i32 @main()
diff --git a/clang/test/CodeGen/wasm-main_argc_argv.c b/clang/test/CodeGen/wasm-main_argc_argv.c
new file mode 100644
index 000000000000..194afc2fd5af
--- /dev/null
+++ b/clang/test/CodeGen/wasm-main_argc_argv.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -triple wasm32 -o - -emit-llvm %s | FileCheck %s
+
+// Mangle the argc/argv form of main.
+
+int main(int argc, char **argv) {
+ return 0;
+}
+
+// CHECK-LABEL: define i32 @__main_argc_argv(i32 %argc, i8** %argv)
More information about the cfe-commits
mailing list