Skip to content

Commit 0b3cf24

Browse files
committedFeb 4, 2019
[WebAssembly] Make segment/size/type directives optional in asm
Summary: These were "boilerplate" that repeated information already present in .functype and end_function, that needed to be repeated to Please the particular way our object writing works, and missing them would generate errors. Instead, we generate the information for these automatically so the user can concern itself with writing more canonical wasm functions that always work as expected. Reviewers: dschuff, sbc100 Subscribers: jgravelle-google, aheejin, sunfish, llvm-commits Differential Revision: https://reviews.llvm.org/D57546 llvm-svn: 353067
1 parent 79e3317 commit 0b3cf24

File tree

6 files changed

+44
-25
lines changed

6 files changed

+44
-25
lines changed
 

‎llvm/lib/MC/MCParser/WasmAsmParser.cpp

+9-4
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,11 @@ class WasmAsmParser : public MCAsmParserExtension {
9191
Expect(AsmToken::Comma, ",") || Expect(AsmToken::At, "@") ||
9292
Expect(AsmToken::EndOfStatement, "eol"))
9393
return true;
94-
auto WS = getContext().getWasmSection(Name, SectionKind::getText());
95-
getStreamer().SwitchSection(WS);
94+
// This is done automatically by the assembler for text sections currently,
95+
// so we don't need to emit that here. This is what it would do (and may
96+
// be needed later for other section types):
97+
// auto WS = getContext().getWasmSection(Name, SectionKind::getText());
98+
// getStreamer().SwitchSection(WS);
9699
return false;
97100
}
98101

@@ -110,8 +113,10 @@ class WasmAsmParser : public MCAsmParserExtension {
110113
return true;
111114
if (Expect(AsmToken::EndOfStatement, "eol"))
112115
return true;
113-
// MCWasmStreamer implements this.
114-
getStreamer().emitELFSize(Sym, Expr);
116+
// This is done automatically by the assembler for functions currently,
117+
// so we don't need to emit that here. This is what it would do:
118+
(void)Sym;
119+
// getStreamer().emitELFSize(Sym, Expr);
115120
return false;
116121
}
117122

‎llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp

+35-1
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@
1717
#include "MCTargetDesc/WebAssemblyTargetStreamer.h"
1818
#include "WebAssembly.h"
1919
#include "llvm/MC/MCContext.h"
20+
#include "llvm/MC/MCExpr.h"
2021
#include "llvm/MC/MCInst.h"
2122
#include "llvm/MC/MCInstrInfo.h"
2223
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
2324
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
25+
#include "llvm/MC/MCSectionWasm.h"
2426
#include "llvm/MC/MCStreamer.h"
2527
#include "llvm/MC/MCSubtargetInfo.h"
2628
#include "llvm/MC/MCSymbol.h"
@@ -169,6 +171,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
169171
FunctionStart,
170172
FunctionLocals,
171173
Instructions,
174+
EndFunction,
172175
} CurrentState = FileStart;
173176

174177
// For ensuring blocks are properly nested.
@@ -186,6 +189,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
186189
// We track this to see if a .functype following a label is the same,
187190
// as this is how we recognize the start of a function.
188191
MCSymbol *LastLabel = nullptr;
192+
MCSymbol *LastFunctionLabel = nullptr;
189193

190194
public:
191195
WebAssemblyAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
@@ -445,6 +449,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
445449
if (pop(BaseName, Block))
446450
return true;
447451
} else if (BaseName == "end_function") {
452+
CurrentState = EndFunction;
448453
if (pop(BaseName, Function) || ensureEmptyNestingStack())
449454
return true;
450455
}
@@ -604,6 +609,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
604609
if (ensureEmptyNestingStack())
605610
return true;
606611
CurrentState = FunctionStart;
612+
LastFunctionLabel = LastLabel;
607613
push(Function);
608614
}
609615
auto Signature = make_unique<wasm::WasmSignature>();
@@ -666,8 +672,12 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
666672
*Out.getTargetStreamer());
667673
TOut.emitLocal(SmallVector<wasm::ValType, 0>());
668674
}
669-
CurrentState = Instructions;
670675
Out.EmitInstruction(Inst, getSTI());
676+
if (CurrentState == EndFunction) {
677+
onEndOfFunction();
678+
} else {
679+
CurrentState = Instructions;
680+
}
671681
return false;
672682
}
673683
case Match_MissingFeature:
@@ -693,6 +703,30 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
693703
llvm_unreachable("Implement any new match types added!");
694704
}
695705

