Index: lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp =================================================================== --- lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -206,13 +206,18 @@ Optional ParseType(const StringRef &Type) { // FIXME: can't use StringSwitch because wasm::ValType doesn't have a // "invalid" value. - if (Type == "i32") return wasm::ValType::I32; - if (Type == "i64") return wasm::ValType::I64; - if (Type == "f32") return wasm::ValType::F32; - if (Type == "f64") return wasm::ValType::F64; + if (Type == "i32") + return wasm::ValType::I32; + if (Type == "i64") + return wasm::ValType::I64; + if (Type == "f32") + return wasm::ValType::F32; + if (Type == "f64") + return wasm::ValType::F64; if (Type == "v128" || Type == "i8x16" || Type == "i16x8" || Type == "i32x4" || Type == "i64x2" || Type == "f32x4" || - Type == "f64x2") return wasm::ValType::V128; + Type == "f64x2") + return wasm::ValType::V128; return Optional(); } @@ -271,13 +276,15 @@ // Note: Name does NOT point into the sourcecode, but to a local, so // use NameLoc instead. Name = StringRef(NameLoc.getPointer(), Name.size()); + // WebAssembly has instructions with / in them, which AsmLexer parses // as seperate tokens, so if we find such tokens immediately adjacent (no // whitespace), expand the name to include them: for (;;) { auto &Sep = Lexer.getTok(); if (Sep.getLoc().getPointer() != Name.end() || - Sep.getKind() != AsmToken::Slash) break; + Sep.getKind() != AsmToken::Slash) + break; // Extend name with / Name = StringRef(Name.begin(), Name.size() + Sep.getString().size()); Parser.Lex(); @@ -289,6 +296,7 @@ Name = StringRef(Name.begin(), Name.size() + Id.getString().size()); Parser.Lex(); } + // Now construct the name as first operand. Operands.push_back(make_unique( WebAssemblyOperand::Token, NameLoc, SMLoc::getFromPointer(Name.end()), @@ -296,6 +304,7 @@ auto NamePair = Name.split('.'); // If no '.', there is no type prefix. auto BaseName = NamePair.second.empty() ? NamePair.first : NamePair.second; + while (Lexer.isNot(AsmToken::EndOfStatement)) { auto &Tok = Lexer.getTok(); switch (Tok.getKind()) { @@ -340,6 +349,7 @@ } } Parser.Lex(); + // Block instructions require a signature index, but these are missing in // assembly, so we add a dummy one explicitly (since we have no control // over signature tables here, we assume these will be regenerated when @@ -371,27 +381,32 @@ auto &Out = getStreamer(); auto &TOut = reinterpret_cast(*Out.getTargetStreamer()); + // TODO: any time we return an error, at least one token must have been // consumed, otherwise this will not signal an error to the caller. if (DirectiveID.getString() == ".globaltype") { auto SymName = ExpectIdent(); - if (SymName.empty()) return true; - if (Expect(AsmToken::Comma, ",")) return true; + if (SymName.empty()) + return true; + if (Expect(AsmToken::Comma, ",")) + return true; auto TypeTok = Lexer.getTok(); auto TypeName = ExpectIdent(); - if (TypeName.empty()) return true; + if (TypeName.empty()) + return true; auto Type = ParseType(TypeName); if (!Type) return Error("Unknown type in .globaltype directive: ", TypeTok); // Now set this symbol with the correct type. auto WasmSym = cast( - TOut.getStreamer().getContext().getOrCreateSymbol(SymName)); + TOut.getStreamer().getContext().getOrCreateSymbol(SymName)); WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL); WasmSym->setGlobalType( - wasm::WasmGlobalType{uint8_t(Type.getValue()), true}); + wasm::WasmGlobalType{uint8_t(Type.getValue()), true}); // And emit the directive again. TOut.emitGlobalType(WasmSym); return Expect(AsmToken::EndOfStatement, "EOL"); + } else if (DirectiveID.getString() == ".functype") { // This code has to send things to the streamer similar to // WebAssemblyAsmPrinter::EmitFunctionBodyStart. @@ -399,38 +414,49 @@ // assembler and backend really don't share any common code, and this code // parses the locals seperately. auto SymName = ExpectIdent(); - if (SymName.empty()) return true; + if (SymName.empty()) + return true; auto WasmSym = cast( - TOut.getStreamer().getContext().getOrCreateSymbol(SymName)); + TOut.getStreamer().getContext().getOrCreateSymbol(SymName)); if (CurrentState == Label && WasmSym == LastLabel) { // This .functype indicates a start of a function. CurrentState = FunctionStart; } auto Signature = make_unique(); - if (Expect(AsmToken::LParen, "(")) return true; - if (ParseRegTypeList(Signature->Params)) return true; - if (Expect(AsmToken::RParen, ")")) return true; - if (Expect(AsmToken::MinusGreater, "->")) return true; - if (Expect(AsmToken::LParen, "(")) return true; - if (ParseRegTypeList(Signature->Returns)) return true; - if (Expect(AsmToken::RParen, ")")) return true; + if (Expect(AsmToken::LParen, "(")) + return true; + if (ParseRegTypeList(Signature->Params)) + return true; + if (Expect(AsmToken::RParen, ")")) + return true; + if (Expect(AsmToken::MinusGreater, "->")) + return true; + if (Expect(AsmToken::LParen, "(")) + return true; + if (ParseRegTypeList(Signature->Returns)) + return true; + if (Expect(AsmToken::RParen, ")")) + return true; WasmSym->setSignature(Signature.get()); addSignature(std::move(Signature)); WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); TOut.emitFunctionType(WasmSym); // TODO: backend also calls TOut.emitIndIdx, but that is not implemented. return Expect(AsmToken::EndOfStatement, "EOL"); + } else if (DirectiveID.getString() == ".local") { if (CurrentState != FunctionStart) return Error(".local directive should follow the start of a function", Lexer.getTok()); SmallVector Locals; - if (ParseRegTypeList(Locals)) return true; + if (ParseRegTypeList(Locals)) + return true; TOut.emitLocal(Locals); CurrentState = FunctionLocals; return Expect(AsmToken::EndOfStatement, "EOL"); } - return true; // We didn't process this directive. + + return true; // We didn't process this directive. } bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned & /*Opcode*/,