Skip to content

Commit 49482f8

Browse files
committed
[WebAssembly] replaced .param/.result by .functype
Summary: This makes it easier/cleaner to generate a single signature from this directive. Also: - Adds the symbol name, such that we don't depend on the location of this directive anymore. - Actually constructs the signature in the assembler, and make the assembler own it. - Refactor the use of MVT vs ValType in the streamer and assembler to require less conversions overall. - Changed 700 or so tests to use it. Reviewers: sbc100, dschuff Subscribers: jgravelle-google, eraman, aheejin, sunfish, jfb, llvm-commits Differential Revision: https://reviews.llvm.org/D54652 llvm-svn: 347228
1 parent b25adf5 commit 49482f8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+1194
-1868
lines changed

llvm/include/llvm/MC/MCAsmMacro.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class AsmToken {
5252
Pipe, PipePipe, Caret,
5353
Amp, AmpAmp, Exclaim, ExclaimEqual, Percent, Hash,
5454
Less, LessEqual, LessLess, LessGreater,
55-
Greater, GreaterEqual, GreaterGreater, At,
55+
Greater, GreaterEqual, GreaterGreater, At, MinusGreater,
5656

5757
// MIPS unary expression operators such as %neg.
5858
PercentCall16, PercentCall_Hi, PercentCall_Lo, PercentDtprel_Hi,

llvm/lib/MC/MCParser/AsmLexer.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,6 @@ AsmToken AsmLexer::LexToken() {
627627
return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
628628
case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1));
629629
case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1));
630-
case '-': return AsmToken(AsmToken::Minus, StringRef(TokStart, 1));
631630
case '~': return AsmToken(AsmToken::Tilde, StringRef(TokStart, 1));
632631
case '(': return AsmToken(AsmToken::LParen, StringRef(TokStart, 1));
633632
case ')': return AsmToken(AsmToken::RParen, StringRef(TokStart, 1));
@@ -646,6 +645,12 @@ AsmToken AsmLexer::LexToken() {
646645
return AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2));
647646
}
648647
return AsmToken(AsmToken::Equal, StringRef(TokStart, 1));
648+
case '-':
649+
if (*CurPtr == '>') {
650+
++CurPtr;
651+
return AsmToken(AsmToken::MinusGreater, StringRef(TokStart, 2));
652+
}
653+
return AsmToken(AsmToken::Minus, StringRef(TokStart, 1));
649654
case '|':
650655
if (*CurPtr == '|') {
651656
++CurPtr;

llvm/lib/MC/MCParser/MCAsmLexer.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ void AsmToken::dump(raw_ostream &OS) const {
8585
case AsmToken::LessGreater: OS << "LessGreater"; break;
8686
case AsmToken::LessLess: OS << "LessLess"; break;
8787
case AsmToken::Minus: OS << "Minus"; break;
88+
case AsmToken::MinusGreater: OS << "MinusGreater"; break;
8889
case AsmToken::Percent: OS << "Percent"; break;
8990
case AsmToken::Pipe: OS << "Pipe"; break;
9091
case AsmToken::PipePipe: OS << "PipePipe"; break;

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

Lines changed: 64 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
133133
MCAsmParser &Parser;
134134
MCAsmLexer &Lexer;
135135

136+
// Much like WebAssemblyAsmPrinter in the backend, we have to own these.
137+
std::vector<std::unique_ptr<wasm::WasmSignature>> Signatures;
138+
136139
public:
137140
WebAssemblyAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
138141
const MCInstrInfo &MII, const MCTargetOptions &Options)
@@ -141,6 +144,10 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
141144
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
142145
}
143146

147+
void addSignature(std::unique_ptr<wasm::WasmSignature> &&Sig) {
148+
Signatures.push_back(std::move(Sig));
149+
}
150+
144151
#define GET_ASSEMBLER_HEADER
145152
#include "WebAssemblyGenAsmMatcher.inc"
146153

@@ -168,39 +175,40 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
168175
return false;
169176
}
170177

178+
StringRef ExpectIdent() {
179+
if (!Lexer.is(AsmToken::Identifier)) {
180+
Error("Expected identifier, got: ", Lexer.getTok());
181+
return StringRef();
182+
}
183+
auto Name = Lexer.getTok().getString();
184+
Parser.Lex();
185+
return Name;
186+
}
171187

