Index: llvm/trunk/lib/MC/MCParser/WasmAsmParser.cpp =================================================================== --- llvm/trunk/lib/MC/MCParser/WasmAsmParser.cpp +++ llvm/trunk/lib/MC/MCParser/WasmAsmParser.cpp @@ -91,8 +91,11 @@ Expect(AsmToken::Comma, ",") || Expect(AsmToken::At, "@") || Expect(AsmToken::EndOfStatement, "eol")) return true; - auto WS = getContext().getWasmSection(Name, SectionKind::getText()); - getStreamer().SwitchSection(WS); + // This is done automatically by the assembler for text sections currently, + // so we don't need to emit that here. This is what it would do (and may + // be needed later for other section types): + // auto WS = getContext().getWasmSection(Name, SectionKind::getText()); + // getStreamer().SwitchSection(WS); return false; } @@ -110,8 +113,10 @@ return true; if (Expect(AsmToken::EndOfStatement, "eol")) return true; - // MCWasmStreamer implements this. - getStreamer().emitELFSize(Sym, Expr); + // This is done automatically by the assembler for functions currently, + // so we don't need to emit that here. This is what it would do: + (void)Sym; + // getStreamer().emitELFSize(Sym, Expr); return false; } 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 @@ -17,10 +17,12 @@ #include "MCTargetDesc/WebAssemblyTargetStreamer.h" #include "WebAssembly.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/MC/MCParser/MCTargetAsmParser.h" +#include "llvm/MC/MCSectionWasm.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" @@ -169,6 +171,7 @@ FunctionStart, FunctionLocals, Instructions, + EndFunction, } CurrentState = FileStart; // For ensuring blocks are properly nested. @@ -186,6 +189,7 @@ // We track this to see if a .functype following a label is the same, // as this is how we recognize the start of a function. MCSymbol *LastLabel = nullptr; + MCSymbol *LastFunctionLabel = nullptr; public: WebAssemblyAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, @@ -445,6 +449,7 @@ if (pop(BaseName, Block)) return true; } else if (BaseName == "end_function") { + CurrentState = EndFunction; if (pop(BaseName, Function) || ensureEmptyNestingStack()) return true; } @@ -604,6 +609,7 @@ if (ensureEmptyNestingStack()) return true; CurrentState = FunctionStart; + LastFunctionLabel = LastLabel; push(Function); } auto Signature = make_unique(); @@ -666,8 +672,12 @@ *Out.getTargetStreamer()); TOut.emitLocal(SmallVector()); } - CurrentState = Instructions; Out.EmitInstruction(Inst, getSTI()); + if (CurrentState == EndFunction) { + onEndOfFunction(); + } else { + CurrentState = Instructions; + } return false; } case Match_MissingFeature: @@ -693,6 +703,30 @@ llvm_unreachable("Implement any new match types added!"); } + void doBeforeLabelEmit(MCSymbol *Symbol) override { + // Start a new section for the next function automatically, since our + // object writer expects each function to have its own section. This way + // The user can't forget this "convention". + auto SymName = Symbol->getName(); + if (SymName.startswith(".L")) + return; // Local Symbol. + auto SecName = ".text." + SymName; + auto WS = getContext().getWasmSection(SecName, SectionKind::getText()); + getStreamer().SwitchSection(WS); + } + + void onEndOfFunction() { + // Automatically output a .size directive, so it becomes optional for the + // user. + auto TempSym = getContext().createLinkerPrivateTempSymbol(); + getStreamer().EmitLabel(TempSym); + auto Start = MCSymbolRefExpr::create(LastLabel, getContext()); + auto End = MCSymbolRefExpr::create(TempSym, getContext()); + auto Expr = + MCBinaryExpr::create(MCBinaryExpr::Sub, End, Start, getContext()); + getStreamer().emitELFSize(LastFunctionLabel, Expr); + } + void onEndOfFile() override { ensureEmptyNestingStack(); } }; } // end anonymous namespace Index: llvm/trunk/test/MC/WebAssembly/assembler-binary.ll =================================================================== --- llvm/trunk/test/MC/WebAssembly/assembler-binary.ll +++ llvm/trunk/test/MC/WebAssembly/assembler-binary.ll @@ -28,8 +28,6 @@ ; ASM-NEXT: .functype foo (i32) -> () ; ASM-NEXT: call bar@FUNCTION ; ASM-NEXT: end_function -; ASM-NEXT: .Lfunc_end0: -; ASM-NEXT: .size foo, .Lfunc_end0-foo ; ASM: .functype bar () -> () Index: llvm/trunk/test/MC/WebAssembly/basic-assembly-errors.s =================================================================== --- llvm/trunk/test/MC/WebAssembly/basic-assembly-errors.s +++ llvm/trunk/test/MC/WebAssembly/basic-assembly-errors.s @@ -1,8 +1,5 @@ # RUN: not llvm-mc -triple=wasm32-unknown-unknown -mattr=+simd128,+nontrapping-fptoint,+exception-handling < %s 2>&1 | FileCheck %s - .text - .section .text.main,"",@ - .type test0,@function # CHECK: End of block construct with no start: end_try end_try test0: @@ -20,6 +17,4 @@ # CHECK: error: Unmatched block construct(s) at function end: block # CHECK: error: Unmatched block construct(s) at function end: function end_function -.Lfunc_end0: - .size test0, .Lfunc_end0-test0 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,9 +2,6 @@ # this one is just here to see if it converts to .o without errors, but doesn't check any output: # RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj -mattr=+unimplemented-simd128,+nontrapping-fptoint,+exception-handling < %s - .text - .section .text.main,"",@ - .type test0,@function test0: # Test all types: .functype test0 (i32, i64) -> (i32) @@ -86,8 +83,6 @@ #i32.trunc_sat_f32_s global.get __stack_pointer@GLOBAL end_function -.Lfunc_end0: - .size test0, .Lfunc_end0-test0 .globaltype __stack_pointer, i32 # CHECK: .text Index: llvm/trunk/test/MC/WebAssembly/objdump.s =================================================================== --- llvm/trunk/test/MC/WebAssembly/objdump.s +++ llvm/trunk/test/MC/WebAssembly/objdump.s @@ -1,25 +1,17 @@ # RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj -o %t.o -mattr=+simd128,+nontrapping-fptoint,+exception-handling < %s # RUN: llvm-objdump -triple=wasm32-unknown-unknown -disassemble %t.o | FileCheck %s - .section .text.main1,"",@ - .type test0,@function test0: .functype test0 (i32, i64) -> (i32) .local f32, f64, v128, v128 local.get 2 end_function -.Lfunc_end0: - .size test0, .Lfunc_end0-test0 - .section .text.main2,"",@ - .type test1,@function test1: .functype test1 (i32, i64) -> (i32) .local i32, i64, except_ref local.get 3 end_function -.Lfunc_end1: - .size test1, .Lfunc_end1-test1 # CHECK-LABEL: CODE: