diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1698,8 +1698,11 @@ // Emit target-specific gunk after the function body. emitFunctionBodyEnd(); - if (needFuncLabelsForEHOrDebugInfo(*MF) || - MAI->hasDotTypeDotSizeDirective()) { + // Even though wasm supports .type and .size in general, function symbols + // are automatically sized. + bool EmitFunctionSize = MAI->hasDotTypeDotSizeDirective() && !TT.isWasm(); + + if (needFuncLabelsForEHOrDebugInfo(*MF) || EmitFunctionSize) { // Create a symbol for the end of function. CurrentFnEnd = createTempSymbol("func_end"); OutStreamer->emitLabel(CurrentFnEnd); @@ -1707,7 +1710,7 @@ // If the target wants a .size directive for the size of the function, emit // it. - if (MAI->hasDotTypeDotSizeDirective()) { + if (EmitFunctionSize) { // We can get the size as difference between the function label and the // temp label. const MCExpr *SizeExp = MCBinaryExpr::createSub( diff --git a/llvm/lib/MC/MCParser/WasmAsmParser.cpp b/llvm/lib/MC/MCParser/WasmAsmParser.cpp --- a/llvm/lib/MC/MCParser/WasmAsmParser.cpp +++ b/llvm/lib/MC/MCParser/WasmAsmParser.cpp @@ -207,7 +207,7 @@ // TODO: This function is almost the same as ELFAsmParser::ParseDirectiveSize // so maybe could be shared somehow. - bool parseDirectiveSize(StringRef, SMLoc) { + bool parseDirectiveSize(StringRef, SMLoc Loc) { StringRef Name; if (Parser->parseIdentifier(Name)) return TokError("expected identifier in directive"); @@ -219,9 +219,14 @@ return true; if (expect(AsmToken::EndOfStatement, "eol")) return true; - // This is done automatically by the assembler for functions currently, - // so this is only currently needed for data sections: - getStreamer().emitELFSize(Sym, Expr); + auto WasmSym = cast(Sym); + if (WasmSym->isFunction()) { + // Ignore .size directives for function symbols. They get their size + // set automatically based on their content. + Warning(Loc, ".size directive ignored for function symbols"); + } else { + getStreamer().emitELFSize(Sym, Expr); + } return false; } diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -72,7 +72,7 @@ // A wasm function to be written into the function section. struct WasmFunction { uint32_t SigIndex; - const MCSymbolWasm *Sym; + MCSection *Section; }; // A wasm global to be written into the global section. @@ -1058,15 +1058,12 @@ encodeULEB128(Functions.size(), W->OS); for (const WasmFunction &Func : Functions) { - auto &FuncSection = static_cast(Func.Sym->getSection()); - - int64_t Size = 0; - if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout)) - report_fatal_error(".size expression must be evaluatable"); + auto *FuncSection = static_cast(Func.Section); + int64_t Size = Layout.getSectionAddressSize(FuncSection); encodeULEB128(Size, W->OS); - FuncSection.setSectionOffset(W->OS.tell() - Section.ContentsOffset); - Asm.writeSectionData(W->OS, &FuncSection, Layout); + FuncSection->setSectionOffset(W->OS.tell() - Section.ContentsOffset); + Asm.writeSectionData(W->OS, FuncSection, Layout); } // Apply fixups. @@ -1591,15 +1588,11 @@ report_fatal_error( "function sections must contain one function each"); - if (WS.getSize() == nullptr) - report_fatal_error( - "function symbols must have a size set with .size"); - // A definition. Write out the function body. Index = NumFunctionImports + Functions.size(); WasmFunction Func; Func.SigIndex = getFunctionType(WS); - Func.Sym = &WS; + Func.Section = &WS.getSection(); assert(WasmIndices.count(&WS) == 0); WasmIndices[&WS] = Index; Functions.push_back(Func); diff --git a/llvm/test/MC/WebAssembly/function-size-warning.s b/llvm/test/MC/WebAssembly/function-size-warning.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/WebAssembly/function-size-warning.s @@ -0,0 +1,15 @@ +# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj %s -o %t.o 2>&1 | FileCheck %s +# RUN: llvm-objdump -t %t.o + +foo: + .functype foo () -> () + i32.const 1 + drop + end_function + +# .size directives for functions are no longer required and will +# be ignored but we continue to allow them to support legacy +# assembly files. +.size foo, 0 + +# CHECK: warning: .size directive ignored for function symbols diff --git a/llvm/test/MC/WebAssembly/stack-ptr-mclower.ll b/llvm/test/MC/WebAssembly/stack-ptr-mclower.ll --- a/llvm/test/MC/WebAssembly/stack-ptr-mclower.ll +++ b/llvm/test/MC/WebAssembly/stack-ptr-mclower.ll @@ -28,8 +28,6 @@ ; CHECK-NEXT: bar: ; CHECK-NEXT: .functype bar () -> () ; CHECK-NEXT: end_function -; CHECK-NEXT: .Lfunc_end0: -; CHECK-NEXT: .size bar, .Lfunc_end0-bar ; CHECK: .section .text.foo,"",@ ; CHECK-NEXT: .hidden foo @@ -42,5 +40,3 @@ ; CHECK-NEXT: [[PTR]].sub ; CHECK-NEXT: drop ; CHECK-NEXT: end_function -; CHECK-NEXT: .Lfunc_end1: -; CHECK-NEXT: .size foo, .Lfunc_end1-foo