172-
std::pair<MVT::SimpleValueType, unsigned>
173-
ParseRegType(const StringRef &RegType) {
174-
// Derive type from .param .local decls, or the instruction itself.
175-
return StringSwitch<std::pair<MVT::SimpleValueType, unsigned>>(RegType)
176-
.Case("i32", {MVT::i32, wasm::WASM_TYPE_I32})
177-
.Case("i64", {MVT::i64, wasm::WASM_TYPE_I64})
178-
.Case("f32", {MVT::f32, wasm::WASM_TYPE_F32})
179-
.Case("f64", {MVT::f64, wasm::WASM_TYPE_F64})
180-
.Case("i8x16", {MVT::v16i8, wasm::WASM_TYPE_V128})
181-
.Case("i16x8", {MVT::v8i16, wasm::WASM_TYPE_V128})
182-
.Case("i32x4", {MVT::v4i32, wasm::WASM_TYPE_V128})
183-
.Case("i64x2", {MVT::v2i64, wasm::WASM_TYPE_V128})
184-
.Case("f32x4", {MVT::v4f32, wasm::WASM_TYPE_V128})
185-
.Case("f64x2", {MVT::v2f64, wasm::WASM_TYPE_V128})
186-
// arbitrarily chosen vector type to associate with "v128"
187-
// FIXME: should these be EVTs to avoid this arbitrary hack? Do we want
188-
// to accept more specific SIMD register types?
189-
.Case("v128", {MVT::v16i8, wasm::WASM_TYPE_V128})
190-
.Default({MVT::INVALID_SIMPLE_VALUE_TYPE, wasm::WASM_TYPE_NORESULT});
188+
Optional<wasm::ValType> ParseType(const StringRef &Type) {
189+
// FIXME: can't use StringSwitch because wasm::ValType doesn't have a
190+
// "invalid" value.
191+
if (Type == "i32") return wasm::ValType::I32;
192+
if (Type == "i64") return wasm::ValType::I64;
193+
if (Type == "f32") return wasm::ValType::F32;
194+
if (Type == "f64") return wasm::ValType::F64;
195+
if (Type == "v128" || Type == "i8x16" || Type == "i16x8" ||
196+
Type == "i32x4" || Type == "i64x2" || Type == "f32x4" ||
197+
Type == "f64x2") return wasm::ValType::V128;
198+
return Optional<wasm::ValType>();
191199
}
192200

193-
bool ParseRegTypeList(std::vector<MVT> &Types) {
201+
bool ParseRegTypeList(SmallVectorImpl<wasm::ValType> &Types) {
194202
while (Lexer.is(AsmToken::Identifier)) {
195-
auto RegType = ParseRegType(Lexer.getTok().getString()).first;
196-
if (RegType == MVT::INVALID_SIMPLE_VALUE_TYPE)
203+
auto Type = ParseType(Lexer.getTok().getString());
204+
if (!Type)
197205
return true;
198-
Types.push_back(RegType);
206+
Types.push_back(Type.getValue());
199207
Parser.Lex();
200208
if (!IsNext(AsmToken::Comma))
201209
break;
202210
}
203-
return Expect(AsmToken::EndOfStatement, "EOL");
211+
return false;
204212
}
205213

206214
void ParseSingleInteger(bool IsNegative, OperandVector &Operands) {
@@ -343,44 +351,47 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
343351
// TODO: any time we return an error, at least one token must have been
344352
// consumed, otherwise this will not signal an error to the caller.
345353
if (DirectiveID.getString() == ".globaltype") {
346-
if (!Lexer.is(AsmToken::Identifier))
347-
return Error("Expected symbol name after .globaltype directive, got: ",
348-
Lexer.getTok());
349-
auto Name = Lexer.getTok().getString();
350-
Parser.Lex();
351-
if (!IsNext(AsmToken::Comma))
352-
return Error("Expected `,`, got: ", Lexer.getTok());
353-
if (!Lexer.is(AsmToken::Identifier))
354-
return Error("Expected type in .globaltype directive, got: ",
355-
Lexer.getTok());
356-
auto Type = ParseRegType(Lexer.getTok().getString()).second;
357-
if (Type == wasm::WASM_TYPE_NORESULT)
358-
return Error("Unknown type in .globaltype directive: ",
359-
Lexer.getTok());
360-
Parser.Lex();
354+
auto SymName = ExpectIdent();
355+
if (SymName.empty()) return true;
356+
if (Expect(AsmToken::Comma, ",")) return true;
357+
auto TypeTok = Lexer.getTok();
358+
auto TypeName = ExpectIdent();
359+
if (TypeName.empty()) return true;
360+
auto Type = ParseType(TypeName);
361+
if (!Type)
362+
return Error("Unknown type in .globaltype directive: ", TypeTok);
361363
// Now set this symbol with the correct type.
362364
auto WasmSym = cast<MCSymbolWasm>(
363-
TOut.getStreamer().getContext().getOrCreateSymbol(Name));
365+
TOut.getStreamer().getContext().getOrCreateSymbol(SymName));
364366
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
365-
WasmSym->setGlobalType(wasm::WasmGlobalType{uint8_t(Type), true});
367+
WasmSym->setGlobalType(
368+
wasm::WasmGlobalType{uint8_t(Type.getValue()), true});
366369
// And emit the directive again.
367370
TOut.emitGlobalType(WasmSym);
368371
return Expect(AsmToken::EndOfStatement, "EOL");
369-
} else if (DirectiveID.getString() == ".param") {
370-
std::vector<MVT> Params;
371-
if (ParseRegTypeList(Params)) return true;
372-
TOut.emitParam(nullptr /* unused */, Params);
373-
return false;
374-
} else if (DirectiveID.getString() == ".result") {
375-
std::vector<MVT> Results;
376-
if (ParseRegTypeList(Results)) return true;
377-
TOut.emitResult(nullptr /* unused */, Results);
378-
return false;
372+
} else if (DirectiveID.getString() == ".functype") {
373+
auto SymName = ExpectIdent();
374+
if (SymName.empty()) return true;
375+
auto WasmSym = cast<MCSymbolWasm>(
376+
TOut.getStreamer().getContext().getOrCreateSymbol(SymName));
377+
auto Signature = make_unique<wasm::WasmSignature>();
378+
if (Expect(AsmToken::LParen, "(")) return true;
379+
if (ParseRegTypeList(Signature->Params)) return true;
380+
if (Expect(AsmToken::RParen, ")")) return true;
381+
if (Expect(AsmToken::MinusGreater, "->")) return true;
382+
if (Expect(AsmToken::LParen, "(")) return true;
383+
if (ParseRegTypeList(Signature->Returns)) return true;
384+
if (Expect(AsmToken::RParen, ")")) return true;
385+
WasmSym->setSignature(Signature.get());
386+
addSignature(std::move(Signature));
387+
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
388+
TOut.emitFunctionType(WasmSym);
389+
return Expect(AsmToken::EndOfStatement, "EOL");
379390
} else if (DirectiveID.getString() == ".local") {
380-
std::vector<MVT> Locals;
391+
SmallVector<wasm::ValType, 4> Locals;
381392
if (ParseRegTypeList(Locals)) return true;
382393
TOut.emitLocal(Locals);
383-
return false;
394+
return Expect(AsmToken::EndOfStatement, "EOL");
384395
}
385396
return true; // We didn't process this directive.
386397
}

llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp

Lines changed: 22 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -39,43 +39,19 @@ WebAssemblyTargetAsmStreamer::WebAssemblyTargetAsmStreamer(
3939
WebAssemblyTargetWasmStreamer::WebAssemblyTargetWasmStreamer(MCStreamer &S)
4040
: WebAssemblyTargetStreamer(S) {}
4141

42-
static void PrintTypes(formatted_raw_ostream &OS, ArrayRef<MVT> Types) {
42+
static void PrintTypes(formatted_raw_ostream &OS, ArrayRef<wasm::ValType> Types) {
4343
bool First = true;
44-
for (MVT Type : Types) {
44+
for (auto Type : Types) {
4545
if (First)
4646
First = false;
4747
else
4848
OS << ", ";
49-
OS << WebAssembly::TypeToString(WebAssembly::toValType(Type));
49+
OS << WebAssembly::TypeToString(Type);
5050
}
5151
OS << '\n';
5252
}
5353

54-
void WebAssemblyTargetAsmStreamer::emitParam(MCSymbol *Symbol,
55-
ArrayRef<MVT> Types) {
56-
if (!Types.empty()) {
57-
OS << "\t.param \t";
58-
59-
// FIXME: Currently this applies to the "current" function; it may
60-
// be cleaner to specify an explicit symbol as part of the directive.
61-
62-
PrintTypes(OS, Types);
63-
}
64-
}
65-
66-
void WebAssemblyTargetAsmStreamer::emitResult(MCSymbol *Symbol,
67-
ArrayRef<MVT> Types) {
68-
if (!Types.empty()) {
69-
OS << "\t.result \t";
70-
71-
// FIXME: Currently this applies to the "current" function; it may
72-
// be cleaner to specify an explicit symbol as part of the directive.
73-
74-
PrintTypes(OS, Types);
75-
}
76-
}
77-
78-
void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<MVT> Types) {
54+
void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<wasm::ValType> Types) {
7955
if (!Types.empty()) {
8056
OS << "\t.local \t";
8157
PrintTypes(OS, Types);
@@ -84,19 +60,20 @@ void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<MVT> Types) {
8460

8561
void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; }
8662

87-
void WebAssemblyTargetAsmStreamer::emitIndirectFunctionType(
88-
MCSymbolWasm *Symbol) {
89-
OS << "\t.functype\t" << Symbol->getName();
90-
if (Symbol->getSignature()->Returns.empty())
91-
OS << ", void";
92-
else {
93-
assert(Symbol->getSignature()->Returns.size() == 1);
94-
OS << ", "
95-
<< WebAssembly::TypeToString(Symbol->getSignature()->Returns.front());
63+
void WebAssemblyTargetAsmStreamer::emitFunctionType(MCSymbolWasm *Symbol) {
64+
OS << "\t.functype\t" << Symbol->getName() << " (";
65+
auto &Params = Symbol->getSignature()->Params;
66+
for (auto &Ty : Params) {
67+
if (&Ty != &Params[0]) OS << ", ";
68+
OS << WebAssembly::TypeToString(Ty);
9669
}
97-
for (auto Ty : Symbol->getSignature()->Params)
98-
OS << ", " << WebAssembly::TypeToString(Ty);
99-
OS << '\n';
70+
OS << ") -> (";
71+
auto &Returns = Symbol->getSignature()->Returns;
72+
for (auto &Ty : Returns) {
73+
if (&Ty != &Returns[0]) OS << ", ";
74+
OS << WebAssembly::TypeToString(Ty);
75+
}
76+
OS << ")\n";
10077
}
10178

10279
void WebAssemblyTargetAsmStreamer::emitGlobalType(MCSymbolWasm *Sym) {
@@ -131,19 +108,9 @@ void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) {
131108
OS << "\t.indidx \t" << *Value << '\n';
132109
}
133110

134-
void WebAssemblyTargetWasmStreamer::emitParam(MCSymbol *Symbol,
135-
ArrayRef<MVT> Types) {
136-
// The Symbol already has its signature
137-
}
138-
139-
void WebAssemblyTargetWasmStreamer::emitResult(MCSymbol *Symbol,
140-
ArrayRef<MVT> Types) {
141-
// The Symbol already has its signature
142-
}
143-
144-
void WebAssemblyTargetWasmStreamer::emitLocal(ArrayRef<MVT> Types) {
145-
SmallVector<std::pair<MVT, uint32_t>, 4> Grouped;
146-
for (MVT Type : Types) {
111+
void WebAssemblyTargetWasmStreamer::emitLocal(ArrayRef<wasm::ValType> Types) {
112+
SmallVector<std::pair<wasm::ValType, uint32_t>, 4> Grouped;
113+
for (auto Type : Types) {
147114
if (Grouped.empty() || Grouped.back().first != Type)
148115
Grouped.push_back(std::make_pair(Type, 1));
149116
else
@@ -153,7 +120,7 @@ void WebAssemblyTargetWasmStreamer::emitLocal(ArrayRef<MVT> Types) {
153120
Streamer.EmitULEB128IntValue(Grouped.size());
154121
for (auto Pair : Grouped) {
155122
Streamer.EmitULEB128IntValue(Pair.second);
156-
emitValueType(WebAssembly::toValType(Pair.first));
123+
emitValueType(Pair.first);
157124
}
158125
}
159126

@@ -165,8 +132,7 @@ void WebAssemblyTargetWasmStreamer::emitIndIdx(const MCExpr *Value) {
165132
llvm_unreachable(".indidx encoding not yet implemented");
166133
}
167134

168-
void WebAssemblyTargetWasmStreamer::emitIndirectFunctionType(
169-
MCSymbolWasm *Symbol) {
135+
void WebAssemblyTargetWasmStreamer::emitFunctionType(MCSymbolWasm *Symbol) {
170136
// Symbol already has its arguments and result set.
171137
Symbol->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
172138
}

llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,12 @@ class WebAssemblyTargetStreamer : public MCTargetStreamer {
3131
public:
3232
explicit WebAssemblyTargetStreamer(MCStreamer &S);
3333

34-
/// .param
35-
virtual void emitParam(MCSymbol *Symbol, ArrayRef<MVT> Types) = 0;
36-
/// .result
37-
virtual void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) = 0;
3834
/// .local
39-
virtual void emitLocal(ArrayRef<MVT> Types) = 0;
35+
virtual void emitLocal(ArrayRef<wasm::ValType> Types) = 0;
4036
/// .endfunc
4137
virtual void emitEndFunc() = 0;
4238
/// .functype
43-
virtual void emitIndirectFunctionType(MCSymbolWasm *Symbol) = 0;
39+
virtual void emitFunctionType(MCSymbolWasm *Symbol) = 0;
4440
/// .indidx
4541
virtual void emitIndIdx(const MCExpr *Value) = 0;
4642
/// .globaltype
@@ -61,11 +57,9 @@ class WebAssemblyTargetAsmStreamer final : public WebAssemblyTargetStreamer {
6157
public:
6258
WebAssemblyTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
6359

64-
void emitParam(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
65-
void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
66-
void emitLocal(ArrayRef<MVT> Types) override;
60+
void emitLocal(ArrayRef<wasm::ValType> Types) override;
6761
void emitEndFunc() override;
68-
void emitIndirectFunctionType(MCSymbolWasm *Symbol) override;
62+
void emitFunctionType(MCSymbolWasm *Symbol) override;
6963
void emitIndIdx(const MCExpr *Value) override;
7064
void emitGlobalType(MCSymbolWasm *Sym) override;
7165
void emitEventType(MCSymbolWasm *Sym) override;
@@ -77,11 +71,9 @@ class WebAssemblyTargetWasmStreamer final : public WebAssemblyTargetStreamer {
7771
public:
7872
explicit WebAssemblyTargetWasmStreamer(MCStreamer &S);
7973

80-
void emitParam(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
81-
void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
82-
void emitLocal(ArrayRef<MVT> Types) override;
74+
void emitLocal(ArrayRef<wasm::ValType> Types) override;
8375
void emitEndFunc() override;
84-
void emitIndirectFunctionType(MCSymbolWasm *Symbol) override;
76+
void emitFunctionType(MCSymbolWasm *Symbol) override;
8577
void emitIndIdx(const MCExpr *Value) override;
8678
void emitGlobalType(MCSymbolWasm *Sym) override;
8779
void emitEventType(MCSymbolWasm *Sym) override;
@@ -94,15 +86,13 @@ class WebAssemblyTargetNullStreamer final : public WebAssemblyTargetStreamer {
9486
explicit WebAssemblyTargetNullStreamer(MCStreamer &S)
9587
: WebAssemblyTargetStreamer(S) {}
9688

97-
void emitParam(MCSymbol *Symbol, ArrayRef<MVT> Types) override {}
98-
void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override {}
99-
void emitLocal(ArrayRef<MVT> Types) override {}
89+
void emitLocal(ArrayRef<wasm::ValType>) override {}
10090
void emitEndFunc() override {}
101-
void emitIndirectFunctionType(MCSymbolWasm *Symbol) override {}
102-
void emitIndIdx(const MCExpr *Value) override {}
103-
void emitGlobalType(MCSymbolWasm *Sym) override {}
104-
void emitEventType(MCSymbolWasm *Sym) override {}
105-
void emitImportModule(MCSymbolWasm *Sym, StringRef ModuleName) override {}
91+
void emitFunctionType(MCSymbolWasm *) override {}
92+
void emitIndIdx(const MCExpr *) override {}
93+
void emitGlobalType(MCSymbolWasm *) override {}
94+
void emitEventType(MCSymbolWasm *) override {}
95+
void emitImportModule(MCSymbolWasm *, StringRef) override {}
10696
};
10797

10898
} // end namespace llvm

0 commit comments

Comments
 (0)