diff options
Diffstat (limited to 'llvm')
9 files changed, 130 insertions, 42 deletions
diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp index 09628e872dd..2fd7382fbcc 100644 --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -492,6 +492,27 @@ public:        CurrentState = EndFunction;        if (pop(Name, Function) || ensureEmptyNestingStack())          return true; +    } else if (Name == "call_indirect" || Name == "return_call_indirect") { +      // This has a special TYPEINDEX operand which in text we +      // represent as a signature, such that we can re-build this signature, +      // attach it to an anonymous symbol, which is what WasmObjectWriter +      // expects to be able to recreate the actual unique-ified type indices. +      auto Loc = Parser.getTok(); +      auto Signature = make_unique<wasm::WasmSignature>(); +      if (parseSignature(Signature.get())) +        return true; +      auto &Ctx = getStreamer().getContext(); +      // The "true" here will cause this to be a nameless symbol. +      MCSymbol *Sym = Ctx.createTempSymbol("typeindex", true); +      auto *WasmSym = cast<MCSymbolWasm>(Sym); +      WasmSym->setSignature(Signature.get()); +      addSignature(std::move(Signature)); +      WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); +      const MCExpr *Expr = MCSymbolRefExpr::create( +          WasmSym, MCSymbolRefExpr::VK_WASM_TYPEINDEX, Ctx); +      Operands.push_back(make_unique<WebAssemblyOperand>( +          WebAssemblyOperand::Symbol, Loc.getLoc(), Loc.getEndLoc(), +          WebAssemblyOperand::SymOp{Expr}));      }      while (Lexer.isNot(AsmToken::EndOfStatement)) { diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp index b5d4d369b72..bc63382aa8f 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp @@ -15,6 +15,7 @@  #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"  #include "WebAssembly.h"  #include "WebAssemblyMachineFunctionInfo.h" +#include "WebAssemblyUtilities.h"  #include "llvm/ADT/SmallSet.h"  #include "llvm/ADT/StringExtras.h"  #include "llvm/CodeGen/TargetRegisterInfo.h" @@ -232,7 +233,16 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,      }    } else {      assert(Op.isExpr() && "unknown operand kind in printOperand"); -    Op.getExpr()->print(O, &MAI); +    // call_indirect instructions have a TYPEINDEX operand that we print +    // as a signature here, such that the assembler can recover this +    // information. +    auto SRE = static_cast<const MCSymbolRefExpr *>(Op.getExpr()); +    if (SRE->getKind() == MCSymbolRefExpr::VK_WASM_TYPEINDEX) { +      auto &Sym = static_cast<const MCSymbolWasm &>(SRE->getSymbol()); +      O << WebAssembly::signatureToString(Sym.getSignature()); +    } else { +      Op.getExpr()->print(O, &MAI); +    }    }  } @@ -266,7 +276,7 @@ void WebAssemblyInstPrinter::printWebAssemblySignatureOperand(const MCInst *MI,  // We have various enums representing a subset of these types, use this  // function to convert any of them to text. -const char *llvm::WebAssembly::anyTypeToString(unsigned Ty) { +const char *WebAssembly::anyTypeToString(unsigned Ty) {    switch (Ty) {    case wasm::WASM_TYPE_I32:      return "i32"; @@ -291,6 +301,24 @@ const char *llvm::WebAssembly::anyTypeToString(unsigned Ty) {    }  } -const char *llvm::WebAssembly::typeToString(wasm::ValType Ty) { +const char *WebAssembly::typeToString(wasm::ValType Ty) {    return anyTypeToString(static_cast<unsigned>(Ty));  } + +std::string WebAssembly::typeListToString(ArrayRef<wasm::ValType> List) { +  std::string S; +  for (auto &Ty : List) { +    if (&Ty != &List[0]) S += ", "; +    S += WebAssembly::typeToString(Ty); +  } +  return S; +} + +std::string WebAssembly::signatureToString(const wasm::WasmSignature *Sig) { +  std::string S("("); +  S += typeListToString(Sig->Params); +  S += ") -> ("; +  S += typeListToString(Sig->Returns); +  S += ")"; +  return S; +} diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.h index b979de5028b..cf37778099a 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.h @@ -58,6 +58,9 @@ namespace WebAssembly {  const char *typeToString(wasm::ValType Ty);  const char *anyTypeToString(unsigned Ty); +std::string typeListToString(ArrayRef<wasm::ValType> List); +std::string signatureToString(const wasm::WasmSignature *Sig); +  } // end namespace WebAssembly  } // end namespace llvm diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp index e05efef7201..40926201931 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp @@ -60,39 +60,10 @@ void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<wasm::ValType> Types) {  void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; } -void WebAssemblyTargetAsmStreamer::emitSignature( -    const wasm::WasmSignature *Sig) { -  OS << "("; -  emitParamList(Sig); -  OS << ") -> ("; -  emitReturnList(Sig); -  OS << ")"; -} - -void WebAssemblyTargetAsmStreamer::emitParamList( -    const wasm::WasmSignature *Sig) { -  auto &Params = Sig->Params; -  for (auto &Ty : Params) { -    if (&Ty != &Params[0]) -      OS << ", "; -    OS << WebAssembly::typeToString(Ty); -  } -} - -void WebAssemblyTargetAsmStreamer::emitReturnList( -    const wasm::WasmSignature *Sig) { -  auto &Returns = Sig->Returns; -  for (auto &Ty : Returns) { -    if (&Ty != &Returns[0]) -      OS << ", "; -    OS << WebAssembly::typeToString(Ty); -  } -} -  void WebAssemblyTargetAsmStreamer::emitFunctionType(const MCSymbolWasm *Sym) {    assert(Sym->isFunction());    OS << "\t.functype\t" << Sym->getName() << " "; -  emitSignature(Sym->getSignature()); +  OS << WebAssembly::signatureToString(Sym->getSignature());    OS << "\n";  } @@ -107,7 +78,7 @@ void WebAssemblyTargetAsmStreamer::emitGlobalType(const MCSymbolWasm *Sym) {  void WebAssemblyTargetAsmStreamer::emitEventType(const MCSymbolWasm *Sym) {    assert(Sym->isEvent());    OS << "\t.eventtype\t" << Sym->getName() << " "; -  emitParamList(Sym->getSignature()); +  OS << WebAssembly::typeListToString(Sym->getSignature()->Params);    OS << "\n";  } diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h index 5ea62b179d2..0164f8e572e 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h @@ -56,9 +56,6 @@ protected:  /// This part is for ascii assembly output  class WebAssemblyTargetAsmStreamer final : public WebAssemblyTargetStreamer {    formatted_raw_ostream &OS; -  void emitSignature(const wasm::WasmSignature *Sig); -  void emitParamList(const wasm::WasmSignature *Sig); -  void emitReturnList(const wasm::WasmSignature *Sig);  public:    WebAssemblyTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS); diff --git a/llvm/test/CodeGen/WebAssembly/reg-stackify.ll b/llvm/test/CodeGen/WebAssembly/reg-stackify.ll index c0668afcefe..9a96016c98f 100644 --- a/llvm/test/CodeGen/WebAssembly/reg-stackify.ll +++ b/llvm/test/CodeGen/WebAssembly/reg-stackify.ll @@ -655,7 +655,7 @@ define i32 @stackpointer_dependency(i8* readnone) {  ; NOREGS-NEXT: local.tee 0  ; NOREGS:      i32.load  0  ; NOREGS-NEXT: i32.load  0 -; NOREGS-NEXT: i32.call_indirect +; NOREGS-NEXT: i32.call_indirect (i32, i32) -> (i32)  %class.call_indirect = type { i32 (...)** }  define i32 @call_indirect_stackify(%class.call_indirect** %objptr, i32 %arg) {    %obj = load %class.call_indirect*, %class.call_indirect** %objptr diff --git a/llvm/test/MC/WebAssembly/basic-assembly.s b/llvm/test/MC/WebAssembly/basic-assembly.s index 23b1a0940f6..ac01dca3755 100644 --- a/llvm/test/MC/WebAssembly/basic-assembly.s +++ b/llvm/test/MC/WebAssembly/basic-assembly.s @@ -34,7 +34,7 @@ test0:      i64.const   1234      i32.call    something2      i32.const   0 -    call_indirect 0 +    call_indirect (i32, f64) -> ()      i32.const   1      i32.add      local.tee   0 @@ -138,7 +138,7 @@ test0:  # CHECK-NEXT:      i64.const   1234  # CHECK-NEXT:      i32.call    something2  # CHECK-NEXT:      i32.const   0 -# CHECK-NEXT:      call_indirect 0 +# CHECK-NEXT:      call_indirect (i32, f64) -> ()  # CHECK-NEXT:      i32.const   1  # CHECK-NEXT:      i32.add  # CHECK-NEXT:      local.tee   0 diff --git a/llvm/test/MC/WebAssembly/tail-call-encodings.s b/llvm/test/MC/WebAssembly/tail-call-encodings.s index a6e921b5434..69839adcfbf 100644 --- a/llvm/test/MC/WebAssembly/tail-call-encodings.s +++ b/llvm/test/MC/WebAssembly/tail-call-encodings.s @@ -16,7 +16,8 @@ foo1:  foo2:      .functype foo2 () -> () -    # CHECK: return_call_indirect 0 # encoding: [0x13,0x00,0x00] -    return_call_indirect 0 +    # CHECK: return_call_indirect (i32) -> (i32) # encoding: [0x13, +    # CHECK-NEXT: fixup A - offset: 1, value: .Ltypeindex0@TYPEINDEX, kind: fixup_uleb128_i32 +    return_call_indirect (i32) -> (i32)      end_function diff --git a/llvm/test/MC/WebAssembly/type-index.s b/llvm/test/MC/WebAssembly/type-index.s new file mode 100644 index 00000000000..707f6aa9894 --- /dev/null +++ b/llvm/test/MC/WebAssembly/type-index.s @@ -0,0 +1,67 @@ +# RUN: llvm-mc -triple=wasm32-unknown-unknown -mattr=+unimplemented-simd128,+nontrapping-fptoint,+exception-handling < %s | FileCheck %s +# Check that it converts to .o without errors: +# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj -mattr=+unimplemented-simd128,+nontrapping-fptoint,+exception-handling < %s | obj2yaml | FileCheck -check-prefix=BIN %s + +# Minimal test for type indices in call_indirect. + +test0: +    .functype   test0 (i32) -> (i32) +    call_indirect (f64) -> (f64) +    end_function + +# CHECK:	.text +# CHECK-LABEL: test0: +# CHECK-NEXT:	.functype	test0 (i32) -> (i32) +# CHECK-NEXT:	call_indirect	(f64) -> (f64) +# CHECK-NEXT:	end_function + +# BIN:      --- !WASM +# BIN-NEXT: FileHeader: +# BIN-NEXT:   Version:         0x00000001 +# BIN-NEXT: Sections: +# BIN-NEXT:   - Type:            TYPE +# BIN-NEXT:     Signatures: +# BIN-NEXT:       - Index:           0 +# BIN-NEXT:         ReturnType:      I32 +# BIN-NEXT:         ParamTypes: +# BIN-NEXT:           - I32 +# BIN-NEXT:       - Index:           1 +# BIN-NEXT:         ReturnType:      F64 +# BIN-NEXT:         ParamTypes: +# BIN-NEXT:           - F64 +# BIN-NEXT:   - Type:            IMPORT +# BIN-NEXT:     Imports: +# BIN-NEXT:       - Module:          env +# BIN-NEXT:         Field:           __linear_memory +# BIN-NEXT:         Kind:            MEMORY +# BIN-NEXT:         Memory: +# BIN-NEXT:           Initial:         0x00000000 +# BIN-NEXT:       - Module:          env +# BIN-NEXT:         Field:           __indirect_function_table +# BIN-NEXT:         Kind:            TABLE +# BIN-NEXT:         Table: +# BIN-NEXT:           ElemType:        FUNCREF +# BIN-NEXT:           Limits: +# BIN-NEXT:             Initial:         0x00000000 +# BIN-NEXT:   - Type:            FUNCTION +# BIN-NEXT:     FunctionTypes:   [ 0 ] +# BIN-NEXT:   - Type:            CODE +# BIN-NEXT:     Relocations: +# BIN-NEXT:       - Type:            R_WASM_TYPE_INDEX_LEB +# BIN-NEXT:         Index:           1 +# BIN-NEXT:         Offset:          0x00000004 +# BIN-NEXT:     Functions: +# BIN-NEXT:       - Index:           0 +# BIN-NEXT:         Locals:          [] +# BIN-NEXT:         Body:            118180808000000B +# BIN-NEXT:   - Type:            CUSTOM +# BIN-NEXT:     Name:            linking +# BIN-NEXT:     Version:         2 +# BIN-NEXT:     SymbolTable: +# BIN-NEXT:       - Index:           0 +# BIN-NEXT:         Kind:            FUNCTION +# BIN-NEXT:         Name:            test0 +# BIN-NEXT:         Flags:           [ BINDING_LOCAL ] +# BIN-NEXT:         Function:        0 +# BIN-NEXT: ... +  | 

