@@ -133,6 +133,9 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
133
133
MCAsmParser &Parser;
134
134
MCAsmLexer &Lexer;
135
135
136
+ // Much like WebAssemblyAsmPrinter in the backend, we have to own these.
137
+ std::vector<std::unique_ptr<wasm::WasmSignature>> Signatures;
138
+
136
139
public:
137
140
WebAssemblyAsmParser (const MCSubtargetInfo &STI, MCAsmParser &Parser,
138
141
const MCInstrInfo &MII, const MCTargetOptions &Options)
@@ -141,6 +144,10 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
141
144
setAvailableFeatures (ComputeAvailableFeatures (STI.getFeatureBits ()));
142
145
}
143
146
147
+ void addSignature (std::unique_ptr<wasm::WasmSignature> &&Sig) {
148
+ Signatures.push_back (std::move (Sig));
149
+ }
150
+
144
151
#define GET_ASSEMBLER_HEADER
145
152
#include " WebAssemblyGenAsmMatcher.inc"
146
153
@@ -168,39 +175,40 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
168
175
return false ;
169
176
}
170
177
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
+ }
171
187
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>();
191
199
}
192
200
193
- bool ParseRegTypeList (std::vector<MVT > &Types) {
201
+ bool ParseRegTypeList (SmallVectorImpl<wasm::ValType > &Types) {
194
202
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 )
197
205
return true ;
198
- Types.push_back (RegType );
206
+ Types.push_back (Type. getValue () );
199
207
Parser.Lex ();
200
208
if (!IsNext (AsmToken::Comma))
201
209
break ;
202
210
}
203
- return Expect (AsmToken::EndOfStatement, " EOL " ) ;
211
+ return false ;
204
212
}
205
213
206
214
void ParseSingleInteger (bool IsNegative, OperandVector &Operands) {
@@ -343,44 +351,47 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
343
351
// TODO: any time we return an error, at least one token must have been
344
352
// consumed, otherwise this will not signal an error to the caller.
345
353
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);
361
363
// Now set this symbol with the correct type.
362
364
auto WasmSym = cast<MCSymbolWasm>(
363
- TOut.getStreamer ().getContext ().getOrCreateSymbol (Name ));
365
+ TOut.getStreamer ().getContext ().getOrCreateSymbol (SymName ));
364
366
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 });
366
369
// And emit the directive again.
367
370
TOut.emitGlobalType (WasmSym);
368
371
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" );
379
390
} else if (DirectiveID.getString () == " .local" ) {
380
- std::vector<MVT > Locals;
391
+ SmallVector<wasm::ValType, 4 > Locals;
381
392
if (ParseRegTypeList (Locals)) return true ;
382
393
TOut.emitLocal (Locals);
383
- return false ;
394
+ return Expect (AsmToken::EndOfStatement, " EOL " ) ;
384
395
}
385
396
return true ; // We didn't process this directive.
386
397
}
0 commit comments