Imported Upstream version 5.18.0.167

Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-10-20 08:25:10 +00:00
parent e19d552987
commit b084638f15
28489 changed files with 184 additions and 3866856 deletions

View File

@ -1,9 +0,0 @@
add_llvm_library(LLVMWebAssemblyDesc
WebAssemblyAsmBackend.cpp
WebAssemblyELFObjectWriter.cpp
WebAssemblyMCAsmInfo.cpp
WebAssemblyMCCodeEmitter.cpp
WebAssemblyMCTargetDesc.cpp
WebAssemblyTargetStreamer.cpp
WebAssemblyWasmObjectWriter.cpp
)

View File

@ -1,23 +0,0 @@
;===- ./lib/Target/WebAssembly/MCTargetDesc/LLVMBuild.txt ------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
; This file is distributed under the University of Illinois Open Source
; License. See LICENSE.TXT for details.
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;
[component_0]
type = Library
name = WebAssemblyDesc
parent = WebAssembly
required_libraries = MC Support WebAssemblyAsmPrinter WebAssemblyInfo
add_to_library_groups = WebAssembly

View File

@ -1,206 +0,0 @@
//===-- 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());
}

View File

@ -1,68 +0,0 @@
//===-- 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);
}

View File

@ -1,31 +0,0 @@
//=- 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

View File

@ -1,83 +0,0 @@
//===-- 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?
}

View File

@ -1,39 +0,0 @@
//===-- 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

View File

@ -1,152 +0,0 @@
//=- 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"

View File

@ -1,140 +0,0 @@
//===-- 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");
}
}

View File

@ -1,185 +0,0 @@
//==- 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

View File

@ -1,264 +0,0 @@
//==-- 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");
}

View File

@ -1,112 +0,0 @@
//==-- 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

View File

@ -1,102 +0,0 @@
//===-- 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);
}