Index: llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h =================================================================== --- llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h +++ llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h @@ -84,7 +84,7 @@ wasm::WasmSignature *Sig, bool &InvokeDetected); MCSymbol *getOrCreateWasmSymbol(StringRef Name); - void emitExternalDecls(const Module &M); + void emitDecls(const Module &M); }; } // end namespace llvm Index: llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp =================================================================== --- llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -291,7 +291,7 @@ } } -void WebAssemblyAsmPrinter::emitExternalDecls(const Module &M) { +void WebAssemblyAsmPrinter::emitDecls(const Module &M) { if (signaturesEmitted) return; signaturesEmitted = true; @@ -324,55 +324,56 @@ if (F.isIntrinsic()) continue; - // Emit function type info for all undefined functions - if (F.isDeclarationForLinker()) { - SmallVector Results; - SmallVector Params; - computeSignatureVTs(F.getFunctionType(), &F, F, TM, Params, Results); - // At this point these MCSymbols may or may not have been created already - // and thus also contain a signature, but we need to get the signature - // anyway here in case it is an invoke that has not yet been created. We - // will discard it later if it turns out not to be necessary. - auto Signature = signatureFromMVTs(Results, Params); - bool InvokeDetected = false; - auto *Sym = getMCSymbolForFunction( - &F, WebAssembly::WasmEnableEmEH || WebAssembly::WasmEnableEmSjLj, - Signature.get(), InvokeDetected); - - // Multiple functions can be mapped to the same invoke symbol. For - // example, two IR functions '__invoke_void_i8*' and '__invoke_void_i32' - // are both mapped to '__invoke_vi'. We keep them in a set once we emit an - // Emscripten EH symbol so we don't emit the same symbol twice. - if (InvokeDetected && !InvokeSymbols.insert(Sym).second) - continue; + // Emit function type info for all functions. This will emit duplicate + // information for defined functions (which already have function type + // info emitted alongside their definition), but this is necessary in + // order to enable the single-pass WebAssemblyAsmTypeCheck to succeed. + SmallVector Results; + SmallVector Params; + computeSignatureVTs(F.getFunctionType(), &F, F, TM, Params, Results); + // At this point these MCSymbols may or may not have been created already + // and thus also contain a signature, but we need to get the signature + // anyway here in case it is an invoke that has not yet been created. We + // will discard it later if it turns out not to be necessary. + auto Signature = signatureFromMVTs(Results, Params); + bool InvokeDetected = false; + auto *Sym = getMCSymbolForFunction( + &F, WebAssembly::WasmEnableEmEH || WebAssembly::WasmEnableEmSjLj, + Signature.get(), InvokeDetected); + + // Multiple functions can be mapped to the same invoke symbol. For + // example, two IR functions '__invoke_void_i8*' and '__invoke_void_i32' + // are both mapped to '__invoke_vi'. We keep them in a set once we emit an + // Emscripten EH symbol so we don't emit the same symbol twice. + if (InvokeDetected && !InvokeSymbols.insert(Sym).second) + continue; - Sym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); - if (!Sym->getSignature()) { - Sym->setSignature(Signature.get()); - addSignature(std::move(Signature)); - } else { - // This symbol has already been created and had a signature. Discard it. - Signature.reset(); - } + Sym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); + if (!Sym->getSignature()) { + Sym->setSignature(Signature.get()); + addSignature(std::move(Signature)); + } else { + // This symbol has already been created and had a signature. Discard it. + Signature.reset(); + } - getTargetStreamer()->emitFunctionType(Sym); + getTargetStreamer()->emitFunctionType(Sym); - if (F.hasFnAttribute("wasm-import-module")) { - StringRef Name = - F.getFnAttribute("wasm-import-module").getValueAsString(); - Sym->setImportModule(storeName(Name)); - getTargetStreamer()->emitImportModule(Sym, Name); - } - if (F.hasFnAttribute("wasm-import-name")) { - // If this is a converted Emscripten EH/SjLj symbol, we shouldn't use - // the original function name but the converted symbol name. - StringRef Name = - InvokeDetected - ? Sym->getName() - : F.getFnAttribute("wasm-import-name").getValueAsString(); - Sym->setImportName(storeName(Name)); - getTargetStreamer()->emitImportName(Sym, Name); - } + if (F.hasFnAttribute("wasm-import-module")) { + StringRef Name = + F.getFnAttribute("wasm-import-module").getValueAsString(); + Sym->setImportModule(storeName(Name)); + getTargetStreamer()->emitImportModule(Sym, Name); + } + if (F.hasFnAttribute("wasm-import-name")) { + // If this is a converted Emscripten EH/SjLj symbol, we shouldn't use + // the original function name but the converted symbol name. + StringRef Name = + InvokeDetected + ? Sym->getName() + : F.getFnAttribute("wasm-import-name").getValueAsString(); + Sym->setImportName(storeName(Name)); + getTargetStreamer()->emitImportName(Sym, Name); } if (F.hasFnAttribute("wasm-export-name")) { @@ -387,8 +388,8 @@ void WebAssemblyAsmPrinter::emitEndOfAsmFile(Module &M) { // This is required to emit external declarations (like .functypes) when // no functions are defined in the compilation unit and therefore, - // emitExternalDecls() is not called until now. - emitExternalDecls(M); + // emitDecls() is not called until now. + emitDecls(M); // When a function's address is taken, a TABLE_INDEX relocation is emitted // against the function symbol at the use site. However the relocation @@ -556,7 +557,7 @@ } void WebAssemblyAsmPrinter::emitConstantPool() { - emitExternalDecls(*MMI->getModule()); + emitDecls(*MMI->getModule()); assert(MF->getConstantPool()->getConstants().empty() && "WebAssembly disables constant pools"); } Index: llvm/test/CodeGen/WebAssembly/byval.ll =================================================================== --- llvm/test/CodeGen/WebAssembly/byval.ll +++ llvm/test/CodeGen/WebAssembly/byval.ll @@ -16,6 +16,11 @@ declare void @ext_byval_func_alignedstruct(%AlignedStruct* byval(%AlignedStruct)) declare void @ext_byval_func_empty(%EmptyStruct* byval(%EmptyStruct)) +; Skip past the functype directives, which interfere with the CHECK-LABEL +; matches. +; +; CHECK-LABEL: .section + ; CHECK-LABEL: byval_arg define void @byval_arg(%SmallStruct* %ptr) { ; CHECK: .functype byval_arg (i32) -> () Index: llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll =================================================================== --- llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll +++ llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll @@ -13,6 +13,13 @@ %class.Object = type { i8 } %class.MyClass = type { i32 } +; Skip past the functype directives, which interfere with the CHECK-LABEL +; matches. +; +; CHECK-LABEL: .section +; NOOPT-LABEL: .section +; NOSORT-LABEL: .section + ; Simple test case with two catch clauses ; ; void foo(); Index: llvm/test/CodeGen/WebAssembly/function-pointer64.ll =================================================================== --- llvm/test/CodeGen/WebAssembly/function-pointer64.ll +++ llvm/test/CodeGen/WebAssembly/function-pointer64.ll @@ -29,6 +29,9 @@ ; For simplicity (and compatibility with UB C/C++ code) we keep all types ; of pointers the same size, so function pointers (which are 32-bit indices ; in Wasm) are represented as 64-bit until called. +; +; Skip past the functype directives at the head of the output. +; CHECK-LABEL: .section ; CHECK: .functype foo (i64) -> () ; CHECK-NEXT: i32.const 1 Index: llvm/test/CodeGen/WebAssembly/functype-emission.ll =================================================================== --- llvm/test/CodeGen/WebAssembly/functype-emission.ll +++ llvm/test/CodeGen/WebAssembly/functype-emission.ll @@ -3,12 +3,10 @@ ; Demonstrates that appropriate .functype directives are emitted for defined ; functions, declared functions, and any libcalls. -; FIXME - functype directives should be emitted for defined functions as well, -; to ensure they pass the type checker (which requires any .functype to be -; encountered ahead of a call to that target). - ; CHECK: .functype __unordtf2 (i64, i64, i64, i64) -> (i32) ; CHECK: .functype __multi3 (i32, i64, i64, i64, i64) -> () +; CHECK: .functype defined_fun_1 (f64) -> (i64) +; CHECK: .functype defined_fun_2 (f64, i32) -> (i64) ; CHECK: .functype declared_fun (i32, f32, i64) -> (i32) define i64 @defined_fun_1(double %a) { Index: llvm/test/CodeGen/WebAssembly/inlineasm-output-template.ll =================================================================== --- llvm/test/CodeGen/WebAssembly/inlineasm-output-template.ll +++ llvm/test/CodeGen/WebAssembly/inlineasm-output-template.ll @@ -1,5 +1,10 @@ ; RUN: llc -mtriple=wasm32 < %s | FileCheck %s +; Skip past the functype directives, which interfere with the CHECK-LABEL +; matches. +; +; CHECK-LABEL: .section + ; Test that %c works with immediates ; CHECK-LABEL: test_inlineasm_c_output_template0 ; CHECK: #TEST 42 Index: llvm/test/CodeGen/WebAssembly/multi-return.ll =================================================================== --- llvm/test/CodeGen/WebAssembly/multi-return.ll +++ llvm/test/CodeGen/WebAssembly/multi-return.ll @@ -5,6 +5,11 @@ ; Return multiple values, some of which will be legalized into multiple values. declare { i64, i128, i192, i128, i64 } @return_multi_multi() +; Skip past the functype directives, which interfere with the CHECK-LABEL +; matches. +; +; CHECK-LABEL: .section + ; Test returning a single value from @return_multi_multi. define i64 @test0() { Index: llvm/test/CodeGen/WebAssembly/stack-protector.ll =================================================================== --- llvm/test/CodeGen/WebAssembly/stack-protector.ll +++ llvm/test/CodeGen/WebAssembly/stack-protector.ll @@ -2,6 +2,11 @@ @"\01LC" = internal constant [11 x i8] c"buf == %s\0A\00" ; <[11 x i8]*> [#uses=1] +; Skip past the functype directives, which interfere with the CHECK-LABEL +; matches. +; +; WASM32-LABEL: .section + ; WASM32-LABEL: test ; WASM32: i32.load 28 ; WASM32: br_if 0 Index: llvm/test/MC/WebAssembly/stack-ptr-mclower.ll =================================================================== --- llvm/test/MC/WebAssembly/stack-ptr-mclower.ll +++ llvm/test/MC/WebAssembly/stack-ptr-mclower.ll @@ -18,6 +18,9 @@ ; CHECK: .text ; CHECK-NEXT: .file "stack-ptr-mclower.ll" ; CHECK-NEXT: .globaltype __stack_pointer, [[PTR]] +; CHECK-NEXT: .functype bar () -> () +; CHECK-NEXT: .functype foo () -> () + ; CHECK-NEXT: .section .text.bar,"",@ ; CHECK-NEXT: .hidden bar ; CHECK-NEXT: .globl bar