diff options
| author | Dan Gohman <dan433584@gmail.com> | 2016-10-24 23:27:49 +0000 |
|---|---|---|
| committer | Dan Gohman <dan433584@gmail.com> | 2016-10-24 23:27:49 +0000 |
| commit | 3acb187d95a8cbe1941459a9c6fb62cc5d44b1e5 (patch) | |
| tree | 450f11c44d1568ef9e344e5163d34bc4d305250b /llvm/lib/Target/WebAssembly/MCTargetDesc | |
| parent | 8b38ffaa986a06a6bdbd243b26eacc46ce9e5889 (diff) | |
| download | bcm5719-llvm-3acb187d95a8cbe1941459a9c6fb62cc5d44b1e5.tar.gz bcm5719-llvm-3acb187d95a8cbe1941459a9c6fb62cc5d44b1e5.zip | |
[WebAssembly] Implement more WebAssembly binary encoding.
This changes locals from being declared by the emitLocal hook in
WebAssemblyTargetStreamer, rather than with an instruction. After exploring
the infastructure in LLVM more, this seems to make more sense since
declaring locals doesn't use an encoded opcode.
This also adds more 0xd opcodes, type encodings, and miscellaneous
binary encoding bits.
llvm-svn: 285040
Diffstat (limited to 'llvm/lib/Target/WebAssembly/MCTargetDesc')
6 files changed, 80 insertions, 67 deletions
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp index df6fb8968d5..97454a824a3 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp +++ b/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/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp index d740b0adc7a..f7183241f9f 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp @@ -60,7 +60,8 @@ void WebAssemblyMCCodeEmitter::encodeInstruction( uint64_t Start = OS.tell(); uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI); - encodeULEB128(Binary, OS); + assert(Binary < UINT8_MAX && "Multi-byte opcodes not supported yet"); + OS << uint8_t(Binary); const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); for (unsigned i = 0, e = MI.getNumOperands(); i < e; ++i) { @@ -68,16 +69,20 @@ void WebAssemblyMCCodeEmitter::encodeInstruction( if (MO.isReg()) { /* nothing to encode */ } else if (MO.isImm()) { - assert(i < Desc.getNumOperands() && - "Unexpected integer immediate as a non-fixed operand"); - assert(Desc.TSFlags == 0 && - "WebAssembly variable_ops integer 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); + 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()) { diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp index 5d7a0f82062..3dc1ded1711 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp @@ -134,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/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h index 5fa277324d6..ae3fb7bfd13 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -26,6 +26,7 @@ class MCContext; class MCInstrInfo; class MCObjectWriter; class MCSubtargetInfo; +class MVT; class Target; class Triple; class raw_pwrite_stream; @@ -59,17 +60,6 @@ enum OperandType { /// 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 - DotIndIdx = UINT64_MAX - 4, ///< .indidx -}; - } // end namespace WebAssembly namespace WebAssemblyII { @@ -79,10 +69,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), - // For immediate values in the variable_ops range, this flag indicates - // whether the value represents a ValType. - VariableOpImmediateIsType = (1 << 2), + VariableOpImmediateIsLabel = (1 << 1) }; } // end namespace WebAssemblyII @@ -150,33 +137,41 @@ static const unsigned StoreP2AlignOperandNo = 2; /// This is used to indicate block signatures. enum class ExprType { - Void = 0, - I32 = 1, - I64 = 2, - F32 = 3, - F64 = 4, - I8x16 = 5, - I16x8 = 6, - I32x4 = 7, - I64x2 = 8, - F32x4 = 9, - F64x2 = 10 + 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 = 1, - I64 = 2, - F32 = 3, - F64 = 4, - I8x16 = 5, - I16x8 = 6, - I32x4 = 7, - I64x2 = 8, - F32x4 = 9, - F64x2 = 10 + 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/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp index 9934b119cb6..f0886880802 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp @@ -58,8 +58,10 @@ 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"; } @@ -82,34 +84,30 @@ void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) { OS << "\t.indidx \t" << *Value << '\n'; } -// FIXME: What follows is not the real binary encoding. - -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 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) { - Streamer.EmitIntValue(WebAssembly::DotIndIdx, sizeof(uint64_t)); - Streamer.EmitValue(Value, sizeof(uint64_t)); + 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. } diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h index 15f67164bee..cf164ca5924 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h @@ -73,6 +73,9 @@ 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; }; |

