Index: llvm/trunk/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ llvm/trunk/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -489,6 +489,7 @@ if (pop(Name, Block)) return true; } else if (Name == "end_function") { + ensureLocals(getStreamer()); CurrentState = EndFunction; if (pop(Name, Function) || ensureEmptyNestingStack()) return true; @@ -758,6 +759,19 @@ return true; // We didn't process this directive. } + // Called either when the first instruction is parsed of the function ends. + void ensureLocals(MCStreamer &Out) { + if (CurrentState == FunctionStart) { + // We haven't seen a .local directive yet. The streamer requires locals to + // be encoded as a prelude to the instructions, so emit an empty list of + // locals here. + auto &TOut = reinterpret_cast( + *Out.getTargetStreamer()); + TOut.emitLocal(SmallVector()); + CurrentState = FunctionLocals; + } + } + bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned & /*Opcode*/, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, @@ -768,15 +782,7 @@ MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); switch (MatchResult) { case Match_Success: { - if (CurrentState == FunctionStart) { - // This is the first instruction in a function, but we haven't seen - // a .local directive yet. The streamer requires locals to be encoded - // as a prelude to the instructions, so emit an empty list of locals - // here. - auto &TOut = reinterpret_cast( - *Out.getTargetStreamer()); - TOut.emitLocal(SmallVector()); - } + ensureLocals(Out); // Fix unknown p2align operands. auto Align = WebAssembly::GetDefaultP2AlignAny(Inst.getOpcode()); if (Align != -1U) { Index: llvm/trunk/test/MC/WebAssembly/basic-assembly.s =================================================================== --- llvm/trunk/test/MC/WebAssembly/basic-assembly.s +++ llvm/trunk/test/MC/WebAssembly/basic-assembly.s @@ -2,6 +2,11 @@ # Check that it converts to .o without errors, but don't check any output: # RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj -mattr=+atomics,+unimplemented-simd128,+nontrapping-fptoint,+exception-handling -o %t.o < %s + +empty_func: + .functype empty_func () -> () + end_function + test0: # Test all types: .functype test0 (i32, i64) -> (i32) @@ -111,6 +116,9 @@ .globaltype __stack_pointer, i32 # CHECK: .text +# CHECK-LABEL: empty_func: +# CHECK-NEXT: .functype empty_func () -> () +# CHECK-NEXT: end_function # CHECK-LABEL: test0: # CHECK-NEXT: .functype test0 (i32, i64) -> (i32) # CHECK-NEXT: .eventtype __cpp_exception i32