diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 21:25:48 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 21:25:48 +0000 |
commit | d88c1a5a572cdb661c111098831fa526e933756f (patch) | |
tree | 97b32c3372106ac47ded3d1a99f9c023a8530073 /contrib/llvm/lib/Target/WebAssembly/MCTargetDesc | |
parent | 715652a404ee99f10c09c0a5edbb5883961b8c25 (diff) | |
parent | b915e9e0fc85ba6f398b3fab0db6a81a8913af94 (diff) | |
download | src-d88c1a5a572cdb661c111098831fa526e933756f.tar.gz src-d88c1a5a572cdb661c111098831fa526e933756f.zip |
Update llvm to trunk r290819 and resolve conflicts.
Notes
Notes:
svn path=/projects/clang400-import/; revision=311142
Diffstat (limited to 'contrib/llvm/lib/Target/WebAssembly/MCTargetDesc')
6 files changed, 178 insertions, 61 deletions
diff --git a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp index df6fb8968d56..97454a824a34 100644 --- a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp +++ b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp @@ -66,8 +66,10 @@ bool WebAssemblyAsmBackend::writeNopData(uint64_t Count, if (Count == 0) return true; - // FIXME: Do something. - return false; + for (uint64_t i = 0; i < Count; ++i) + OW->write8(WebAssembly::Nop); + + return true; } void WebAssemblyAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, diff --git a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp index 23f8b3d0e827..d0e0eecd3002 100644 --- a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp +++ b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp @@ -23,6 +23,7 @@ #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; @@ -45,7 +46,7 @@ class WebAssemblyMCCodeEmitter final : public MCCodeEmitter { const MCSubtargetInfo &STI) const override; public: - WebAssemblyMCCodeEmitter(const MCInstrInfo &mcii) : MCII(mcii) {} + explicit WebAssemblyMCCodeEmitter(const MCInstrInfo &mcii) : MCII(mcii) {} }; } // end anonymous namespace @@ -56,30 +57,59 @@ MCCodeEmitter *llvm::createWebAssemblyMCCodeEmitter(const MCInstrInfo &MCII) { void WebAssemblyMCCodeEmitter::encodeInstruction( const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { - // FIXME: This is not the real binary encoding. This is an extremely - // over-simplified encoding where we just use uint64_t for everything. This - // is a temporary measure. - support::endian::Writer<support::little>(OS).write<uint64_t>(MI.getOpcode()); + uint64_t Start = OS.tell(); + + uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI); + assert(Binary < UINT8_MAX && "Multi-byte opcodes not supported yet"); + OS << uint8_t(Binary); + const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); - if (Desc.isVariadic()) - support::endian::Writer<support::little>(OS).write<uint64_t>( - MI.getNumOperands() - Desc.NumOperands); for (unsigned i = 0, e = MI.getNumOperands(); i < e; ++i) { const MCOperand &MO = MI.getOperand(i); if (MO.isReg()) { - support::endian::Writer<support::little>(OS).write<uint64_t>(MO.getReg()); + /* nothing to encode */ } else if (MO.isImm()) { - support::endian::Writer<support::little>(OS).write<uint64_t>(MO.getImm()); + 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 { + encodeULEB128(uint64_t(MO.getImm()), OS); + } + } else { + assert(Desc.TSFlags == (WebAssemblyII::VariableOpIsImmediate | + WebAssemblyII::VariableOpImmediateIsLabel)); + encodeULEB128(uint64_t(MO.getImm()), OS); + } } else if (MO.isFPImm()) { - support::endian::Writer<support::little>(OS).write<double>(MO.getFPImm()); + 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()) { - support::endian::Writer<support::little>(OS).write<uint64_t>(0); Fixups.push_back(MCFixup::create( - (1 + MCII.get(MI.getOpcode()).isVariadic() + i) * sizeof(uint64_t), - MO.getExpr(), + OS.tell() - Start, MO.getExpr(), STI.getTargetTriple().isArch64Bit() ? FK_Data_8 : FK_Data_4, MI.getLoc())); ++MCNumFixups; + encodeULEB128(STI.getTargetTriple().isArch64Bit() ? UINT64_MAX + : uint64_t(UINT32_MAX), + OS); } else { llvm_unreachable("unexpected operand kind"); } diff --git a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp index ac11a64086f2..3dc1ded17116 100644 --- a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp +++ b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp @@ -77,7 +77,8 @@ static MCCodeEmitter *createCodeEmitter(const MCInstrInfo &MCII, static MCAsmBackend *createAsmBackend(const Target & /*T*/, const MCRegisterInfo & /*MRI*/, - const Triple &TT, StringRef /*CPU*/) { + const Triple &TT, StringRef /*CPU*/, + const MCTargetOptions & /*Options*/) { return createWebAssemblyAsmBackend(TT); } @@ -100,7 +101,8 @@ static MCTargetStreamer *createAsmTargetStreamer(MCStreamer &S, // Force static initialization. extern "C" void LLVMInitializeWebAssemblyTargetMC() { - for (Target *T : {&TheWebAssemblyTarget32, &TheWebAssemblyTarget64}) { + for (Target *T : + {&getTheWebAssemblyTarget32(), &getTheWebAssemblyTarget64()}) { // Register the MC asm info. RegisterMCAsmInfoFn X(*T, createMCAsmInfo); @@ -132,3 +134,13 @@ extern "C" void LLVMInitializeWebAssemblyTargetMC() { TargetRegistry::RegisterAsmTargetStreamer(*T, createAsmTargetStreamer); } } + +WebAssembly::ValType WebAssembly::toValType(const MVT &Ty) { + switch (Ty.SimpleTy) { + case MVT::i32: return WebAssembly::ValType::I32; + case MVT::i64: return WebAssembly::ValType::I64; + case MVT::f32: return WebAssembly::ValType::F32; + case MVT::f64: return WebAssembly::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 index 001bd7f1fc43..8583b772deab 100644 --- a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -26,12 +26,13 @@ class MCContext; class MCInstrInfo; class MCObjectWriter; class MCSubtargetInfo; +class MVT; class Target; class Triple; class raw_pwrite_stream; -extern Target TheWebAssemblyTarget32; -extern Target TheWebAssemblyTarget64; +Target &getTheWebAssemblyTarget32(); +Target &getTheWebAssemblyTarget64(); MCCodeEmitter *createWebAssemblyMCCodeEmitter(const MCInstrInfo &MCII); @@ -44,23 +45,25 @@ namespace WebAssembly { enum OperandType { /// Basic block label in a branch construct. OPERAND_BASIC_BLOCK = MCOI::OPERAND_FIRST_TARGET, + /// Local index. + OPERAND_LOCAL, + /// 32-bit integer immediates. + OPERAND_I32IMM, + /// 64-bit integer immediates. + OPERAND_I64IMM, /// 32-bit floating-point immediates. - OPERAND_FP32IMM, + OPERAND_F32IMM, /// 64-bit floating-point immediates. - OPERAND_FP64IMM, + 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 + OPERAND_P2ALIGN, + /// signature immediate for block/loop. + OPERAND_SIGNATURE }; - -/// WebAssembly-specific directive identifiers. -enum Directive { - // FIXME: This is not the real binary encoding. - DotParam = UINT64_MAX - 0, ///< .param - DotResult = UINT64_MAX - 1, ///< .result - DotLocal = UINT64_MAX - 2, ///< .local - DotEndFunc = UINT64_MAX - 3, ///< .endfunc -}; - } // end namespace WebAssembly namespace WebAssemblyII { @@ -70,7 +73,7 @@ enum { 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), + VariableOpImmediateIsLabel = (1 << 1) }; } // end namespace WebAssemblyII @@ -123,14 +126,55 @@ inline unsigned GetDefaultP2Align(unsigned Opcode) { case WebAssembly::STORE_I64: case WebAssembly::STORE_F64: return 3; - default: llvm_unreachable("Only loads and stores have p2align values"); + 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 MemOpAddressOperandNo = 2; -/// The operand number of the stored value in a store instruction. -static const unsigned StoreValueOperandNo = 4; +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 = 0x7f, + I64 = 0x7e, + F32 = 0x7d, + F64 = 0x7c, + I8x16 = 0x7b, + I16x8 = 0x7a, + I32x4 = 0x79, + F32x4 = 0x78, + B8x16 = 0x77, + B16x8 = 0x76, + B32x4 = 0x75 +}; + +/// This is used to indicate local types. +enum class ValType { + I32 = 0x7f, + I64 = 0x7e, + F32 = 0x7d, + F64 = 0x7c, + I8x16 = 0x7b, + I16x8 = 0x7a, + I32x4 = 0x79, + F32x4 = 0x78, + B8x16 = 0x77, + B16x8 = 0x76, + B32x4 = 0x75 +}; + +/// Instruction opcodes emitted via means other than CodeGen. +static const unsigned Nop = 0x01; +static const unsigned End = 0x0b; + +ValType toValType(const MVT &Ty); } // end namespace WebAssembly } // end namespace llvm diff --git a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp index 3d61c15717b4..3cee8b2a1844 100644 --- a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp +++ b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp @@ -58,45 +58,63 @@ void WebAssemblyTargetAsmStreamer::emitResult(ArrayRef<MVT> Types) { } void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<MVT> Types) { - OS << "\t.local \t"; - PrintTypes(OS, Types); + if (!Types.empty()) { + OS << "\t.local \t"; + PrintTypes(OS, Types); + } } void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; } void WebAssemblyTargetAsmStreamer::emitIndirectFunctionType( - StringRef name, SmallVectorImpl<MVT> &SignatureVTs, size_t NumResults) { + StringRef name, SmallVectorImpl<MVT> &Params, SmallVectorImpl<MVT> &Results) { OS << "\t.functype\t" << name; - if (NumResults == 0) OS << ", void"; - for (auto Ty : SignatureVTs) { - OS << ", " << WebAssembly::TypeToString(Ty); + if (Results.empty()) + OS << ", void"; + else { + assert(Results.size() == 1); + OS << ", " << WebAssembly::TypeToString(Results.front()); } - OS << "\n"; + for (auto Ty : Params) + OS << ", " << WebAssembly::TypeToString(Ty); + OS << '\n'; } -// FIXME: What follows is not the real binary encoding. +void WebAssemblyTargetAsmStreamer::emitGlobalImport(StringRef name) { + OS << "\t.import_global\t" << name << '\n'; +} -static void EncodeTypes(MCStreamer &Streamer, ArrayRef<MVT> Types) { - Streamer.EmitIntValue(Types.size(), sizeof(uint64_t)); - for (MVT Type : Types) - Streamer.EmitIntValue(Type.SimpleTy, sizeof(uint64_t)); +void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) { + OS << "\t.indidx \t" << *Value << '\n'; } void WebAssemblyTargetELFStreamer::emitParam(ArrayRef<MVT> Types) { - Streamer.EmitIntValue(WebAssembly::DotParam, sizeof(uint64_t)); - EncodeTypes(Streamer, Types); + // Nothing to emit; params are declared as part of the function signature. } void WebAssemblyTargetELFStreamer::emitResult(ArrayRef<MVT> Types) { - Streamer.EmitIntValue(WebAssembly::DotResult, sizeof(uint64_t)); - EncodeTypes(Streamer, Types); + // Nothing to emit; results are declared as part of the function signature. } void WebAssemblyTargetELFStreamer::emitLocal(ArrayRef<MVT> Types) { - Streamer.EmitIntValue(WebAssembly::DotLocal, sizeof(uint64_t)); - EncodeTypes(Streamer, Types); + Streamer.EmitULEB128IntValue(Types.size()); + for (MVT Type : Types) + Streamer.EmitIntValue(int64_t(WebAssembly::toValType(Type)), 1); } void WebAssemblyTargetELFStreamer::emitEndFunc() { - Streamer.EmitIntValue(WebAssembly::DotEndFunc, sizeof(uint64_t)); + Streamer.EmitIntValue(WebAssembly::End, 1); +} + +void WebAssemblyTargetELFStreamer::emitIndIdx(const MCExpr *Value) { + llvm_unreachable(".indidx encoding not yet implemented"); } + +void WebAssemblyTargetELFStreamer::emitIndirectFunctionType( + StringRef name, 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) { +}
\ No newline at end of file diff --git a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h index 51354ef22d71..23ac3190243a 100644 --- a/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h +++ b/contrib/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h @@ -39,10 +39,14 @@ public: virtual void emitEndFunc() = 0; /// .functype virtual void emitIndirectFunctionType(StringRef name, - SmallVectorImpl<MVT> &SignatureVTs, - size_t NumResults) { + SmallVectorImpl<MVT> &Params, + SmallVectorImpl<MVT> &Results) { llvm_unreachable("emitIndirectFunctionType not implemented"); } + /// .indidx + virtual void emitIndIdx(const MCExpr *Value) = 0; + /// .import_global + virtual void emitGlobalImport(StringRef name) = 0; }; /// This part is for ascii assembly output @@ -57,8 +61,10 @@ public: void emitLocal(ArrayRef<MVT> Types) override; void emitEndFunc() override; void emitIndirectFunctionType(StringRef name, - SmallVectorImpl<MVT> &SignatureVTs, - size_t NumResults) override; + 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 @@ -70,6 +76,11 @@ public: void emitResult(ArrayRef<MVT> Types) override; void emitLocal(ArrayRef<MVT> Types) override; void emitEndFunc() override; + void emitIndirectFunctionType(StringRef name, + SmallVectorImpl<MVT> &Params, + SmallVectorImpl<MVT> &Results) override; + void emitIndIdx(const MCExpr *Value) override; + void emitGlobalImport(StringRef name) override; }; } // end namespace llvm |