aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Target/WebAssembly/MCTargetDesc')
-rw-r--r--contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp206
-rw-r--r--contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyELFObjectWriter.cpp68
-rw-r--r--contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyFixupKinds.h31
-rw-r--r--contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp83
-rw-r--r--contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.h39
-rw-r--r--contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp152
-rw-r--r--contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp140
-rw-r--r--contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h185
-rw-r--r--contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp264
-rw-r--r--contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h112
-rw-r--r--contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp102
11 files changed, 1382 insertions, 0 deletions
diff --git a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp
new file mode 100644
index 000000000000..226a3b35f2cf
--- /dev/null
+++ b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp
@@ -0,0 +1,206 @@
+//===-- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file implements the WebAssemblyAsmBackend class.
+///
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/WebAssemblyFixupKinds.h"
+#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCDirectives.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCFixupKindInfo.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCWasmObjectWriter.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+namespace {
+class WebAssemblyAsmBackendELF final : public MCAsmBackend {
+ bool Is64Bit;
+
+public:
+ explicit WebAssemblyAsmBackendELF(bool Is64Bit)
+ : MCAsmBackend(), Is64Bit(Is64Bit) {}
+ ~WebAssemblyAsmBackendELF() override {}
+
+ void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, MutableArrayRef<char> Data,
+ uint64_t Value, bool IsPCRel) const override;
+
+ std::unique_ptr<MCObjectWriter>
+ createObjectWriter(raw_pwrite_stream &OS) const override;
+
+ // No instruction requires relaxation
+ bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
+ const MCRelaxableFragment *DF,
+ const MCAsmLayout &Layout) const override {
+ return false;
+ }
+
+ unsigned getNumFixupKinds() const override {
+ // We currently just use the generic fixups in MCFixup.h and don't have any
+ // target-specific fixups.
+ return 0;
+ }
+
+ bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
+
+ void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ MCInst &Res) const override {}
+
+ bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
+};
+
+class WebAssemblyAsmBackend final : public MCAsmBackend {
+ bool Is64Bit;
+
+public:
+ explicit WebAssemblyAsmBackend(bool Is64Bit)
+ : MCAsmBackend(), Is64Bit(Is64Bit) {}
+ ~WebAssemblyAsmBackend() override {}
+
+ unsigned getNumFixupKinds() const override {
+ return WebAssembly::NumTargetFixupKinds;
+ }
+
+ const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
+
+ void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, MutableArrayRef<char> Data,
+ uint64_t Value, bool IsPCRel) const override;
+
+ std::unique_ptr<MCObjectWriter>
+ createObjectWriter(raw_pwrite_stream &OS) const override;
+
+ // No instruction requires relaxation
+ bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
+ const MCRelaxableFragment *DF,
+ const MCAsmLayout &Layout) const override {
+ return false;
+ }
+
+ bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
+
+ void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ MCInst &Res) const override {}
+
+ bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
+};
+
+bool WebAssemblyAsmBackendELF::writeNopData(uint64_t Count,
+ MCObjectWriter *OW) const {
+ for (uint64_t i = 0; i < Count; ++i)
+ OW->write8(WebAssembly::Nop);
+
+ return true;
+}
+
+void WebAssemblyAsmBackendELF::applyFixup(const MCAssembler &Asm,
+ const MCFixup &Fixup,
+ const MCValue &Target,
+ MutableArrayRef<char> Data,
+ uint64_t Value, bool IsPCRel) const {
+ const MCFixupKindInfo &Info = getFixupKindInfo(Fixup.getKind());
+ assert(Info.Flags == 0 && "WebAssembly does not use MCFixupKindInfo flags");
+
+ unsigned NumBytes = alignTo(Info.TargetSize, 8) / 8;
+ if (Value == 0)
+ return; // Doesn't change encoding.
+
+ // Shift the value into position.
+ Value <<= Info.TargetOffset;
+
+ unsigned Offset = Fixup.getOffset();
+ assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
+
+ // 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);
+}
+
+std::unique_ptr<MCObjectWriter>
+WebAssemblyAsmBackendELF::createObjectWriter(raw_pwrite_stream &OS) const {
+ return createWebAssemblyELFObjectWriter(OS, Is64Bit, 0);
+}
+
+const MCFixupKindInfo &
+WebAssemblyAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
+ const static MCFixupKindInfo Infos[WebAssembly::NumTargetFixupKinds] = {
+ // This table *must* be in the order that the fixup_* kinds are defined in
+ // 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 },
+ };
+
+ if (Kind < FirstTargetFixupKind)
+ return MCAsmBackend::getFixupKindInfo(Kind);
+
+ assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
+ "Invalid kind!");
+ return Infos[Kind - FirstTargetFixupKind];
+}
+
+bool WebAssemblyAsmBackend::writeNopData(uint64_t Count,
+ MCObjectWriter *OW) const {
+ if (Count == 0)
+ return true;
+
+ for (uint64_t i = 0; i < Count; ++i)
+ OW->write8(WebAssembly::Nop);
+
+ return true;
+}
+
+void WebAssemblyAsmBackend::applyFixup(const MCAssembler &Asm,
+ const MCFixup &Fixup,
+ const MCValue &Target,
+ MutableArrayRef<char> Data,
+ uint64_t Value, bool IsPCRel) const {
+ const MCFixupKindInfo &Info = getFixupKindInfo(Fixup.getKind());
+ assert(Info.Flags == 0 && "WebAssembly does not use MCFixupKindInfo flags");
+
+ unsigned NumBytes = alignTo(Info.TargetSize, 8) / 8;
+ if (Value == 0)
+ return; // Doesn't change encoding.
+
+ // Shift the value into position.
+ Value <<= Info.TargetOffset;
+
+ unsigned Offset = Fixup.getOffset();
+ assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
+
+ // 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);
+}
+
+std::unique_ptr<MCObjectWriter>
+WebAssemblyAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
+ return createWebAssemblyWasmObjectWriter(OS, Is64Bit);
+}
+} // end anonymous namespace
+
+MCAsmBackend *llvm::createWebAssemblyAsmBackend(const Triple &TT) {
+ if (TT.isOSBinFormatELF())
+ return new WebAssemblyAsmBackendELF(TT.isArch64Bit());
+ return new WebAssemblyAsmBackend(TT.isArch64Bit());
+}
diff --git a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyELFObjectWriter.cpp b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyELFObjectWriter.cpp
new file mode 100644
index 000000000000..b67ecfa455b3
--- /dev/null
+++ b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyELFObjectWriter.cpp
@@ -0,0 +1,68 @@
+//===-- WebAssemblyELFObjectWriter.cpp - WebAssembly ELF Writer -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file handles ELF-specific object emission, converting LLVM's
+/// internal fixups into the appropriate relocations.
+///
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCFixup.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace llvm;
+
+namespace {
+class WebAssemblyELFObjectWriter final : public MCELFObjectTargetWriter {
+public:
+ WebAssemblyELFObjectWriter(bool Is64Bit, uint8_t OSABI);
+
+protected:
+ unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
+ const MCFixup &Fixup, bool IsPCRel) const override;
+};
+} // end anonymous namespace
+
+WebAssemblyELFObjectWriter::WebAssemblyELFObjectWriter(bool Is64Bit,
+ uint8_t OSABI)
+ : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_WEBASSEMBLY,
+ /*HasRelocationAddend=*/false) {}
+
+unsigned WebAssemblyELFObjectWriter::getRelocType(MCContext &Ctx,
+ const MCValue &Target,
+ const MCFixup &Fixup,
+ bool IsPCRel) const {
+ // WebAssembly functions are not allocated in the address space. To resolve a
+ // pointer to a function, we must use a special relocation type.
+ if (const MCSymbolRefExpr *SyExp =
+ dyn_cast<MCSymbolRefExpr>(Fixup.getValue()))
+ if (SyExp->getKind() == MCSymbolRefExpr::VK_WebAssembly_FUNCTION)
+ return ELF::R_WEBASSEMBLY_FUNCTION;
+
+ switch (Fixup.getKind()) {
+ case FK_Data_4:
+ assert(!is64Bit() && "4-byte relocations only supported on wasm32");
+ return ELF::R_WEBASSEMBLY_DATA;
+ case FK_Data_8:
+ assert(is64Bit() && "8-byte relocations only supported on wasm64");
+ return ELF::R_WEBASSEMBLY_DATA;
+ default:
+ llvm_unreachable("unimplemented fixup kind");
+ }
+}
+
+std::unique_ptr<MCObjectWriter>
+llvm::createWebAssemblyELFObjectWriter(raw_pwrite_stream &OS,
+ bool Is64Bit,
+ uint8_t OSABI) {
+ auto MOTW = llvm::make_unique<WebAssemblyELFObjectWriter>(Is64Bit, OSABI);
+ return createELFObjectWriter(std::move(MOTW), OS, /*IsLittleEndian=*/true);
+}
diff --git a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyFixupKinds.h b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyFixupKinds.h
new file mode 100644
index 000000000000..b0af63c924bd
--- /dev/null
+++ b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyFixupKinds.h
@@ -0,0 +1,31 @@
+//=- 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.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_WEBASSEMBLY_MCTARGETDESC_WEBASSEMBLYFIXUPKINDS_H
+#define LLVM_LIB_TARGET_WEBASSEMBLY_MCTARGETDESC_WEBASSEMBLYFIXUPKINDS_H
+
+#include "llvm/MC/MCFixup.h"
+
+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_code_global_index, // 32-bit unsigned
+
+ // Marker
+ LastTargetFixupKind,
+ NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
+};
+} // end namespace WebAssembly
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp
new file mode 100644
index 000000000000..5f8c78ed1683
--- /dev/null
+++ b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.cpp
@@ -0,0 +1,83 @@
+//===-- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file contains the declarations of the WebAssemblyMCAsmInfo
+/// properties.
+///
+//===----------------------------------------------------------------------===//
+
+#include "WebAssemblyMCAsmInfo.h"
+#include "llvm/ADT/Triple.h"
+using namespace llvm;
+
+#define DEBUG_TYPE "wasm-mc-asm-info"
+
+WebAssemblyMCAsmInfoELF::~WebAssemblyMCAsmInfoELF() {}
+
+WebAssemblyMCAsmInfoELF::WebAssemblyMCAsmInfoELF(const Triple &T) {
+ CodePointerSize = CalleeSaveStackSlotSize = T.isArch64Bit() ? 8 : 4;
+
+ // TODO: What should MaxInstLength be?
+
+ UseDataRegionDirectives = true;
+
+ // Use .skip instead of .zero because .zero is confusing when used with two
+ // arguments (it doesn't actually zero things out).
+ ZeroDirective = "\t.skip\t";
+
+ Data8bitsDirective = "\t.int8\t";
+ Data16bitsDirective = "\t.int16\t";
+ Data32bitsDirective = "\t.int32\t";
+ Data64bitsDirective = "\t.int64\t";
+
+ AlignmentIsInBytes = false;
+ COMMDirectiveAlignmentIsInBytes = false;
+ LCOMMDirectiveAlignmentType = LCOMM::Log2Alignment;
+
+ SupportsDebugInformation = true;
+
+ // For now, WebAssembly does not support exceptions.
+ ExceptionsType = ExceptionHandling::None;
+
+ // TODO: UseIntegratedAssembler?
+
+ // WebAssembly's stack is never executable.
+ UsesNonexecutableStackSection = false;
+}
+
+WebAssemblyMCAsmInfo::~WebAssemblyMCAsmInfo() {}
+
+WebAssemblyMCAsmInfo::WebAssemblyMCAsmInfo(const Triple &T) {
+ CodePointerSize = CalleeSaveStackSlotSize = T.isArch64Bit() ? 8 : 4;
+
+ // TODO: What should MaxInstLength be?
+
+ UseDataRegionDirectives = true;
+
+ // Use .skip instead of .zero because .zero is confusing when used with two
+ // arguments (it doesn't actually zero things out).
+ ZeroDirective = "\t.skip\t";
+
+ Data8bitsDirective = "\t.int8\t";
+ Data16bitsDirective = "\t.int16\t";
+ Data32bitsDirective = "\t.int32\t";
+ Data64bitsDirective = "\t.int64\t";
+
+ AlignmentIsInBytes = false;
+ COMMDirectiveAlignmentIsInBytes = false;
+ LCOMMDirectiveAlignmentType = LCOMM::Log2Alignment;
+
+ SupportsDebugInformation = true;
+
+ // For now, WebAssembly does not support exceptions.
+ ExceptionsType = ExceptionHandling::None;
+
+ // TODO: UseIntegratedAssembler?
+}
diff --git a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.h b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.h
new file mode 100644
index 000000000000..d9547096190e
--- /dev/null
+++ b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCAsmInfo.h
@@ -0,0 +1,39 @@
+//===-- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file contains the declaration of the WebAssemblyMCAsmInfo class.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_WEBASSEMBLY_MCTARGETDESC_WEBASSEMBLYMCASMINFO_H
+#define LLVM_LIB_TARGET_WEBASSEMBLY_MCTARGETDESC_WEBASSEMBLYMCASMINFO_H
+
+#include "llvm/MC/MCAsmInfoELF.h"
+#include "llvm/MC/MCAsmInfoWasm.h"
+
+namespace llvm {
+
+class Triple;
+
+class WebAssemblyMCAsmInfoELF final : public MCAsmInfoELF {
+public:
+ explicit WebAssemblyMCAsmInfoELF(const Triple &T);
+ ~WebAssemblyMCAsmInfoELF() override;
+};
+
+class WebAssemblyMCAsmInfo final : public MCAsmInfoWasm {
+public:
+ explicit WebAssemblyMCAsmInfo(const Triple &T);
+ ~WebAssemblyMCAsmInfo() override;
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
new file mode 100644
index 000000000000..77744e53d62f
--- /dev/null
+++ b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
@@ -0,0 +1,152 @@
+//=- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file implements the WebAssemblyMCCodeEmitter class.
+///
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/WebAssemblyFixupKinds.h"
+#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCFixup.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/LEB128.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+#define DEBUG_TYPE "mccodeemitter"
+
+STATISTIC(MCNumEmitted, "Number of MC instructions emitted.");
+STATISTIC(MCNumFixups, "Number of MC fixups created.");
+
+namespace {
+class WebAssemblyMCCodeEmitter final : public MCCodeEmitter {
+ const MCInstrInfo &MCII;
+
+ // Implementation generated by tablegen.
+ uint64_t getBinaryCodeForInstr(const MCInst &MI,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
+ void encodeInstruction(const MCInst &MI, raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const override;
+
+public:
+ WebAssemblyMCCodeEmitter(const MCInstrInfo &mcii) : MCII(mcii) {}
+};
+} // end anonymous namespace
+
+MCCodeEmitter *llvm::createWebAssemblyMCCodeEmitter(const MCInstrInfo &MCII) {
+ return new WebAssemblyMCCodeEmitter(MCII);
+}
+
+void WebAssemblyMCCodeEmitter::encodeInstruction(
+ const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ uint64_t Start = OS.tell();
+
+ uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI);
+ if (Binary <= UINT8_MAX) {
+ OS << uint8_t(Binary);
+ } else {
+ assert(Binary <= UINT16_MAX && "Several-byte opcodes not supported yet");
+ OS << uint8_t(Binary >> 8)
+ << uint8_t(Binary);
+ }
+
+ // For br_table instructions, encode the size of the table. In the MCInst,
+ // there's an index operand, one operand for each table entry, and the
+ // default operand.
+ if (MI.getOpcode() == WebAssembly::BR_TABLE_I32 ||
+ MI.getOpcode() == WebAssembly::BR_TABLE_I64)
+ 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);
+ if (MO.isReg()) {
+ /* nothing to encode */
+ } else if (MO.isImm()) {
+ if (i < Desc.getNumOperands()) {
+ assert(Desc.TSFlags == 0 &&
+ "WebAssembly non-variable_ops don't use TSFlags");
+ const MCOperandInfo &Info = Desc.OpInfo[i];
+ if (Info.OperandType == WebAssembly::OPERAND_I32IMM) {
+ encodeSLEB128(int32_t(MO.getImm()), OS);
+ } else if (Info.OperandType == WebAssembly::OPERAND_I64IMM) {
+ encodeSLEB128(int64_t(MO.getImm()), OS);
+ } else if (Info.OperandType == WebAssembly::OPERAND_GLOBAL) {
+ llvm_unreachable("wasm globals should only be accessed symbolicly");
+ } else if (Info.OperandType == WebAssembly::OPERAND_SIGNATURE) {
+ encodeSLEB128(int64_t(MO.getImm()), OS);
+ } else {
+ encodeULEB128(uint64_t(MO.getImm()), OS);
+ }
+ } else {
+ assert(Desc.TSFlags == (WebAssemblyII::VariableOpIsImmediate |
+ WebAssemblyII::VariableOpImmediateIsLabel));
+ encodeULEB128(uint64_t(MO.getImm()), OS);
+ }
+ } else if (MO.isFPImm()) {
+ assert(i < Desc.getNumOperands() &&
+ "Unexpected floating-point immediate as a non-fixed operand");
+ assert(Desc.TSFlags == 0 &&
+ "WebAssembly variable_ops floating point ops don't use TSFlags");
+ 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::Writer<support::little>(OS).write<float>(f);
+ } else {
+ assert(Info.OperandType == WebAssembly::OPERAND_F64IMM);
+ double d = MO.getFPImm();
+ support::endian::Writer<support::little>(OS).write<double>(d);
+ }
+ } else if (MO.isExpr()) {
+ const MCOperandInfo &Info = Desc.OpInfo[i];
+ llvm::MCFixupKind FixupKind;
+ size_t PaddedSize = 5;
+ if (Info.OperandType == WebAssembly::OPERAND_I32IMM) {
+ FixupKind = MCFixupKind(WebAssembly::fixup_code_sleb128_i32);
+ } else if (Info.OperandType == WebAssembly::OPERAND_I64IMM) {
+ FixupKind = MCFixupKind(WebAssembly::fixup_code_sleb128_i64);
+ PaddedSize = 10;
+ } else if (Info.OperandType == WebAssembly::OPERAND_FUNCTION32 ||
+ Info.OperandType == WebAssembly::OPERAND_OFFSET32 ||
+ Info.OperandType == WebAssembly::OPERAND_TYPEINDEX) {
+ FixupKind = MCFixupKind(WebAssembly::fixup_code_uleb128_i32);
+ } else if (Info.OperandType == WebAssembly::OPERAND_GLOBAL) {
+ FixupKind = MCFixupKind(WebAssembly::fixup_code_global_index);
+ } else {
+ llvm_unreachable("unexpected symbolic operand kind");
+ }
+ Fixups.push_back(MCFixup::create(
+ OS.tell() - Start, MO.getExpr(),
+ FixupKind, MI.getLoc()));
+ ++MCNumFixups;
+ encodeULEB128(0, OS, PaddedSize);
+ } else {
+ llvm_unreachable("unexpected operand kind");
+ }
+ }
+
+ ++MCNumEmitted; // Keep track of the # of mi's emitted.
+}
+
+#include "WebAssemblyGenMCCodeEmitter.inc"
diff --git a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp
new file mode 100644
index 000000000000..e7c8809de70e
--- /dev/null
+++ b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp
@@ -0,0 +1,140 @@
+//===-- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file provides WebAssembly-specific target descriptions.
+///
+//===----------------------------------------------------------------------===//
+
+#include "WebAssemblyMCTargetDesc.h"
+#include "InstPrinter/WebAssemblyInstPrinter.h"
+#include "WebAssemblyMCAsmInfo.h"
+#include "WebAssemblyTargetStreamer.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
+using namespace llvm;
+
+#define DEBUG_TYPE "wasm-mc-target-desc"
+
+#define GET_INSTRINFO_MC_DESC
+#include "WebAssemblyGenInstrInfo.inc"
+
+#define GET_SUBTARGETINFO_MC_DESC
+#include "WebAssemblyGenSubtargetInfo.inc"
+
+#define GET_REGINFO_MC_DESC
+#include "WebAssemblyGenRegisterInfo.inc"
+
+static MCAsmInfo *createMCAsmInfo(const MCRegisterInfo & /*MRI*/,
+ const Triple &TT) {
+ if (TT.isOSBinFormatELF())
+ return new WebAssemblyMCAsmInfoELF(TT);
+ return new WebAssemblyMCAsmInfo(TT);
+}
+
+static MCInstrInfo *createMCInstrInfo() {
+ MCInstrInfo *X = new MCInstrInfo();
+ InitWebAssemblyMCInstrInfo(X);
+ return X;
+}
+
+static MCRegisterInfo *createMCRegisterInfo(const Triple & /*T*/) {
+ MCRegisterInfo *X = new MCRegisterInfo();
+ InitWebAssemblyMCRegisterInfo(X, 0);
+ return X;
+}
+
+static MCInstPrinter *createMCInstPrinter(const Triple & /*T*/,
+ unsigned SyntaxVariant,
+ const MCAsmInfo &MAI,
+ const MCInstrInfo &MII,
+ const MCRegisterInfo &MRI) {
+ assert(SyntaxVariant == 0 && "WebAssembly only has one syntax variant");
+ return new WebAssemblyInstPrinter(MAI, MII, MRI);
+}
+
+static MCCodeEmitter *createCodeEmitter(const MCInstrInfo &MCII,
+ const MCRegisterInfo & /*MRI*/,
+ MCContext &Ctx) {
+ return createWebAssemblyMCCodeEmitter(MCII);
+}
+
+static MCAsmBackend *createAsmBackend(const Target & /*T*/,
+ const MCSubtargetInfo &STI,
+ const MCRegisterInfo & /*MRI*/,
+ const MCTargetOptions & /*Options*/) {
+ return createWebAssemblyAsmBackend(STI.getTargetTriple());
+}
+
+static MCSubtargetInfo *createMCSubtargetInfo(const Triple &TT, StringRef CPU,
+ StringRef FS) {
+ return createWebAssemblyMCSubtargetInfoImpl(TT, CPU, FS);
+}
+
+static MCTargetStreamer *
+createObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
+ const Triple &TT = STI.getTargetTriple();
+ if (TT.isOSBinFormatELF())
+ return new WebAssemblyTargetELFStreamer(S);
+
+ return new WebAssemblyTargetWasmStreamer(S);
+}
+
+static MCTargetStreamer *createAsmTargetStreamer(MCStreamer &S,
+ formatted_raw_ostream &OS,
+ MCInstPrinter * /*InstPrint*/,
+ bool /*isVerboseAsm*/) {
+ return new WebAssemblyTargetAsmStreamer(S, OS);
+}
+
+// Force static initialization.
+extern "C" void LLVMInitializeWebAssemblyTargetMC() {
+ for (Target *T :
+ {&getTheWebAssemblyTarget32(), &getTheWebAssemblyTarget64()}) {
+ // Register the MC asm info.
+ RegisterMCAsmInfoFn X(*T, createMCAsmInfo);
+
+ // Register the MC instruction info.
+ TargetRegistry::RegisterMCInstrInfo(*T, createMCInstrInfo);
+
+ // Register the MC register info.
+ TargetRegistry::RegisterMCRegInfo(*T, createMCRegisterInfo);
+
+ // Register the MCInstPrinter.
+ TargetRegistry::RegisterMCInstPrinter(*T, createMCInstPrinter);
+
+ // Register the MC code emitter.
+ TargetRegistry::RegisterMCCodeEmitter(*T, createCodeEmitter);
+
+ // Register the ASM Backend.
+ TargetRegistry::RegisterMCAsmBackend(*T, createAsmBackend);
+
+ // Register the MC subtarget info.
+ TargetRegistry::RegisterMCSubtargetInfo(*T, createMCSubtargetInfo);
+
+ // Register the object target streamer.
+ TargetRegistry::RegisterObjectTargetStreamer(*T,
+ createObjectTargetStreamer);
+ // Register the asm target streamer.
+ TargetRegistry::RegisterAsmTargetStreamer(*T, createAsmTargetStreamer);
+ }
+}
+
+wasm::ValType WebAssembly::toValType(const MVT &Ty) {
+ switch (Ty.SimpleTy) {
+ case MVT::i32: return wasm::ValType::I32;
+ case MVT::i64: return wasm::ValType::I64;
+ case MVT::f32: return wasm::ValType::F32;
+ case MVT::f64: return wasm::ValType::F64;
+ default: llvm_unreachable("unexpected type");
+ }
+}
diff --git a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
new file mode 100644
index 000000000000..7dca89ab822d
--- /dev/null
+++ b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
@@ -0,0 +1,185 @@
+//==- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file provides WebAssembly-specific target descriptions.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_WEBASSEMBLY_MCTARGETDESC_WEBASSEMBLYMCTARGETDESC_H
+#define LLVM_LIB_TARGET_WEBASSEMBLY_MCTARGETDESC_WEBASSEMBLYMCTARGETDESC_H
+
+#include "llvm/BinaryFormat/Wasm.h"
+#include "llvm/MC/MCInstrDesc.h"
+#include "llvm/Support/DataTypes.h"
+#include <memory>
+
+namespace llvm {
+
+class MCAsmBackend;
+class MCCodeEmitter;
+class MCContext;
+class MCInstrInfo;
+class MCObjectWriter;
+class MCSubtargetInfo;
+class MVT;
+class Target;
+class Triple;
+class raw_pwrite_stream;
+
+Target &getTheWebAssemblyTarget32();
+Target &getTheWebAssemblyTarget64();
+
+MCCodeEmitter *createWebAssemblyMCCodeEmitter(const MCInstrInfo &MCII);
+
+MCAsmBackend *createWebAssemblyAsmBackend(const Triple &TT);
+
+std::unique_ptr<MCObjectWriter>
+createWebAssemblyELFObjectWriter(raw_pwrite_stream &OS,
+ bool Is64Bit, uint8_t OSABI);
+
+std::unique_ptr<MCObjectWriter>
+createWebAssemblyWasmObjectWriter(raw_pwrite_stream &OS,
+ bool Is64Bit);
+
+namespace WebAssembly {
+enum OperandType {
+ /// Basic block label in a branch construct.
+ OPERAND_BASIC_BLOCK = MCOI::OPERAND_FIRST_TARGET,
+ /// Local index.
+ OPERAND_LOCAL,
+ /// Global index.
+ OPERAND_GLOBAL,
+ /// 32-bit integer immediates.
+ OPERAND_I32IMM,
+ /// 64-bit integer immediates.
+ OPERAND_I64IMM,
+ /// 32-bit floating-point immediates.
+ OPERAND_F32IMM,
+ /// 64-bit floating-point immediates.
+ OPERAND_F64IMM,
+ /// 32-bit unsigned function indices.
+ OPERAND_FUNCTION32,
+ /// 32-bit unsigned memory offsets.
+ OPERAND_OFFSET32,
+ /// p2align immediate for load and store address alignment.
+ OPERAND_P2ALIGN,
+ /// signature immediate for block/loop.
+ OPERAND_SIGNATURE,
+ /// type signature immediate for call_indirect.
+ OPERAND_TYPEINDEX,
+};
+} // end namespace WebAssembly
+
+namespace WebAssemblyII {
+enum {
+ // For variadic instructions, this flag indicates whether an operand
+ // in the variable_ops range is an immediate value.
+ VariableOpIsImmediate = (1 << 0),
+ // For immediate values in the variable_ops range, this flag indicates
+ // whether the value represents a control-flow label.
+ VariableOpImmediateIsLabel = (1 << 1)
+};
+} // end namespace WebAssemblyII
+
+} // end namespace llvm
+
+// Defines symbolic names for WebAssembly registers. This defines a mapping from
+// register name to register number.
+//
+#define GET_REGINFO_ENUM
+#include "WebAssemblyGenRegisterInfo.inc"
+
+// Defines symbolic names for the WebAssembly instructions.
+//
+#define GET_INSTRINFO_ENUM
+#include "WebAssemblyGenInstrInfo.inc"
+
+#define GET_SUBTARGETINFO_ENUM
+#include "WebAssemblyGenSubtargetInfo.inc"
+
+namespace llvm {
+namespace WebAssembly {
+
+/// Return the default p2align value for a load or store with the given opcode.
+inline unsigned GetDefaultP2Align(unsigned Opcode) {
+ switch (Opcode) {
+ case WebAssembly::LOAD8_S_I32:
+ case WebAssembly::LOAD8_U_I32:
+ case WebAssembly::LOAD8_S_I64:
+ case WebAssembly::LOAD8_U_I64:
+ case WebAssembly::ATOMIC_LOAD8_U_I32:
+ case WebAssembly::ATOMIC_LOAD8_U_I64:
+ case WebAssembly::STORE8_I32:
+ case WebAssembly::STORE8_I64:
+ return 0;
+ case WebAssembly::LOAD16_S_I32:
+ case WebAssembly::LOAD16_U_I32:
+ case WebAssembly::LOAD16_S_I64:
+ case WebAssembly::LOAD16_U_I64:
+ case WebAssembly::ATOMIC_LOAD16_U_I32:
+ case WebAssembly::ATOMIC_LOAD16_U_I64:
+ case WebAssembly::STORE16_I32:
+ case WebAssembly::STORE16_I64:
+ return 1;
+ case WebAssembly::LOAD_I32:
+ case WebAssembly::LOAD_F32:
+ case WebAssembly::STORE_I32:
+ case WebAssembly::STORE_F32:
+ case WebAssembly::LOAD32_S_I64:
+ case WebAssembly::LOAD32_U_I64:
+ case WebAssembly::STORE32_I64:
+ case WebAssembly::ATOMIC_LOAD_I32:
+ case WebAssembly::ATOMIC_LOAD32_U_I64:
+ return 2;
+ case WebAssembly::LOAD_I64:
+ case WebAssembly::LOAD_F64:
+ case WebAssembly::STORE_I64:
+ case WebAssembly::STORE_F64:
+ case WebAssembly::ATOMIC_LOAD_I64:
+ return 3;
+ default:
+ llvm_unreachable("Only loads and stores have p2align values");
+ }
+}
+
+/// The operand number of the load or store address in load/store instructions.
+static const unsigned LoadAddressOperandNo = 3;
+static const unsigned StoreAddressOperandNo = 2;
+
+/// The operand number of the load or store p2align in load/store instructions.
+static const unsigned LoadP2AlignOperandNo = 1;
+static const unsigned StoreP2AlignOperandNo = 0;
+
+/// This is used to indicate block signatures.
+enum class ExprType {
+ Void = -0x40,
+ I32 = -0x01,
+ I64 = -0x02,
+ F32 = -0x03,
+ F64 = -0x04,
+ I8x16 = -0x05,
+ I16x8 = -0x06,
+ I32x4 = -0x07,
+ F32x4 = -0x08,
+ B8x16 = -0x09,
+ B16x8 = -0x0a,
+ B32x4 = -0x0b
+};
+
+/// Instruction opcodes emitted via means other than CodeGen.
+static const unsigned Nop = 0x01;
+static const unsigned End = 0x0b;
+
+wasm::ValType toValType(const MVT &Ty);
+
+} // end namespace WebAssembly
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp
new file mode 100644
index 000000000000..0ca52ad651b5
--- /dev/null
+++ b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp
@@ -0,0 +1,264 @@
+//==-- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file defines WebAssembly-specific target streamer classes.
+/// These are for implementing support for target-specific assembly directives.
+///
+//===----------------------------------------------------------------------===//
+
+#include "WebAssemblyTargetStreamer.h"
+#include "InstPrinter/WebAssemblyInstPrinter.h"
+#include "WebAssemblyMCTargetDesc.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCSectionWasm.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbolELF.h"
+#include "llvm/MC/MCSymbolWasm.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
+using namespace llvm;
+
+WebAssemblyTargetStreamer::WebAssemblyTargetStreamer(MCStreamer &S)
+ : MCTargetStreamer(S) {}
+
+void WebAssemblyTargetStreamer::emitValueType(wasm::ValType Type) {
+ Streamer.EmitSLEB128IntValue(int32_t(Type));
+}
+
+WebAssemblyTargetAsmStreamer::WebAssemblyTargetAsmStreamer(
+ MCStreamer &S, formatted_raw_ostream &OS)
+ : WebAssemblyTargetStreamer(S), OS(OS) {}
+
+WebAssemblyTargetELFStreamer::WebAssemblyTargetELFStreamer(MCStreamer &S)
+ : WebAssemblyTargetStreamer(S) {}
+
+WebAssemblyTargetWasmStreamer::WebAssemblyTargetWasmStreamer(MCStreamer &S)
+ : WebAssemblyTargetStreamer(S) {}
+
+static void PrintTypes(formatted_raw_ostream &OS, ArrayRef<MVT> Types) {
+ bool First = true;
+ for (MVT Type : Types) {
+ if (First)
+ First = false;
+ else
+ OS << ", ";
+ OS << WebAssembly::TypeToString(Type);
+ }
+ OS << '\n';
+}
+
+void WebAssemblyTargetAsmStreamer::emitParam(MCSymbol *Symbol,
+ ArrayRef<MVT> Types) {
+ if (!Types.empty()) {
+ OS << "\t.param \t";
+
+ // FIXME: Currently this applies to the "current" function; it may
+ // be cleaner to specify an explicit symbol as part of the directive.
+
+ PrintTypes(OS, Types);
+ }
+}
+
+void WebAssemblyTargetAsmStreamer::emitResult(MCSymbol *Symbol,
+ ArrayRef<MVT> Types) {
+ if (!Types.empty()) {
+ OS << "\t.result \t";
+
+ // FIXME: Currently this applies to the "current" function; it may
+ // be cleaner to specify an explicit symbol as part of the directive.
+
+ PrintTypes(OS, Types);
+ }
+}
+
+void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<MVT> Types) {
+ if (!Types.empty()) {
+ OS << "\t.local \t";
+ PrintTypes(OS, Types);
+ }
+}
+
+void WebAssemblyTargetAsmStreamer::emitGlobal(
+ ArrayRef<wasm::Global> Globals) {
+ if (!Globals.empty()) {
+ OS << "\t.globalvar \t";
+
+ bool First = true;
+ for (const wasm::Global &G : Globals) {
+ if (First)
+ First = false;
+ else
+ OS << ", ";
+ OS << WebAssembly::TypeToString(G.Type);
+ if (!G.InitialModule.empty())
+ OS << '=' << G.InitialModule << ':' << G.InitialName;
+ else
+ OS << '=' << G.InitialValue;
+ }
+ OS << '\n';
+ }
+}
+
+void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; }
+
+void WebAssemblyTargetAsmStreamer::emitIndirectFunctionType(
+ MCSymbol *Symbol, SmallVectorImpl<MVT> &Params, SmallVectorImpl<MVT> &Results) {
+ OS << "\t.functype\t" << Symbol->getName();
+ if (Results.empty())
+ OS << ", void";
+ else {
+ assert(Results.size() == 1);
+ OS << ", " << WebAssembly::TypeToString(Results.front());
+ }
+ for (auto Ty : Params)
+ OS << ", " << WebAssembly::TypeToString(Ty);
+ OS << '\n';
+}
+
+void WebAssemblyTargetAsmStreamer::emitGlobalImport(StringRef name) {
+ OS << "\t.import_global\t" << name << '\n';
+}
+
+void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) {
+ OS << "\t.indidx \t" << *Value << '\n';
+}
+
+void WebAssemblyTargetELFStreamer::emitParam(MCSymbol *Symbol,
+ ArrayRef<MVT> Types) {
+ // Nothing to emit; params are declared as part of the function signature.
+}
+
+void WebAssemblyTargetELFStreamer::emitResult(MCSymbol *Symbol,
+ ArrayRef<MVT> Types) {
+ // Nothing to emit; results are declared as part of the function signature.
+}
+
+void WebAssemblyTargetELFStreamer::emitLocal(ArrayRef<MVT> Types) {
+ Streamer.EmitULEB128IntValue(Types.size());
+ for (MVT Type : Types)
+ emitValueType(WebAssembly::toValType(Type));
+}
+
+void WebAssemblyTargetELFStreamer::emitGlobal(
+ ArrayRef<wasm::Global> Globals) {
+ llvm_unreachable(".globalvar encoding not yet implemented");
+}
+
+void WebAssemblyTargetELFStreamer::emitEndFunc() {
+ Streamer.EmitIntValue(WebAssembly::End, 1);
+}
+
+void WebAssemblyTargetELFStreamer::emitIndIdx(const MCExpr *Value) {
+ llvm_unreachable(".indidx encoding not yet implemented");
+}
+
+void WebAssemblyTargetELFStreamer::emitIndirectFunctionType(
+ MCSymbol *Symbol, SmallVectorImpl<MVT> &Params, SmallVectorImpl<MVT> &Results) {
+ // Nothing to emit here. TODO: Re-design how linking works and re-evaluate
+ // whether it's necessary for .o files to declare indirect function types.
+}
+
+void WebAssemblyTargetELFStreamer::emitGlobalImport(StringRef name) {
+}
+
+void WebAssemblyTargetWasmStreamer::emitParam(MCSymbol *Symbol,
+ ArrayRef<MVT> Types) {
+ SmallVector<wasm::ValType, 4> Params;
+ for (MVT Ty : Types)
+ Params.push_back(WebAssembly::toValType(Ty));
+
+ cast<MCSymbolWasm>(Symbol)->setParams(std::move(Params));
+}
+
+void WebAssemblyTargetWasmStreamer::emitResult(MCSymbol *Symbol,
+ ArrayRef<MVT> Types) {
+ SmallVector<wasm::ValType, 4> Returns;
+ for (MVT Ty : Types)
+ Returns.push_back(WebAssembly::toValType(Ty));
+
+ cast<MCSymbolWasm>(Symbol)->setReturns(std::move(Returns));
+}
+
+void WebAssemblyTargetWasmStreamer::emitLocal(ArrayRef<MVT> Types) {
+ SmallVector<std::pair<MVT, uint32_t>, 4> Grouped;
+ for (MVT Type : Types) {
+ if (Grouped.empty() || Grouped.back().first != Type)
+ Grouped.push_back(std::make_pair(Type, 1));
+ else
+ ++Grouped.back().second;
+ }
+
+ Streamer.EmitULEB128IntValue(Grouped.size());
+ for (auto Pair : Grouped) {
+ Streamer.EmitULEB128IntValue(Pair.second);
+ emitValueType(WebAssembly::toValType(Pair.first));
+ }
+}
+
+void WebAssemblyTargetWasmStreamer::emitGlobal(
+ ArrayRef<wasm::Global> Globals) {
+ // Encode the globals use by the funciton into the special .global_variables
+ // section. This will later be decoded and turned into contents for the
+ // Globals Section.
+ Streamer.PushSection();
+ Streamer.SwitchSection(Streamer.getContext().getWasmSection(
+ ".global_variables", SectionKind::getMetadata()));
+ for (const wasm::Global &G : Globals) {
+ Streamer.EmitIntValue(int32_t(G.Type), 1);
+ Streamer.EmitIntValue(G.Mutable, 1);
+ if (G.InitialModule.empty()) {
+ Streamer.EmitIntValue(0, 1); // indicate that we have an int value
+ Streamer.EmitSLEB128IntValue(0);
+ } else {
+ Streamer.EmitIntValue(1, 1); // indicate that we have a module import
+ Streamer.EmitBytes(G.InitialModule);
+ Streamer.EmitIntValue(0, 1); // nul-terminate
+ Streamer.EmitBytes(G.InitialName);
+ Streamer.EmitIntValue(0, 1); // nul-terminate
+ }
+ }
+ Streamer.PopSection();
+}
+
+void WebAssemblyTargetWasmStreamer::emitEndFunc() {
+ llvm_unreachable(".end_func is not needed for direct wasm output");
+}
+
+void WebAssemblyTargetWasmStreamer::emitIndIdx(const MCExpr *Value) {
+ llvm_unreachable(".indidx encoding not yet implemented");
+}
+
+void WebAssemblyTargetWasmStreamer::emitIndirectFunctionType(
+ MCSymbol *Symbol, SmallVectorImpl<MVT> &Params,
+ SmallVectorImpl<MVT> &Results) {
+ MCSymbolWasm *WasmSym = cast<MCSymbolWasm>(Symbol);
+ if (WasmSym->isFunction()) {
+ // Symbol already has its arguments and result set.
+ return;
+ }
+
+ SmallVector<wasm::ValType, 4> ValParams;
+ for (MVT Ty : Params)
+ ValParams.push_back(WebAssembly::toValType(Ty));
+
+ SmallVector<wasm::ValType, 1> ValResults;
+ for (MVT Ty : Results)
+ ValResults.push_back(WebAssembly::toValType(Ty));
+
+ WasmSym->setParams(std::move(ValParams));
+ WasmSym->setReturns(std::move(ValResults));
+ WasmSym->setIsFunction(true);
+}
+
+void WebAssemblyTargetWasmStreamer::emitGlobalImport(StringRef name) {
+ llvm_unreachable(".global_import is not needed for direct wasm output");
+}
diff --git a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h
new file mode 100644
index 000000000000..2cb21a20580b
--- /dev/null
+++ b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h
@@ -0,0 +1,112 @@
+//==-- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file declares WebAssembly-specific target streamer classes.
+/// These are for implementing support for target-specific assembly directives.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_WEBASSEMBLY_MCTARGETDESC_WEBASSEMBLYTARGETSTREAMER_H
+#define LLVM_LIB_TARGET_WEBASSEMBLY_MCTARGETDESC_WEBASSEMBLYTARGETSTREAMER_H
+
+#include "llvm/BinaryFormat/Wasm.h"
+#include "llvm/CodeGen/MachineValueType.h"
+#include "llvm/MC/MCStreamer.h"
+
+namespace llvm {
+
+class MCELFStreamer;
+class MCWasmStreamer;
+
+/// WebAssembly-specific streamer interface, to implement support
+/// WebAssembly-specific assembly directives.
+class WebAssemblyTargetStreamer : public MCTargetStreamer {
+public:
+ explicit WebAssemblyTargetStreamer(MCStreamer &S);
+
+ /// .param
+ virtual void emitParam(MCSymbol *Symbol, ArrayRef<MVT> Types) = 0;
+ /// .result
+ virtual void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) = 0;
+ /// .local
+ virtual void emitLocal(ArrayRef<MVT> Types) = 0;
+ /// .globalvar
+ virtual void emitGlobal(ArrayRef<wasm::Global> Globals) = 0;
+ /// .endfunc
+ virtual void emitEndFunc() = 0;
+ /// .functype
+ virtual void emitIndirectFunctionType(MCSymbol *Symbol,
+ SmallVectorImpl<MVT> &Params,
+ SmallVectorImpl<MVT> &Results) = 0;
+ /// .indidx
+ virtual void emitIndIdx(const MCExpr *Value) = 0;
+ /// .import_global
+ virtual void emitGlobalImport(StringRef name) = 0;
+
+protected:
+ void emitValueType(wasm::ValType Type);
+};
+
+/// This part is for ascii assembly output
+class WebAssemblyTargetAsmStreamer final : public WebAssemblyTargetStreamer {
+ formatted_raw_ostream &OS;
+
+public:
+ WebAssemblyTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
+
+ void emitParam(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
+ void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
+ void emitLocal(ArrayRef<MVT> Types) override;
+ void emitGlobal(ArrayRef<wasm::Global> Globals) override;
+ void emitEndFunc() override;
+ void emitIndirectFunctionType(MCSymbol *Symbol,
+ SmallVectorImpl<MVT> &Params,
+ SmallVectorImpl<MVT> &Results) override;
+ void emitIndIdx(const MCExpr *Value) override;
+ void emitGlobalImport(StringRef name) override;
+};
+
+/// This part is for ELF object output
+class WebAssemblyTargetELFStreamer final : public WebAssemblyTargetStreamer {
+public:
+ explicit WebAssemblyTargetELFStreamer(MCStreamer &S);
+
+ void emitParam(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
+ void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
+ void emitLocal(ArrayRef<MVT> Types) override;
+ void emitGlobal(ArrayRef<wasm::Global> Globals) override;
+ void emitEndFunc() override;
+ void emitIndirectFunctionType(MCSymbol *Symbol,
+ SmallVectorImpl<MVT> &Params,
+ SmallVectorImpl<MVT> &Results) override;
+ void emitIndIdx(const MCExpr *Value) override;
+ void emitGlobalImport(StringRef name) override;
+};
+
+/// This part is for Wasm object output
+class WebAssemblyTargetWasmStreamer final : public WebAssemblyTargetStreamer {
+public:
+ explicit WebAssemblyTargetWasmStreamer(MCStreamer &S);
+
+ void emitParam(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
+ void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
+ void emitLocal(ArrayRef<MVT> Types) override;
+ void emitGlobal(ArrayRef<wasm::Global> Globals) override;
+ void emitEndFunc() override;
+ void emitIndirectFunctionType(MCSymbol *Symbol,
+ SmallVectorImpl<MVT> &Params,
+ SmallVectorImpl<MVT> &Results) override;
+ void emitIndIdx(const MCExpr *Value) override;
+ void emitGlobalImport(StringRef name) override;
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
new file mode 100644
index 000000000000..39abde26df7f
--- /dev/null
+++ b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
@@ -0,0 +1,102 @@
+//===-- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file handles Wasm-specific object emission, converting LLVM's
+/// internal fixups into the appropriate relocations.
+///
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/WebAssemblyFixupKinds.h"
+#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
+#include "llvm/BinaryFormat/Wasm.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCFixup.h"
+#include "llvm/MC/MCFixupKindInfo.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSymbolWasm.h"
+#include "llvm/MC/MCWasmObjectWriter.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+
+namespace {
+class WebAssemblyWasmObjectWriter final : public MCWasmObjectTargetWriter {
+public:
+ explicit WebAssemblyWasmObjectWriter(bool Is64Bit);
+
+private:
+ unsigned getRelocType(const MCValue &Target,
+ const MCFixup &Fixup) const override;
+};
+} // end anonymous namespace
+
+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;
+}
+
+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());
+
+ switch (unsigned(Fixup.getKind())) {
+ case WebAssembly::fixup_code_global_index:
+ return wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB;
+ 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:
+ llvm_unreachable("fixup_sleb128_i64 not implemented yet");
+ case WebAssembly::fixup_code_uleb128_i32:
+ if (IsFunctionType(Target))
+ return wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB;
+ if (IsFunction)
+ return wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB;
+ return wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB;
+ case FK_Data_4:
+ if (IsFunction)
+ return wasm::R_WEBASSEMBLY_TABLE_INDEX_I32;
+ return wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32;
+ case FK_Data_8:
+ llvm_unreachable("FK_Data_8 not implemented yet");
+ default:
+ llvm_unreachable("unimplemented fixup kind");
+ }
+}
+
+std::unique_ptr<MCObjectWriter>
+llvm::createWebAssemblyWasmObjectWriter(raw_pwrite_stream &OS,
+ bool Is64Bit) {
+ auto MOTW = llvm::make_unique<WebAssemblyWasmObjectWriter>(Is64Bit);
+ return createWasmObjectWriter(std::move(MOTW), OS);
+}