17
17
#include " MCTargetDesc/WebAssemblyTargetStreamer.h"
18
18
#include " WebAssembly.h"
19
19
#include " llvm/MC/MCContext.h"
20
+ #include " llvm/MC/MCExpr.h"
20
21
#include " llvm/MC/MCInst.h"
21
22
#include " llvm/MC/MCInstrInfo.h"
22
23
#include " llvm/MC/MCParser/MCParsedAsmOperand.h"
23
24
#include " llvm/MC/MCParser/MCTargetAsmParser.h"
25
+ #include " llvm/MC/MCSectionWasm.h"
24
26
#include " llvm/MC/MCStreamer.h"
25
27
#include " llvm/MC/MCSubtargetInfo.h"
26
28
#include " llvm/MC/MCSymbol.h"
@@ -169,6 +171,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
169
171
FunctionStart,
170
172
FunctionLocals,
171
173
Instructions,
174
+ EndFunction,
172
175
} CurrentState = FileStart;
173
176
174
177
// For ensuring blocks are properly nested.
@@ -186,6 +189,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
186
189
// We track this to see if a .functype following a label is the same,
187
190
// as this is how we recognize the start of a function.
188
191
MCSymbol *LastLabel = nullptr ;
192
+ MCSymbol *LastFunctionLabel = nullptr ;
189
193
190
194
public:
191
195
WebAssemblyAsmParser (const MCSubtargetInfo &STI, MCAsmParser &Parser,
@@ -445,6 +449,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
445
449
if (pop (BaseName, Block))
446
450
return true ;
447
451
} else if (BaseName == " end_function" ) {
452
+ CurrentState = EndFunction;
448
453
if (pop (BaseName, Function) || ensureEmptyNestingStack ())
449
454
return true ;
450
455
}
@@ -604,6 +609,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
604
609
if (ensureEmptyNestingStack ())
605
610
return true ;
606
611
CurrentState = FunctionStart;
612
+ LastFunctionLabel = LastLabel;
607
613
push (Function);
608
614
}
609
615
auto Signature = make_unique<wasm::WasmSignature>();
@@ -666,8 +672,12 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
666
672
*Out.getTargetStreamer ());
667
673
TOut.emitLocal (SmallVector<wasm::ValType, 0 >());
668
674
}
669
- CurrentState = Instructions;
670
675
Out.EmitInstruction (Inst, getSTI ());
676
+ if (CurrentState == EndFunction) {
677
+ onEndOfFunction ();
678
+ } else {
679
+ CurrentState = Instructions;
680
+ }
671
681
return false ;
672
682
}
673
683
case Match_MissingFeature:
@@ -693,6 +703,30 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
693
703
llvm_unreachable (" Implement any new match types added!" );
694
704
}
695
705
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
+
696
730
void onEndOfFile () override { ensureEmptyNestingStack (); }
697
731
};
698
732
} // end anonymous namespace
0 commit comments