Index: lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp +++ lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp @@ -23,6 +23,7 @@ //===----------------------------------------------------------------------===// #include "WebAssembly.h" +#include "llvm/ADT/Triple.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" @@ -226,6 +227,23 @@ return Wrapper; } +// Test whether a main function with type FuncTy should be rewritten to have +// type MainTy. +bool ShouldFixMainFunction(FunctionType *FuncTy, + FunctionType *MainTy, + Module &M) { + if (Triple(M.getTargetTriple()).isOSWASI()) { + // For WASI, only fix the main function if it's the standard zero-arg form. + // That way, the standard cases will work as expected, and users will see + // signature mismatches from the linker for non-standard cases. + return FuncTy->getReturnType() == MainTy->getReturnType() && + FuncTy->getNumParams() == 0 && + !FuncTy->isVarArg(); + } + + return FuncTy != MainTy; +} + bool FixFunctionBitcasts::runOnModule(Module &M) { LLVM_DEBUG(dbgs() << "********** Fix Function Bitcasts **********\n"); @@ -234,6 +252,12 @@ SmallVector, 0> Uses; SmallPtrSet ConstantBCs; + // In general, main-function fixup is disabled because it breaks some tests + // involving three-argument (with envp) main functions. On WASI, + // three-argument main functions are not supported. + bool FixMainFunctions = Triple(M.getTargetTriple()).isOSWASI() || + !TemporaryWorkarounds; + // Collect all the places that need wrappers. for (Function &F : M) { FindUses(&F, F, Uses, ConstantBCs); @@ -242,14 +266,14 @@ // "int main(int argc, char *argv[])", create an artificial call with it // bitcasted to that type so that we generate a wrapper for it, so that // the C runtime can call it. - if (!TemporaryWorkarounds && !F.isDeclaration() && F.getName() == "main") { + if (FixMainFunctions && !F.isDeclaration() && F.getName() == "main") { Main = &F; LLVMContext &C = M.getContext(); Type *MainArgTys[] = {Type::getInt32Ty(C), PointerType::get(Type::getInt8PtrTy(C), 0)}; FunctionType *MainTy = FunctionType::get(Type::getInt32Ty(C), MainArgTys, /*isVarArg=*/false); - if (F.getFunctionType() != MainTy) { + if (ShouldFixMainFunction(F.getFunctionType(), MainTy, M)) { LLVM_DEBUG(dbgs() << "Found `main` function with incorrect type: " << *F.getFunctionType() << "\n"); Value *Args[] = {UndefValue::get(MainArgTys[0]), Index: test/CodeGen/WebAssembly/wasi-main-no-args.ll =================================================================== --- test/CodeGen/WebAssembly/wasi-main-no-args.ll +++ test/CodeGen/WebAssembly/wasi-main-no-args.ll @@ -1,16 +1,17 @@ -; RUN: llc < %s -asm-verbose=false -wasm-temporary-workarounds=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false | FileCheck %s ; Test main functions with alternate signatures. target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" -target triple = "wasm32-unknown-unknown" +target triple = "wasm32-unknown-wasi" -define void @main() { - ret void +define i32 @main() { + ret i32 0 } ; CHECK-LABEL: .L__original_main: -; CHECK-NEXT: .functype .L__original_main () -> () +; CHECK-NEXT: .functype .L__original_main () -> (i32) +; CHECK-NEXT: i32.const 0 ; CHECK-NEXT: end_function ; CHECK-LABEL: main: Index: test/CodeGen/WebAssembly/wasi-main-three-args.ll =================================================================== --- test/CodeGen/WebAssembly/wasi-main-three-args.ll +++ test/CodeGen/WebAssembly/wasi-main-three-args.ll @@ -1,15 +1,16 @@ -; RUN: llc < %s -asm-verbose=false -wasm-temporary-workarounds=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false | FileCheck %s -; Test that main function with expected signature is not wrapped +; Test that main function with a non-standard third argument is +; not wrapped on WASI. target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" -target triple = "wasm32-unknown-unknown" +target triple = "wasm32-unknown-wasi" -define i32 @main(i32 %a, i8** %b) { +define i32 @main(i32 %a, i8** %b, i8** %c) { ret i32 0 } ; CHECK-LABEL: main: -; CHECK-NEXT: .functype main (i32, i32) -> (i32) +; CHECK-NEXT: .functype main (i32, i32, i32) -> (i32) ; CHECK-NOT: __original_main: Index: test/CodeGen/WebAssembly/wasi-main-with-args.ll =================================================================== --- test/CodeGen/WebAssembly/wasi-main-with-args.ll +++ test/CodeGen/WebAssembly/wasi-main-with-args.ll @@ -1,9 +1,9 @@ -; RUN: llc < %s -asm-verbose=false -wasm-temporary-workarounds=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false | FileCheck %s ; Test that main function with expected signature is not wrapped target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" -target triple = "wasm32-unknown-unknown" +target triple = "wasm32-unknown-wasi" define i32 @main(i32 %a, i8** %b) { ret i32 0