706+
void doBeforeLabelEmit(MCSymbol *Symbol) override {
707+
// Start a new section for the next function automatically, since our
708+
// object writer expects each function to have its own section. This way
709+
// The user can't forget this "convention".
710+
auto SymName = Symbol->getName();
711+
if (SymName.startswith(".L"))
712+
return; // Local Symbol.
713+
auto SecName = ".text." + SymName;
714+
auto WS = getContext().getWasmSection(SecName, SectionKind::getText());
715+
getStreamer().SwitchSection(WS);
716+
}
717+
718+
void onEndOfFunction() {
719+
// Automatically output a .size directive, so it becomes optional for the
720+
// user.
721+
auto TempSym = getContext().createLinkerPrivateTempSymbol();
722+
getStreamer().EmitLabel(TempSym);
723+
auto Start = MCSymbolRefExpr::create(LastLabel, getContext());
724+
auto End = MCSymbolRefExpr::create(TempSym, getContext());
725+
auto Expr =
726+
MCBinaryExpr::create(MCBinaryExpr::Sub, End, Start, getContext());
727+
getStreamer().emitELFSize(LastFunctionLabel, Expr);
728+
}
729+
696730
void onEndOfFile() override { ensureEmptyNestingStack(); }
697731
};
698732
} // end anonymous namespace

‎llvm/test/MC/WebAssembly/assembler-binary.ll

-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ entry:
2828
; ASM-NEXT: .functype foo (i32) -> ()
2929
; ASM-NEXT: call bar@FUNCTION
3030
; ASM-NEXT: end_function
31-
; ASM-NEXT: .Lfunc_end0:
32-
; ASM-NEXT: .size foo, .Lfunc_end0-foo
3331
; ASM: .functype bar () -> ()
3432

3533

‎llvm/test/MC/WebAssembly/basic-assembly-errors.s

-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
# RUN: not llvm-mc -triple=wasm32-unknown-unknown -mattr=+simd128,+nontrapping-fptoint,+exception-handling < %s 2>&1 | FileCheck %s
22

3-
.text
4-
.section .text.main,"",@
5-
.type test0,@function
63
# CHECK: End of block construct with no start: end_try
74
end_try
85
test0:
@@ -20,6 +17,4 @@ test0:
2017
# CHECK: error: Unmatched block construct(s) at function end: block
2118
# CHECK: error: Unmatched block construct(s) at function end: function
2219
end_function
23-
.Lfunc_end0:
24-
.size test0, .Lfunc_end0-test0
2520

‎llvm/test/MC/WebAssembly/basic-assembly.s

-5
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
# this one is just here to see if it converts to .o without errors, but doesn't check any output:
33
# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj -mattr=+unimplemented-simd128,+nontrapping-fptoint,+exception-handling < %s
44

5-
.text
6-
.section .text.main,"",@
7-
.type test0,@function
85
test0:
96
# Test all types:
107
.functype test0 (i32, i64) -> (i32)
@@ -86,8 +83,6 @@ test0:
8683
#i32.trunc_sat_f32_s
8784
global.get __stack_pointer@GLOBAL
8885
end_function
89-
.Lfunc_end0:
90-
.size test0, .Lfunc_end0-test0
9186
.globaltype __stack_pointer, i32
9287

9388
# CHECK: .text

‎llvm/test/MC/WebAssembly/objdump.s

-8
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,17 @@
11
# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj -o %t.o -mattr=+simd128,+nontrapping-fptoint,+exception-handling < %s
22
# RUN: llvm-objdump -triple=wasm32-unknown-unknown -disassemble %t.o | FileCheck %s
33

4-
.section .text.main1,"",@
5-
.type test0,@function
64
test0:
75
.functype test0 (i32, i64) -> (i32)
86
.local f32, f64, v128, v128
97
local.get 2
108
end_function
11-
.Lfunc_end0:
12-
.size test0, .Lfunc_end0-test0
139

14-
.section .text.main2,"",@
15-
.type test1,@function
1610
test1:
1711
.functype test1 (i32, i64) -> (i32)
1812
.local i32, i64, except_ref
1913
local.get 3
2014
end_function
21-
.Lfunc_end1:
22-
.size test1, .Lfunc_end1-test1
2315

2416

2517
# CHECK-LABEL: CODE:

0 commit comments

Comments
 (0)
Please sign in to comment.