summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/WebAssembly
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/WebAssembly')
-rw-r--r--llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp26
-rw-r--r--llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp6
-rw-r--r--llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp25
-rw-r--r--llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp10
-rw-r--r--llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h67
-rw-r--r--llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp36
-rw-r--r--llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h3
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp13
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp2
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp22
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td16
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td12
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td4
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td7
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td4
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h4
16 files changed, 126 insertions, 131 deletions
diff --git a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp
index 9b59c7554bd..1b52bed0abe 100644
--- a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp
@@ -154,22 +154,11 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
(Desc.TSFlags & WebAssemblyII::VariableOpIsImmediate)) &&
"WebAssemblyII::VariableOpIsImmediate should be set for "
"variable_ops immediate ops");
-
- if (Desc.TSFlags & WebAssemblyII::VariableOpImmediateIsType) {
- switch (Op.getImm()) {
- case int64_t(WebAssembly::ValType::I32): O << "i32"; break;
- case int64_t(WebAssembly::ValType::I64): O << "i64"; break;
- case int64_t(WebAssembly::ValType::F32): O << "f32"; break;
- case int64_t(WebAssembly::ValType::F64): O << "f64"; break;
- default: llvm_unreachable("unknown local type");
- }
- } else {
- // TODO: (MII.get(MI->getOpcode()).TSFlags &
- // WebAssemblyII::VariableOpImmediateIsLabel)
- // can tell us whether this is an immediate referencing a label in the
- // control flow stack, and it may be nice to pretty-print.
- O << Op.getImm();
- }
+ // TODO: (MII.get(MI->getOpcode()).TSFlags &
+ // WebAssemblyII::VariableOpImmediateIsLabel)
+ // can tell us whether this is an immediate referencing a label in the
+ // control flow stack, and it may be nice to pretty-print.
+ O << Op.getImm();
} else if (Op.isFPImm()) {
const MCInstrDesc &Desc = MII.get(MI->getOpcode());
assert(OpNo < Desc.getNumOperands() &&
@@ -220,9 +209,10 @@ WebAssemblyInstPrinter::printWebAssemblySignatureOperand(const MCInst *MI,
case WebAssembly::ExprType::I8x16: O << "i8x16"; break;
case WebAssembly::ExprType::I16x8: O << "i16x8"; break;
case WebAssembly::ExprType::I32x4: O << "i32x4"; break;
- case WebAssembly::ExprType::I64x2: O << "i32x4"; break;
case WebAssembly::ExprType::F32x4: O << "f32x4"; break;
- case WebAssembly::ExprType::F64x2: O << "f64x2"; break;
+ case WebAssembly::ExprType::B8x16: O << "b8x16"; break;
+ case WebAssembly::ExprType::B16x8: O << "b16x8"; break;
+ case WebAssembly::ExprType::B32x4: O << "b32x4"; break;
}
}
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;
};
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index 85ff1b80e3c..f53cfca9db3 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -42,7 +42,7 @@ namespace {
class WebAssemblyAsmPrinter final : public AsmPrinter {
const MachineRegisterInfo *MRI;
- const WebAssemblyFunctionInfo *MFI;
+ WebAssemblyFunctionInfo *MFI;
public:
WebAssemblyAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
@@ -166,8 +166,8 @@ void WebAssemblyAsmPrinter::EmitFunctionBodyStart() {
if (ResultVTs.size() == 1)
getTargetStreamer()->emitResult(ResultVTs);
- bool AnyWARegs = false;
- SmallVector<MVT, 16> LocalTypes;
+ // FIXME: When ExplicitLocals is enabled by default, we won't need
+ // to define the locals here (and MFI can go back to being pointer-to-const).
for (unsigned Idx = 0, IdxE = MRI->getNumVirtRegs(); Idx != IdxE; ++Idx) {
unsigned VReg = TargetRegisterInfo::index2VirtReg(Idx);
unsigned WAReg = MFI->getWAReg(VReg);
@@ -180,11 +180,10 @@ void WebAssemblyAsmPrinter::EmitFunctionBodyStart() {
// Don't declare stackified registers.
if (int(WAReg) < 0)
continue;
- LocalTypes.push_back(getRegType(VReg));
- AnyWARegs = true;
+ MFI->addLocal(getRegType(VReg));
}
- if (AnyWARegs)
- getTargetStreamer()->emitLocal(LocalTypes);
+
+ getTargetStreamer()->emitLocal(MFI->getLocals());
AsmPrinter::EmitFunctionBodyStart();
}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
index 18b6f932081..49b9754e6b6 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
@@ -466,9 +466,7 @@ static void FixEndsAtEndOfFunction(
case MVT::v16i8: retType = WebAssembly::ExprType::I8x16; break;
case MVT::v8i16: retType = WebAssembly::ExprType::I16x8; break;
case MVT::v4i32: retType = WebAssembly::ExprType::I32x4; break;
- case MVT::v2i64: retType = WebAssembly::ExprType::I64x2; break;
case MVT::v4f32: retType = WebAssembly::ExprType::F32x4; break;
- case MVT::v2f64: retType = WebAssembly::ExprType::F64x2; break;
default: llvm_unreachable("unexpected return type");
}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
index 3b527922419..56b0f4fb684 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
@@ -109,15 +109,15 @@ static unsigned getTeeLocalOpcode(const TargetRegisterClass *RC) {
}
/// Get the type associated with the given register class.
-static WebAssembly::ValType typeForRegClass(const TargetRegisterClass *RC) {
+static MVT typeForRegClass(const TargetRegisterClass *RC) {
if (RC == &WebAssembly::I32RegClass)
- return WebAssembly::ValType::I32;
+ return MVT::i32;
if (RC == &WebAssembly::I64RegClass)
- return WebAssembly::ValType::I64;
+ return MVT::i64;
if (RC == &WebAssembly::F32RegClass)
- return WebAssembly::ValType::F32;
+ return MVT::f32;
if (RC == &WebAssembly::F64RegClass)
- return WebAssembly::ValType::F64;
+ return MVT::f64;
llvm_unreachable("unrecognized register class");
}
@@ -272,21 +272,15 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
}
}
- // Insert a .locals directive to declare the locals.
- MachineInstrBuilder DeclareLocals;
+ // Define the locals.
for (size_t i = 0, e = MRI.getNumVirtRegs(); i < e; ++i) {
unsigned Reg = TargetRegisterInfo::index2VirtReg(i);
auto I = Reg2Local.find(Reg);
if (I == Reg2Local.end() || I->second < MFI.getParams().size())
continue;
- if (!DeclareLocals) {
- DeclareLocals = BuildMI(*MF.begin(), MF.begin()->begin(), DebugLoc(),
- TII->get(WebAssembly::DECLARE_LOCALS));
- Changed = true;
- }
-
- DeclareLocals.addImm(int64_t(typeForRegClass(MRI.getRegClass(Reg))));
+ MFI.addLocal(typeForRegClass(MRI.getRegClass(Reg)));
+ Changed = true;
}
#ifndef NDEBUG
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td
index 47459f85a16..f4906e9fca2 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td
@@ -28,7 +28,8 @@ def ADJCALLSTACKUP : I<(outs), (ins i32imm:$amt, i32imm:$amt2),
multiclass CALL<WebAssemblyRegClass vt, string prefix> {
def CALL_#vt : I<(outs vt:$dst), (ins i32imm:$callee, variable_ops),
[(set vt:$dst, (WebAssemblycall1 (i32 imm:$callee)))],
- !strconcat(prefix, "call\t$dst, $callee")>;
+ !strconcat(prefix, "call\t$dst, $callee"),
+ 0x10>;
let isCodeGenOnly = 1 in {
def PCALL_INDIRECT_#vt : I<(outs vt:$dst), (ins I32:$callee, variable_ops),
[(set vt:$dst, (WebAssemblycall1 I32:$callee))],
@@ -36,14 +37,16 @@ multiclass CALL<WebAssemblyRegClass vt, string prefix> {
} // isCodeGenOnly = 1
def CALL_INDIRECT_#vt : I<(outs vt:$dst), (ins variable_ops),
[],
- !strconcat(prefix, "call_indirect\t$dst")>;
+ !strconcat(prefix, "call_indirect\t$dst"),
+ 0x11>;
}
multiclass SIMD_CALL<ValueType vt, string prefix> {
def CALL_#vt : SIMD_I<(outs V128:$dst), (ins i32imm:$callee, variable_ops),
[(set (vt V128:$dst),
(WebAssemblycall1 (i32 imm:$callee)))],
- !strconcat(prefix, "call\t$dst, $callee")>;
+ !strconcat(prefix, "call\t$dst, $callee"),
+ 0x10>;
let isCodeGenOnly = 1 in {
def PCALL_INDIRECT_#vt : SIMD_I<(outs V128:$dst),
(ins I32:$callee, variable_ops),
@@ -54,7 +57,8 @@ multiclass SIMD_CALL<ValueType vt, string prefix> {
def CALL_INDIRECT_#vt : SIMD_I<(outs V128:$dst),
(ins variable_ops),
[],
- !strconcat(prefix, "call_indirect\t$dst")>;
+ !strconcat(prefix, "call_indirect\t$dst"),
+ 0x11>;
}
let Uses = [SP32, SP64], isCall = 1 in {
@@ -69,7 +73,7 @@ let Uses = [SP32, SP64], isCall = 1 in {
def CALL_VOID : I<(outs), (ins i32imm:$callee, variable_ops),
[(WebAssemblycall0 (i32 imm:$callee))],
- "call \t$callee">;
+ "call \t$callee", 0x10>;
let isCodeGenOnly = 1 in {
def PCALL_INDIRECT_VOID : I<(outs), (ins I32:$callee, variable_ops),
[(WebAssemblycall0 I32:$callee)],
@@ -77,7 +81,7 @@ let Uses = [SP32, SP64], isCall = 1 in {
} // isCodeGenOnly = 1
def CALL_INDIRECT_VOID : I<(outs), (ins variable_ops),
[],
- "call_indirect\t">;
+ "call_indirect\t", 0x11>;
} // Uses = [SP32,SP64], isCall = 1
} // Defs = [ARGUMENTS]
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td
index 7ff5bbdcd48..1146431e6b7 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td
@@ -65,13 +65,13 @@ def BLOCK : I<(outs), (ins Signature:$sig), [], "block \t$sig", 0x02>;
def LOOP : I<(outs), (ins Signature:$sig), [], "loop \t$sig", 0x03>;
// END_BLOCK and END_LOOP are represented with the same opcode in wasm.
-def END_BLOCK : I<(outs), (ins), [], "end_block", 0x0f>;
-def END_LOOP : I<(outs), (ins), [], "end_loop", 0x0f>;
+def END_BLOCK : I<(outs), (ins), [], "end_block", 0x0b>;
+def END_LOOP : I<(outs), (ins), [], "end_loop", 0x0b>;
} // Uses = [VALUE_STACK], Defs = [VALUE_STACK]
multiclass RETURN<WebAssemblyRegClass vt> {
def RETURN_#vt : I<(outs), (ins vt:$val), [(WebAssemblyreturn vt:$val)],
- "return \t$val">;
+ "return \t$val", 0x0f>;
// Equivalent to RETURN_#vt, for use at the end of a function when wasm
// semantics return by falling off the end of the block.
let isCodeGenOnly = 1 in
@@ -81,7 +81,7 @@ multiclass RETURN<WebAssemblyRegClass vt> {
multiclass SIMD_RETURN<ValueType vt> {
def RETURN_#vt : SIMD_I<(outs), (ins V128:$val),
[(WebAssemblyreturn (vt V128:$val))],
- "return \t$val">;
+ "return \t$val", 0x0f>;
// Equivalent to RETURN_#vt, for use at the end of a function when wasm
// semantics return by falling off the end of the block.
let isCodeGenOnly = 1 in
@@ -100,14 +100,14 @@ let isReturn = 1 in {
defm : SIMD_RETURN<v4i32>;
defm : SIMD_RETURN<v4f32>;
- def RETURN_VOID : I<(outs), (ins), [(WebAssemblyreturn)], "return">;
+ def RETURN_VOID : I<(outs), (ins), [(WebAssemblyreturn)], "return", 0x0f>;
// This is to RETURN_VOID what FALLTHROUGH_RETURN_#vt is to RETURN_#vt.
let isCodeGenOnly = 1 in
def FALLTHROUGH_RETURN_VOID : I<(outs), (ins), []>;
} // isReturn = 1
-def UNREACHABLE : I<(outs), (ins), [(trap)], "unreachable">;
+def UNREACHABLE : I<(outs), (ins), [(trap)], "unreachable", 0x00>;
} // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td
index a67fd676013..030be0862a5 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFloat.td
@@ -79,10 +79,10 @@ let Defs = [ARGUMENTS] in {
def SELECT_F32 : I<(outs F32:$dst), (ins F32:$lhs, F32:$rhs, I32:$cond),
[(set F32:$dst, (select I32:$cond, F32:$lhs, F32:$rhs))],
- "f32.select\t$dst, $lhs, $rhs, $cond">;
+ "f32.select\t$dst, $lhs, $rhs, $cond", 0x1b>;
def SELECT_F64 : I<(outs F64:$dst), (ins F64:$lhs, F64:$rhs, I32:$cond),
[(set F64:$dst, (select I32:$cond, F64:$lhs, F64:$rhs))],
- "f64.select\t$dst, $lhs, $rhs, $cond">;
+ "f64.select\t$dst, $lhs, $rhs, $cond", 0x1b>;
} // Defs = [ARGUMENTS]
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
index f094aae9c90..b38dd2070ce 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
@@ -180,13 +180,6 @@ defm : LOCAL<F32>;
defm : LOCAL<F64>;
defm : LOCAL<V128>, Requires<[HasSIMD128]>;
-// Set TSFlags{0} to 1 to indicate that the variable_ops are immediates.
-// Set TSFlags{2} to 1 to indicate that the immediates are ValTypes.
-def DECLARE_LOCALS : I<(outs), (ins variable_ops), [], ".local \t"> {
- let TSFlags{0} = 1;
- let TSFlags{2} = 1;
-}
-
let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 in {
def CONST_I32 : I<(outs I32:$res), (ins i32imm_op:$imm),
[(set I32:$res, imm:$imm)],
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td
index ab28dd3e1c7..7cdeb397be9 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td
@@ -75,10 +75,10 @@ let Defs = [ARGUMENTS] in {
def SELECT_I32 : I<(outs I32:$dst), (ins I32:$lhs, I32:$rhs, I32:$cond),
[(set I32:$dst, (select I32:$cond, I32:$lhs, I32:$rhs))],
- "i32.select\t$dst, $lhs, $rhs, $cond">;
+ "i32.select\t$dst, $lhs, $rhs, $cond", 0x1b>;
def SELECT_I64 : I<(outs I64:$dst), (ins I64:$lhs, I64:$rhs, I32:$cond),
[(set I64:$dst, (select I32:$cond, I64:$lhs, I64:$rhs))],
- "i64.select\t$dst, $lhs, $rhs, $cond">;
+ "i64.select\t$dst, $lhs, $rhs, $cond", 0x1b>;
} // Defs = [ARGUMENTS]
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h
index 61382cd0640..c5702ce11ad 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h
@@ -28,6 +28,7 @@ class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
std::vector<MVT> Params;
std::vector<MVT> Results;
+ std::vector<MVT> Locals;
/// A mapping from CodeGen vreg index to WebAssembly register number.
std::vector<unsigned> WARegs;
@@ -55,6 +56,9 @@ class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
void addResult(MVT VT) { Results.push_back(VT); }
const std::vector<MVT> &getResults() const { return Results; }
+ void addLocal(MVT VT) { Locals.push_back(VT); }
+ const std::vector<MVT> &getLocals() const { return Locals; }
+
unsigned getVarargBufferVreg() const {
assert(VarargVreg != -1U && "Vararg vreg hasn't been set");
return VarargVreg;
OpenPOWER on IntegriCloud