diff options
Diffstat (limited to 'lib/Target/WebAssembly/MCTargetDesc')
12 files changed, 750 insertions, 174 deletions
diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp index 0726dd481174..70b409cf4a90 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp @@ -1,9 +1,8 @@ //===-- WebAssemblyAsmBackend.cpp - WebAssembly Assembler Backend ---------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// @@ -36,7 +35,6 @@ class WebAssemblyAsmBackend final : public MCAsmBackend { public: explicit WebAssemblyAsmBackend(bool Is64Bit) : MCAsmBackend(support::little), Is64Bit(Is64Bit) {} - ~WebAssemblyAsmBackend() override {} unsigned getNumFixupKinds() const override { return WebAssembly::NumTargetFixupKinds; @@ -77,9 +75,9 @@ WebAssemblyAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { // WebAssemblyFixupKinds.h. // // Name Offset (bits) Size (bits) Flags - {"fixup_code_sleb128_i32", 0, 5 * 8, 0}, - {"fixup_code_sleb128_i64", 0, 10 * 8, 0}, - {"fixup_code_uleb128_i32", 0, 5 * 8, 0}, + {"fixup_sleb128_i32", 0, 5 * 8, 0}, + {"fixup_sleb128_i64", 0, 10 * 8, 0}, + {"fixup_uleb128_i32", 0, 5 * 8, 0}, }; if (Kind < FirstTargetFixupKind) @@ -92,7 +90,7 @@ WebAssemblyAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { bool WebAssemblyAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { - for (uint64_t i = 0; i < Count; ++i) + for (uint64_t I = 0; I < Count; ++I) OS << char(WebAssembly::Nop); return true; @@ -119,8 +117,8 @@ void WebAssemblyAsmBackend::applyFixup(const MCAssembler &Asm, // For each byte of the fragment that the fixup touches, mask in the // bits from the fixup value. - for (unsigned i = 0; i != NumBytes; ++i) - Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); + for (unsigned I = 0; I != NumBytes; ++I) + Data[Offset + I] |= uint8_t((Value >> (I * 8)) & 0xff); } std::unique_ptr<MCObjectTargetWriter> diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyFixupKinds.h b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyFixupKinds.h index c2fac5f93a2f..33e8de282955 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyFixupKinds.h +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyFixupKinds.h @@ -1,9 +1,8 @@ //=- WebAssemblyFixupKinds.h - WebAssembly Specific Fixup Entries -*- C++ -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -15,9 +14,9 @@ namespace llvm { namespace WebAssembly { enum Fixups { - fixup_code_sleb128_i32 = FirstTargetFixupKind, // 32-bit signed - fixup_code_sleb128_i64, // 64-bit signed - fixup_code_uleb128_i32, // 32-bit unsigned + fixup_sleb128_i32 = FirstTargetFixupKind, // 32-bit signed + fixup_sleb128_i64, // 64-bit signed + fixup_uleb128_i32, // 32-bit unsigned // Marker LastTargetFixupKind, diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp new file mode 100644 index 000000000000..b5d4d369b726 --- /dev/null +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp @@ -0,0 +1,296 @@ +//=- WebAssemblyInstPrinter.cpp - WebAssembly assembly instruction printing -=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Print MCInst instructions to wasm format. +/// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/WebAssemblyInstPrinter.h" +#include "MCTargetDesc/WebAssemblyMCTargetDesc.h" +#include "WebAssembly.h" +#include "WebAssemblyMachineFunctionInfo.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +using namespace llvm; + +#define DEBUG_TYPE "asm-printer" + +#include "WebAssemblyGenAsmWriter.inc" + +WebAssemblyInstPrinter::WebAssemblyInstPrinter(const MCAsmInfo &MAI, + const MCInstrInfo &MII, + const MCRegisterInfo &MRI) + : MCInstPrinter(MAI, MII, MRI) {} + +void WebAssemblyInstPrinter::printRegName(raw_ostream &OS, + unsigned RegNo) const { + assert(RegNo != WebAssemblyFunctionInfo::UnusedReg); + // Note that there's an implicit local.get/local.set here! + OS << "$" << RegNo; +} + +void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, + StringRef Annot, + const MCSubtargetInfo &STI) { + // Print the instruction (this uses the AsmStrings from the .td files). + printInstruction(MI, OS); + + // Print any additional variadic operands. + const MCInstrDesc &Desc = MII.get(MI->getOpcode()); + if (Desc.isVariadic()) + for (auto I = Desc.getNumOperands(), E = MI->getNumOperands(); I < E; ++I) { + // FIXME: For CALL_INDIRECT_VOID, don't print a leading comma, because + // we have an extra flags operand which is not currently printed, for + // compatiblity reasons. + if (I != 0 && ((MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID && + MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID_S) || + I != Desc.getNumOperands())) + OS << ", "; + printOperand(MI, I, OS); + } + + // Print any added annotation. + printAnnotation(OS, Annot); + + if (CommentStream) { + // Observe any effects on the control flow stack, for use in annotating + // control flow label references. + unsigned Opc = MI->getOpcode(); + switch (Opc) { + default: + break; + + case WebAssembly::LOOP: + case WebAssembly::LOOP_S: + printAnnotation(OS, "label" + utostr(ControlFlowCounter) + ':'); + ControlFlowStack.push_back(std::make_pair(ControlFlowCounter++, true)); + break; + + case WebAssembly::BLOCK: + case WebAssembly::BLOCK_S: + ControlFlowStack.push_back(std::make_pair(ControlFlowCounter++, false)); + break; + + case WebAssembly::TRY: + case WebAssembly::TRY_S: + ControlFlowStack.push_back(std::make_pair(ControlFlowCounter++, false)); + EHPadStack.push_back(EHPadStackCounter++); + LastSeenEHInst = TRY; + break; + + case WebAssembly::END_LOOP: + case WebAssembly::END_LOOP_S: + if (ControlFlowStack.empty()) { + printAnnotation(OS, "End marker mismatch!"); + } else { + ControlFlowStack.pop_back(); + } + break; + + case WebAssembly::END_BLOCK: + case WebAssembly::END_BLOCK_S: + if (ControlFlowStack.empty()) { + printAnnotation(OS, "End marker mismatch!"); + } else { + printAnnotation( + OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':'); + } + break; + + case WebAssembly::END_TRY: + case WebAssembly::END_TRY_S: + if (ControlFlowStack.empty()) { + printAnnotation(OS, "End marker mismatch!"); + } else { + printAnnotation( + OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':'); + LastSeenEHInst = END_TRY; + } + break; + + case WebAssembly::CATCH: + case WebAssembly::CATCH_S: + if (EHPadStack.empty()) { + printAnnotation(OS, "try-catch mismatch!"); + } else { + printAnnotation(OS, "catch" + utostr(EHPadStack.pop_back_val()) + ':'); + } + break; + } + + // Annotate any control flow label references. + + // rethrow instruction does not take any depth argument and rethrows to the + // nearest enclosing catch scope, if any. If there's no enclosing catch + // scope, it throws up to the caller. + if (Opc == WebAssembly::RETHROW || Opc == WebAssembly::RETHROW_S) { + if (EHPadStack.empty()) { + printAnnotation(OS, "to caller"); + } else { + printAnnotation(OS, "down to catch" + utostr(EHPadStack.back())); + } + + } else { + unsigned NumFixedOperands = Desc.NumOperands; + SmallSet<uint64_t, 8> Printed; + for (unsigned I = 0, E = MI->getNumOperands(); I < E; ++I) { + // See if this operand denotes a basic block target. + if (I < NumFixedOperands) { + // A non-variable_ops operand, check its type. + if (Desc.OpInfo[I].OperandType != WebAssembly::OPERAND_BASIC_BLOCK) + continue; + } else { + // A variable_ops operand, which currently can be immediates (used in + // br_table) which are basic block targets, or for call instructions + // when using -wasm-keep-registers (in which case they are registers, + // and should not be processed). + if (!MI->getOperand(I).isImm()) + continue; + } + uint64_t Depth = MI->getOperand(I).getImm(); + if (!Printed.insert(Depth).second) + continue; + if (Depth >= ControlFlowStack.size()) { + printAnnotation(OS, "Invalid depth argument!"); + } else { + const auto &Pair = ControlFlowStack.rbegin()[Depth]; + printAnnotation(OS, utostr(Depth) + ": " + + (Pair.second ? "up" : "down") + " to label" + + utostr(Pair.first)); + } + } + } + } +} + +static std::string toString(const APFloat &FP) { + // Print NaNs with custom payloads specially. + if (FP.isNaN() && !FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics())) && + !FP.bitwiseIsEqual( + APFloat::getQNaN(FP.getSemantics(), /*Negative=*/true))) { + APInt AI = FP.bitcastToAPInt(); + return std::string(AI.isNegative() ? "-" : "") + "nan:0x" + + utohexstr(AI.getZExtValue() & + (AI.getBitWidth() == 32 ? INT64_C(0x007fffff) + : INT64_C(0x000fffffffffffff)), + /*LowerCase=*/true); + } + + // Use C99's hexadecimal floating-point representation. + static const size_t BufBytes = 128; + char Buf[BufBytes]; + auto Written = FP.convertToHexString( + Buf, /*HexDigits=*/0, /*UpperCase=*/false, APFloat::rmNearestTiesToEven); + (void)Written; + assert(Written != 0); + assert(Written < BufBytes); + return Buf; +} + +void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { + const MCOperand &Op = MI->getOperand(OpNo); + if (Op.isReg()) { + unsigned WAReg = Op.getReg(); + if (int(WAReg) >= 0) + printRegName(O, WAReg); + else if (OpNo >= MII.get(MI->getOpcode()).getNumDefs()) + O << "$pop" << WebAssemblyFunctionInfo::getWARegStackId(WAReg); + else if (WAReg != WebAssemblyFunctionInfo::UnusedReg) + O << "$push" << WebAssemblyFunctionInfo::getWARegStackId(WAReg); + else + O << "$drop"; + // Add a '=' suffix if this is a def. + if (OpNo < MII.get(MI->getOpcode()).getNumDefs()) + O << '='; + } else if (Op.isImm()) { + O << Op.getImm(); + } else if (Op.isFPImm()) { + const MCInstrDesc &Desc = MII.get(MI->getOpcode()); + const MCOperandInfo &Info = Desc.OpInfo[OpNo]; + if (Info.OperandType == WebAssembly::OPERAND_F32IMM) { + // TODO: MC converts all floating point immediate operands to double. + // This is fine for numeric values, but may cause NaNs to change bits. + O << ::toString(APFloat(float(Op.getFPImm()))); + } else { + assert(Info.OperandType == WebAssembly::OPERAND_F64IMM); + O << ::toString(APFloat(Op.getFPImm())); + } + } else { + assert(Op.isExpr() && "unknown operand kind in printOperand"); + Op.getExpr()->print(O, &MAI); + } +} + +void WebAssemblyInstPrinter::printBrList(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { + O << "{"; + for (unsigned I = OpNo, E = MI->getNumOperands(); I != E; ++I) { + if (I != OpNo) + O << ", "; + O << MI->getOperand(I).getImm(); + } + O << "}"; +} + +void WebAssemblyInstPrinter::printWebAssemblyP2AlignOperand(const MCInst *MI, + unsigned OpNo, + raw_ostream &O) { + int64_t Imm = MI->getOperand(OpNo).getImm(); + if (Imm == WebAssembly::GetDefaultP2Align(MI->getOpcode())) + return; + O << ":p2align=" << Imm; +} + +void WebAssemblyInstPrinter::printWebAssemblySignatureOperand(const MCInst *MI, + unsigned OpNo, + raw_ostream &O) { + auto Imm = static_cast<unsigned>(MI->getOperand(OpNo).getImm()); + if (Imm != wasm::WASM_TYPE_NORESULT) + O << WebAssembly::anyTypeToString(Imm); +} + +// 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) { + switch (Ty) { + case wasm::WASM_TYPE_I32: + return "i32"; + case wasm::WASM_TYPE_I64: + return "i64"; + case wasm::WASM_TYPE_F32: + return "f32"; + case wasm::WASM_TYPE_F64: + return "f64"; + case wasm::WASM_TYPE_V128: + return "v128"; + case wasm::WASM_TYPE_FUNCREF: + return "funcref"; + case wasm::WASM_TYPE_FUNC: + return "func"; + case wasm::WASM_TYPE_EXNREF: + return "exnref"; + case wasm::WASM_TYPE_NORESULT: + return "void"; + default: + return "invalid_type"; + } +} + +const char *llvm::WebAssembly::typeToString(wasm::ValType Ty) { + return anyTypeToString(static_cast<unsigned>(Ty)); +} diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.h b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.h new file mode 100644 index 000000000000..b979de5028bf --- /dev/null +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.h @@ -0,0 +1,65 @@ +// WebAssemblyInstPrinter.h - Print wasm MCInst to assembly syntax -*- C++ -*-// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This class prints an WebAssembly MCInst to wasm file syntax. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_WEBASSEMBLY_INSTPRINTER_WEBASSEMBLYINSTPRINTER_H +#define LLVM_LIB_TARGET_WEBASSEMBLY_INSTPRINTER_WEBASSEMBLYINSTPRINTER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/BinaryFormat/Wasm.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/Support/MachineValueType.h" + +namespace llvm { + +class MCSubtargetInfo; + +class WebAssemblyInstPrinter final : public MCInstPrinter { + uint64_t ControlFlowCounter = 0; + uint64_t EHPadStackCounter = 0; + SmallVector<std::pair<uint64_t, bool>, 4> ControlFlowStack; + SmallVector<uint64_t, 4> EHPadStack; + + enum EHInstKind { TRY, CATCH, END_TRY }; + EHInstKind LastSeenEHInst = END_TRY; + +public: + WebAssemblyInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, + const MCRegisterInfo &MRI); + + void printRegName(raw_ostream &OS, unsigned RegNo) const override; + void printInst(const MCInst *MI, raw_ostream &OS, StringRef Annot, + const MCSubtargetInfo &STI) override; + + // Used by tblegen code. + void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); + void printBrList(const MCInst *MI, unsigned OpNo, raw_ostream &O); + void printWebAssemblyP2AlignOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O); + void printWebAssemblySignatureOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O); + + // Autogenerated by tblgen. + void printInstruction(const MCInst *MI, raw_ostream &O); + static const char *getRegisterName(unsigned RegNo); +}; + +namespace WebAssembly { + +const char *typeToString(wasm::ValType Ty); +const char *anyTypeToString(unsigned Ty); + +} // end namespace WebAssembly + +} // end namespace llvm + +#endif diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp index 44fcc129c39e..8f6531563e1b 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp @@ -1,9 +1,8 @@ //===-- WebAssemblyMCAsmInfo.cpp - WebAssembly asm properties -------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// @@ -20,7 +19,7 @@ using namespace llvm; #define DEBUG_TYPE "wasm-mc-asm-info" -WebAssemblyMCAsmInfo::~WebAssemblyMCAsmInfo() {} +WebAssemblyMCAsmInfo::~WebAssemblyMCAsmInfo() = default; // anchor. WebAssemblyMCAsmInfo::WebAssemblyMCAsmInfo(const Triple &T) { CodePointerSize = CalleeSaveStackSlotSize = T.isArch64Bit() ? 8 : 4; diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.h b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.h index 8627a6e40c6a..9efbbf881f59 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.h +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.h @@ -1,9 +1,8 @@ //===-- WebAssemblyMCAsmInfo.h - WebAssembly asm properties -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp index 065a4dc94ca6..44b6d6a968a9 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp @@ -1,9 +1,8 @@ //=- WebAssemblyMCCodeEmitter.cpp - Convert WebAssembly code to machine code -// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// @@ -49,7 +48,7 @@ class WebAssemblyMCCodeEmitter final : public MCCodeEmitter { const MCSubtargetInfo &STI) const override; public: - WebAssemblyMCCodeEmitter(const MCInstrInfo &mcii) : MCII(mcii) {} + WebAssemblyMCCodeEmitter(const MCInstrInfo &MCII) : MCII(MCII) {} }; } // end anonymous namespace @@ -82,14 +81,14 @@ void WebAssemblyMCCodeEmitter::encodeInstruction( encodeULEB128(MI.getNumOperands() - 2, OS); const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); - for (unsigned i = 0, e = MI.getNumOperands(); i < e; ++i) { - const MCOperand &MO = MI.getOperand(i); + for (unsigned I = 0, E = MI.getNumOperands(); I < E; ++I) { + const MCOperand &MO = MI.getOperand(I); if (MO.isReg()) { /* nothing to encode */ } else if (MO.isImm()) { - if (i < Desc.getNumOperands()) { - const MCOperandInfo &Info = Desc.OpInfo[i]; + if (I < Desc.getNumOperands()) { + const MCOperandInfo &Info = Desc.OpInfo[I]; LLVM_DEBUG(dbgs() << "Encoding immediate: type=" << int(Info.OperandType) << "\n"); switch (Info.OperandType) { @@ -127,28 +126,28 @@ void WebAssemblyMCCodeEmitter::encodeInstruction( } } else if (MO.isFPImm()) { - const MCOperandInfo &Info = Desc.OpInfo[i]; + const MCOperandInfo &Info = Desc.OpInfo[I]; if (Info.OperandType == WebAssembly::OPERAND_F32IMM) { // TODO: MC converts all floating point immediate operands to double. // This is fine for numeric values, but may cause NaNs to change bits. - float f = float(MO.getFPImm()); - support::endian::write<float>(OS, f, support::little); + auto F = float(MO.getFPImm()); + support::endian::write<float>(OS, F, support::little); } else { assert(Info.OperandType == WebAssembly::OPERAND_F64IMM); - double d = MO.getFPImm(); - support::endian::write<double>(OS, d, support::little); + double D = MO.getFPImm(); + support::endian::write<double>(OS, D, support::little); } } else if (MO.isExpr()) { - const MCOperandInfo &Info = Desc.OpInfo[i]; + const MCOperandInfo &Info = Desc.OpInfo[I]; llvm::MCFixupKind FixupKind; size_t PaddedSize = 5; switch (Info.OperandType) { case WebAssembly::OPERAND_I32IMM: - FixupKind = MCFixupKind(WebAssembly::fixup_code_sleb128_i32); + FixupKind = MCFixupKind(WebAssembly::fixup_sleb128_i32); break; case WebAssembly::OPERAND_I64IMM: - FixupKind = MCFixupKind(WebAssembly::fixup_code_sleb128_i64); + FixupKind = MCFixupKind(WebAssembly::fixup_sleb128_i64); PaddedSize = 10; break; case WebAssembly::OPERAND_FUNCTION32: @@ -156,7 +155,7 @@ void WebAssemblyMCCodeEmitter::encodeInstruction( case WebAssembly::OPERAND_TYPEINDEX: case WebAssembly::OPERAND_GLOBAL: case WebAssembly::OPERAND_EVENT: - FixupKind = MCFixupKind(WebAssembly::fixup_code_uleb128_i32); + FixupKind = MCFixupKind(WebAssembly::fixup_uleb128_i32); break; default: llvm_unreachable("unexpected symbolic operand kind"); diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp index 390f367c2978..9c8ca1f13b18 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp @@ -1,9 +1,8 @@ //===-- WebAssemblyMCTargetDesc.cpp - WebAssembly Target Descriptions -----===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// @@ -12,10 +11,11 @@ /// //===----------------------------------------------------------------------===// -#include "WebAssemblyMCTargetDesc.h" -#include "InstPrinter/WebAssemblyInstPrinter.h" -#include "WebAssemblyMCAsmInfo.h" -#include "WebAssemblyTargetStreamer.h" +#include "MCTargetDesc/WebAssemblyMCTargetDesc.h" +#include "MCTargetDesc/WebAssemblyInstPrinter.h" +#include "MCTargetDesc/WebAssemblyMCAsmInfo.h" +#include "MCTargetDesc/WebAssemblyTargetStreamer.h" +#include "TargetInfo/WebAssemblyTargetInfo.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -40,13 +40,13 @@ static MCAsmInfo *createMCAsmInfo(const MCRegisterInfo & /*MRI*/, } static MCInstrInfo *createMCInstrInfo() { - MCInstrInfo *X = new MCInstrInfo(); + auto *X = new MCInstrInfo(); InitWebAssemblyMCInstrInfo(X); return X; } static MCRegisterInfo *createMCRegisterInfo(const Triple & /*T*/) { - MCRegisterInfo *X = new MCRegisterInfo(); + auto *X = new MCRegisterInfo(); InitWebAssemblyMCRegisterInfo(X, 0); return X; } @@ -146,8 +146,8 @@ wasm::ValType WebAssembly::toValType(const MVT &Ty) { case MVT::v4f32: case MVT::v2f64: return wasm::ValType::V128; - case MVT::ExceptRef: - return wasm::ValType::EXCEPT_REF; + case MVT::exnref: + return wasm::ValType::EXNREF; default: llvm_unreachable("unexpected type"); } diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h index a01517fb90c3..7a9f59b1a4f2 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -1,9 +1,8 @@ //==- WebAssemblyMCTargetDesc.h - WebAssembly Target Descriptions -*- C++ -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// @@ -15,6 +14,7 @@ #ifndef LLVM_LIB_TARGET_WEBASSEMBLY_MCTARGETDESC_WEBASSEMBLYMCTARGETDESC_H #define LLVM_LIB_TARGET_WEBASSEMBLY_MCTARGETDESC_WEBASSEMBLYMCTARGETDESC_H +#include "../WebAssemblySubtarget.h" #include "llvm/BinaryFormat/Wasm.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/Support/DataTypes.h" @@ -33,9 +33,6 @@ class Target; class Triple; class raw_pwrite_stream; -Target &getTheWebAssemblyTarget32(); -Target &getTheWebAssemblyTarget64(); - MCCodeEmitter *createWebAssemblyMCCodeEmitter(const MCInstrInfo &MCII); MCAsmBackend *createWebAssemblyAsmBackend(const Triple &TT); @@ -90,12 +87,23 @@ namespace WebAssemblyII { enum TOF { MO_NO_FLAG = 0, - // Flags to indicate the type of the symbol being referenced - MO_SYMBOL_FUNCTION = 0x1, - MO_SYMBOL_GLOBAL = 0x2, - MO_SYMBOL_EVENT = 0x4, - MO_SYMBOL_MASK = 0x7, + // On a symbol operand this indicates that the immediate is a wasm global + // index. The value of the wasm global will be set to the symbol address at + // runtime. This adds a level of indirection similar to the GOT on native + // platforms. + MO_GOT, + + // On a symbol operand this indicates that the immediate is the symbol + // address relative the __memory_base wasm global. + // Only applicable to data symbols. + MO_MEMORY_BASE_REL, + + // On a symbol operand this indicates that the immediate is the symbol + // address relative the __table_base wasm global. + // Only applicable to function symbols. + MO_TABLE_BASE_REL, }; + } // end namespace WebAssemblyII } // end namespace llvm @@ -111,15 +119,30 @@ enum TOF { #define GET_INSTRINFO_ENUM #include "WebAssemblyGenInstrInfo.inc" -#define GET_SUBTARGETINFO_ENUM -#include "WebAssemblyGenSubtargetInfo.inc" - namespace llvm { namespace WebAssembly { +/// This is used to indicate block signatures. +enum class ExprType : unsigned { + Void = 0x40, + I32 = 0x7F, + I64 = 0x7E, + F32 = 0x7D, + F64 = 0x7C, + V128 = 0x7B, + Exnref = 0x68, + Invalid = 0x00 +}; + +/// Instruction opcodes emitted via means other than CodeGen. +static const unsigned Nop = 0x01; +static const unsigned End = 0x0b; + +wasm::ValType toValType(const MVT &Ty); + /// Return the default p2align value for a load or store with the given opcode. -inline unsigned GetDefaultP2Align(unsigned Opcode) { - switch (Opcode) { +inline unsigned GetDefaultP2AlignAny(unsigned Opc) { + switch (Opc) { case WebAssembly::LOAD8_S_I32: case WebAssembly::LOAD8_S_I32_S: case WebAssembly::LOAD8_U_I32: @@ -328,35 +351,238 @@ inline unsigned GetDefaultP2Align(unsigned Opcode) { case WebAssembly::STORE_v2f64_S: return 4; default: + return -1; + } +} + +inline unsigned GetDefaultP2Align(unsigned Opc) { + auto Align = GetDefaultP2AlignAny(Opc); + if (Align == -1U) { llvm_unreachable("Only loads and stores have p2align values"); } + return Align; } -/// The operand number of the load or store address in load/store instructions. -static const unsigned LoadAddressOperandNo = 3; -static const unsigned StoreAddressOperandNo = 2; +inline bool isArgument(unsigned Opc) { + switch (Opc) { + case WebAssembly::ARGUMENT_i32: + case WebAssembly::ARGUMENT_i32_S: + case WebAssembly::ARGUMENT_i64: + case WebAssembly::ARGUMENT_i64_S: + case WebAssembly::ARGUMENT_f32: + case WebAssembly::ARGUMENT_f32_S: + case WebAssembly::ARGUMENT_f64: + case WebAssembly::ARGUMENT_f64_S: + case WebAssembly::ARGUMENT_v16i8: + case WebAssembly::ARGUMENT_v16i8_S: + case WebAssembly::ARGUMENT_v8i16: + case WebAssembly::ARGUMENT_v8i16_S: + case WebAssembly::ARGUMENT_v4i32: + case WebAssembly::ARGUMENT_v4i32_S: + case WebAssembly::ARGUMENT_v2i64: + case WebAssembly::ARGUMENT_v2i64_S: + case WebAssembly::ARGUMENT_v4f32: + case WebAssembly::ARGUMENT_v4f32_S: + case WebAssembly::ARGUMENT_v2f64: + case WebAssembly::ARGUMENT_v2f64_S: + case WebAssembly::ARGUMENT_exnref: + case WebAssembly::ARGUMENT_exnref_S: + return true; + default: + return false; + } +} -/// The operand number of the load or store p2align in load/store instructions. -static const unsigned LoadP2AlignOperandNo = 1; -static const unsigned StoreP2AlignOperandNo = 0; +inline bool isCopy(unsigned Opc) { + switch (Opc) { + case WebAssembly::COPY_I32: + case WebAssembly::COPY_I32_S: + case WebAssembly::COPY_I64: + case WebAssembly::COPY_I64_S: + case WebAssembly::COPY_F32: + case WebAssembly::COPY_F32_S: + case WebAssembly::COPY_F64: + case WebAssembly::COPY_F64_S: + case WebAssembly::COPY_V128: + case WebAssembly::COPY_V128_S: + case WebAssembly::COPY_EXNREF: + case WebAssembly::COPY_EXNREF_S: + return true; + default: + return false; + } +} -/// This is used to indicate block signatures. -enum class ExprType : unsigned { - Void = 0x40, - I32 = 0x7F, - I64 = 0x7E, - F32 = 0x7D, - F64 = 0x7C, - V128 = 0x7B, - ExceptRef = 0x68, - Invalid = 0x00 -}; +inline bool isTee(unsigned Opc) { + switch (Opc) { + case WebAssembly::TEE_I32: + case WebAssembly::TEE_I32_S: + case WebAssembly::TEE_I64: + case WebAssembly::TEE_I64_S: + case WebAssembly::TEE_F32: + case WebAssembly::TEE_F32_S: + case WebAssembly::TEE_F64: + case WebAssembly::TEE_F64_S: + case WebAssembly::TEE_V128: + case WebAssembly::TEE_V128_S: + case WebAssembly::TEE_EXNREF: + case WebAssembly::TEE_EXNREF_S: + return true; + default: + return false; + } +} -/// Instruction opcodes emitted via means other than CodeGen. -static const unsigned Nop = 0x01; -static const unsigned End = 0x0b; +inline bool isCallDirect(unsigned Opc) { + switch (Opc) { + case WebAssembly::CALL_VOID: + case WebAssembly::CALL_VOID_S: + case WebAssembly::CALL_i32: + case WebAssembly::CALL_i32_S: + case WebAssembly::CALL_i64: + case WebAssembly::CALL_i64_S: + case WebAssembly::CALL_f32: + case WebAssembly::CALL_f32_S: + case WebAssembly::CALL_f64: + case WebAssembly::CALL_f64_S: + case WebAssembly::CALL_v16i8: + case WebAssembly::CALL_v16i8_S: + case WebAssembly::CALL_v8i16: + case WebAssembly::CALL_v8i16_S: + case WebAssembly::CALL_v4i32: + case WebAssembly::CALL_v4i32_S: + case WebAssembly::CALL_v2i64: + case WebAssembly::CALL_v2i64_S: + case WebAssembly::CALL_v4f32: + case WebAssembly::CALL_v4f32_S: + case WebAssembly::CALL_v2f64: + case WebAssembly::CALL_v2f64_S: + case WebAssembly::CALL_exnref: + case WebAssembly::CALL_exnref_S: + case WebAssembly::RET_CALL: + case WebAssembly::RET_CALL_S: + return true; + default: + return false; + } +} -wasm::ValType toValType(const MVT &Ty); +inline bool isCallIndirect(unsigned Opc) { + switch (Opc) { + case WebAssembly::CALL_INDIRECT_VOID: + case WebAssembly::CALL_INDIRECT_VOID_S: + case WebAssembly::CALL_INDIRECT_i32: + case WebAssembly::CALL_INDIRECT_i32_S: + case WebAssembly::CALL_INDIRECT_i64: + case WebAssembly::CALL_INDIRECT_i64_S: + case WebAssembly::CALL_INDIRECT_f32: + case WebAssembly::CALL_INDIRECT_f32_S: + case WebAssembly::CALL_INDIRECT_f64: + case WebAssembly::CALL_INDIRECT_f64_S: + case WebAssembly::CALL_INDIRECT_v16i8: + case WebAssembly::CALL_INDIRECT_v16i8_S: + case WebAssembly::CALL_INDIRECT_v8i16: + case WebAssembly::CALL_INDIRECT_v8i16_S: + case WebAssembly::CALL_INDIRECT_v4i32: + case WebAssembly::CALL_INDIRECT_v4i32_S: + case WebAssembly::CALL_INDIRECT_v2i64: + case WebAssembly::CALL_INDIRECT_v2i64_S: + case WebAssembly::CALL_INDIRECT_v4f32: + case WebAssembly::CALL_INDIRECT_v4f32_S: + case WebAssembly::CALL_INDIRECT_v2f64: + case WebAssembly::CALL_INDIRECT_v2f64_S: + case WebAssembly::CALL_INDIRECT_exnref: + case WebAssembly::CALL_INDIRECT_exnref_S: + case WebAssembly::RET_CALL_INDIRECT: + case WebAssembly::RET_CALL_INDIRECT_S: + return true; + default: + return false; + } +} + +/// Returns the operand number of a callee, assuming the argument is a call +/// instruction. +inline unsigned getCalleeOpNo(unsigned Opc) { + switch (Opc) { + case WebAssembly::CALL_VOID: + case WebAssembly::CALL_VOID_S: + case WebAssembly::CALL_INDIRECT_VOID: + case WebAssembly::CALL_INDIRECT_VOID_S: + case WebAssembly::RET_CALL: + case WebAssembly::RET_CALL_S: + case WebAssembly::RET_CALL_INDIRECT: + case WebAssembly::RET_CALL_INDIRECT_S: + return 0; + case WebAssembly::CALL_i32: + case WebAssembly::CALL_i32_S: + case WebAssembly::CALL_i64: + case WebAssembly::CALL_i64_S: + case WebAssembly::CALL_f32: + case WebAssembly::CALL_f32_S: + case WebAssembly::CALL_f64: + case WebAssembly::CALL_f64_S: + case WebAssembly::CALL_v16i8: + case WebAssembly::CALL_v16i8_S: + case WebAssembly::CALL_v8i16: + case WebAssembly::CALL_v8i16_S: + case WebAssembly::CALL_v4i32: + case WebAssembly::CALL_v4i32_S: + case WebAssembly::CALL_v2i64: + case WebAssembly::CALL_v2i64_S: + case WebAssembly::CALL_v4f32: + case WebAssembly::CALL_v4f32_S: + case WebAssembly::CALL_v2f64: + case WebAssembly::CALL_v2f64_S: + case WebAssembly::CALL_exnref: + case WebAssembly::CALL_exnref_S: + case WebAssembly::CALL_INDIRECT_i32: + case WebAssembly::CALL_INDIRECT_i32_S: + case WebAssembly::CALL_INDIRECT_i64: + case WebAssembly::CALL_INDIRECT_i64_S: + case WebAssembly::CALL_INDIRECT_f32: + case WebAssembly::CALL_INDIRECT_f32_S: + case WebAssembly::CALL_INDIRECT_f64: + case WebAssembly::CALL_INDIRECT_f64_S: + case WebAssembly::CALL_INDIRECT_v16i8: + case WebAssembly::CALL_INDIRECT_v16i8_S: + case WebAssembly::CALL_INDIRECT_v8i16: + case WebAssembly::CALL_INDIRECT_v8i16_S: + case WebAssembly::CALL_INDIRECT_v4i32: + case WebAssembly::CALL_INDIRECT_v4i32_S: + case WebAssembly::CALL_INDIRECT_v2i64: + case WebAssembly::CALL_INDIRECT_v2i64_S: + case WebAssembly::CALL_INDIRECT_v4f32: + case WebAssembly::CALL_INDIRECT_v4f32_S: + case WebAssembly::CALL_INDIRECT_v2f64: + case WebAssembly::CALL_INDIRECT_v2f64_S: + case WebAssembly::CALL_INDIRECT_exnref: + case WebAssembly::CALL_INDIRECT_exnref_S: + return 1; + default: + llvm_unreachable("Not a call instruction"); + } +} + +inline bool isMarker(unsigned Opc) { + switch (Opc) { + case WebAssembly::BLOCK: + case WebAssembly::BLOCK_S: + case WebAssembly::END_BLOCK: + case WebAssembly::END_BLOCK_S: + case WebAssembly::LOOP: + case WebAssembly::LOOP_S: + case WebAssembly::END_LOOP: + case WebAssembly::END_LOOP_S: + case WebAssembly::TRY: + case WebAssembly::TRY_S: + case WebAssembly::END_TRY: + case WebAssembly::END_TRY_S: + return true; + default: + return false; + } +} } // end namespace WebAssembly } // end namespace llvm diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp index 50143fb0ece3..e05efef7201b 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp @@ -1,9 +1,8 @@ //==-- WebAssemblyTargetStreamer.cpp - WebAssembly Target Streamer Methods --=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// @@ -13,9 +12,9 @@ /// //===----------------------------------------------------------------------===// -#include "WebAssemblyTargetStreamer.h" -#include "InstPrinter/WebAssemblyInstPrinter.h" -#include "WebAssemblyMCTargetDesc.h" +#include "MCTargetDesc/WebAssemblyTargetStreamer.h" +#include "MCTargetDesc/WebAssemblyInstPrinter.h" +#include "MCTargetDesc/WebAssemblyMCTargetDesc.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSectionWasm.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -113,8 +112,15 @@ void WebAssemblyTargetAsmStreamer::emitEventType(const MCSymbolWasm *Sym) { } void WebAssemblyTargetAsmStreamer::emitImportModule(const MCSymbolWasm *Sym, - StringRef ModuleName) { - OS << "\t.import_module\t" << Sym->getName() << ", " << ModuleName << '\n'; + StringRef ImportModule) { + OS << "\t.import_module\t" << Sym->getName() << ", " + << ImportModule << '\n'; +} + +void WebAssemblyTargetAsmStreamer::emitImportName(const MCSymbolWasm *Sym, + StringRef ImportName) { + OS << "\t.import_name\t" << Sym->getName() << ", " + << ImportName << '\n'; } void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) { diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h index 3073938118b4..5ea62b179d22 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h @@ -1,9 +1,8 @@ //==-- WebAssemblyTargetStreamer.h - WebAssembly Target Streamer -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// @@ -45,7 +44,10 @@ public: virtual void emitEventType(const MCSymbolWasm *Sym) = 0; /// .import_module virtual void emitImportModule(const MCSymbolWasm *Sym, - StringRef ModuleName) = 0; + StringRef ImportModule) = 0; + /// .import_name + virtual void emitImportName(const MCSymbolWasm *Sym, + StringRef ImportName) = 0; protected: void emitValueType(wasm::ValType Type); @@ -67,7 +69,8 @@ public: void emitIndIdx(const MCExpr *Value) override; void emitGlobalType(const MCSymbolWasm *Sym) override; void emitEventType(const MCSymbolWasm *Sym) override; - void emitImportModule(const MCSymbolWasm *Sym, StringRef ModuleName) override; + void emitImportModule(const MCSymbolWasm *Sym, StringRef ImportModule) override; + void emitImportName(const MCSymbolWasm *Sym, StringRef ImportName) override; }; /// This part is for Wasm object output @@ -82,7 +85,9 @@ public: void emitGlobalType(const MCSymbolWasm *Sym) override {} void emitEventType(const MCSymbolWasm *Sym) override {} void emitImportModule(const MCSymbolWasm *Sym, - StringRef ModuleName) override {} + StringRef ImportModule) override {} + void emitImportName(const MCSymbolWasm *Sym, + StringRef ImportName) override {} }; /// This part is for null output @@ -98,6 +103,7 @@ public: void emitGlobalType(const MCSymbolWasm *) override {} void emitEventType(const MCSymbolWasm *) override {} void emitImportModule(const MCSymbolWasm *, StringRef) override {} + void emitImportName(const MCSymbolWasm *, StringRef) override {} }; } // end namespace llvm diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp index 763e30be8e02..a1cc3e268e8f 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp @@ -1,9 +1,8 @@ //===-- WebAssemblyWasmObjectWriter.cpp - WebAssembly Wasm Writer ---------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// @@ -43,26 +42,7 @@ private: WebAssemblyWasmObjectWriter::WebAssemblyWasmObjectWriter(bool Is64Bit) : MCWasmObjectTargetWriter(Is64Bit) {} -// Test whether the given expression computes a function address. -static bool IsFunctionExpr(const MCExpr *Expr) { - if (auto SyExp = dyn_cast<MCSymbolRefExpr>(Expr)) - return cast<MCSymbolWasm>(SyExp->getSymbol()).isFunction(); - - if (auto BinOp = dyn_cast<MCBinaryExpr>(Expr)) - return IsFunctionExpr(BinOp->getLHS()) != IsFunctionExpr(BinOp->getRHS()); - - if (auto UnOp = dyn_cast<MCUnaryExpr>(Expr)) - return IsFunctionExpr(UnOp->getSubExpr()); - - return false; -} - -static bool IsFunctionType(const MCValue &Target) { - const MCSymbolRefExpr *RefA = Target.getSymA(); - return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_TYPEINDEX; -} - -static const MCSection *GetFixupSection(const MCExpr *Expr) { +static const MCSection *getFixupSection(const MCExpr *Expr) { if (auto SyExp = dyn_cast<MCSymbolRefExpr>(Expr)) { if (SyExp->getSymbol().isInSection()) return &SyExp->getSymbol().getSection(); @@ -70,63 +50,66 @@ static const MCSection *GetFixupSection(const MCExpr *Expr) { } if (auto BinOp = dyn_cast<MCBinaryExpr>(Expr)) { - auto SectionLHS = GetFixupSection(BinOp->getLHS()); - auto SectionRHS = GetFixupSection(BinOp->getRHS()); + auto SectionLHS = getFixupSection(BinOp->getLHS()); + auto SectionRHS = getFixupSection(BinOp->getRHS()); return SectionLHS == SectionRHS ? nullptr : SectionLHS; } if (auto UnOp = dyn_cast<MCUnaryExpr>(Expr)) - return GetFixupSection(UnOp->getSubExpr()); + return getFixupSection(UnOp->getSubExpr()); return nullptr; } -static bool IsGlobalType(const MCValue &Target) { - const MCSymbolRefExpr *RefA = Target.getSymA(); - return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_GLOBAL; -} - -static bool IsEventType(const MCValue &Target) { - const MCSymbolRefExpr *RefA = Target.getSymA(); - return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_EVENT; -} - unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target, const MCFixup &Fixup) const { - // WebAssembly functions are not allocated in the data address space. To - // resolve a pointer to a function, we must use a special relocation type. - bool IsFunction = IsFunctionExpr(Fixup.getValue()); + const MCSymbolRefExpr *RefA = Target.getSymA(); + assert(RefA); + auto& SymA = cast<MCSymbolWasm>(RefA->getSymbol()); + + MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); + + switch (Modifier) { + case MCSymbolRefExpr::VK_GOT: + return wasm::R_WASM_GLOBAL_INDEX_LEB; + case MCSymbolRefExpr::VK_WASM_TBREL: + assert(SymA.isFunction()); + return wasm::R_WASM_TABLE_INDEX_REL_SLEB; + case MCSymbolRefExpr::VK_WASM_MBREL: + assert(SymA.isData()); + return wasm::R_WASM_MEMORY_ADDR_REL_SLEB; + case MCSymbolRefExpr::VK_WASM_TYPEINDEX: + return wasm::R_WASM_TYPE_INDEX_LEB; + default: + break; + } switch (unsigned(Fixup.getKind())) { - case WebAssembly::fixup_code_sleb128_i32: - if (IsFunction) - return wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB; - return wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB; - case WebAssembly::fixup_code_sleb128_i64: + case WebAssembly::fixup_sleb128_i32: + if (SymA.isFunction()) + return wasm::R_WASM_TABLE_INDEX_SLEB; + return wasm::R_WASM_MEMORY_ADDR_SLEB; + case WebAssembly::fixup_sleb128_i64: llvm_unreachable("fixup_sleb128_i64 not implemented yet"); - case WebAssembly::fixup_code_uleb128_i32: - if (IsGlobalType(Target)) - return wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB; - if (IsFunctionType(Target)) - return wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB; - if (IsFunction) - return wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB; - if (IsEventType(Target)) - return wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB; - return wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB; + case WebAssembly::fixup_uleb128_i32: + if (SymA.isGlobal()) + return wasm::R_WASM_GLOBAL_INDEX_LEB; + if (SymA.isFunction()) + return wasm::R_WASM_FUNCTION_INDEX_LEB; + if (SymA.isEvent()) + return wasm::R_WASM_EVENT_INDEX_LEB; + return wasm::R_WASM_MEMORY_ADDR_LEB; case FK_Data_4: - if (IsFunction) - return wasm::R_WEBASSEMBLY_TABLE_INDEX_I32; + if (SymA.isFunction()) + return wasm::R_WASM_TABLE_INDEX_I32; if (auto Section = static_cast<const MCSectionWasm *>( - GetFixupSection(Fixup.getValue()))) { + getFixupSection(Fixup.getValue()))) { if (Section->getKind().isText()) - return wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32; + return wasm::R_WASM_FUNCTION_OFFSET_I32; else if (!Section->isWasmData()) - return wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32; + return wasm::R_WASM_SECTION_OFFSET_I32; } - return wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32; - case FK_Data_8: - llvm_unreachable("FK_Data_8 not implemented yet"); + return wasm::R_WASM_MEMORY_ADDR_I32; default: llvm_unreachable("unimplemented fixup kind"); } |