Index: lib/Target/WebAssembly/CMakeLists.txt =================================================================== --- lib/Target/WebAssembly/CMakeLists.txt +++ lib/Target/WebAssembly/CMakeLists.txt @@ -1,5 +1,6 @@ set(LLVM_TARGET_DEFINITIONS WebAssembly.td) +tablegen(LLVM WebAssemblyGenRegisterInfo.inc -gen-register-info) tablegen(LLVM WebAssemblyGenMCCodeEmitter.inc -gen-emitter) tablegen(LLVM WebAssemblyGenSubtargetInfo.inc -gen-subtarget) add_public_tablegen_target(WebAssemblyCommonTableGen) Index: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -47,6 +47,9 @@ // Defines symbolic names for WebAssembly registers. This defines a mapping from // register name to register number. // +#define GET_REGINFO_ENUM +#include "WebAssemblyGenRegisterInfo.inc" + #define GET_SUBTARGETINFO_ENUM #include "WebAssemblyGenSubtargetInfo.inc" Index: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp +++ lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp @@ -29,6 +29,9 @@ #define GET_SUBTARGETINFO_MC_DESC #include "WebAssemblyGenSubtargetInfo.inc" +#define GET_REGINFO_MC_DESC +#include "WebAssemblyGenRegisterInfo.inc" + static MCAsmInfo *createWebAssemblyMCAsmInfo(const MCRegisterInfo &MRI, const Triple &TT) { MCAsmInfo *MAI = new WebAssemblyMCAsmInfo(TT); Index: lib/Target/WebAssembly/Makefile =================================================================== --- lib/Target/WebAssembly/Makefile +++ lib/Target/WebAssembly/Makefile @@ -12,7 +12,8 @@ TARGET = WebAssembly # Make sure that tblgen is run, first thing. -BUILT_SOURCES = WebAssemblyGenSubtargetInfo.inc WebAssemblyGenMCCodeEmitter.inc +BUILT_SOURCES = WebAssemblyGenRegisterInfo.inc WebAssemblyGenSubtargetInfo.inc \ + WebAssemblyGenMCCodeEmitter.inc DIRS = InstPrinter TargetInfo MCTargetDesc Index: lib/Target/WebAssembly/WebAssemblyInstrAtomics.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrAtomics.td +++ lib/Target/WebAssembly/WebAssemblyInstrAtomics.td @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// // -// WebAssembly Atomic operand code-gen constructs. +// \file +// \brief WebAssembly Atomic operand code-gen constructs. // //===----------------------------------------------------------------------===// Index: lib/Target/WebAssembly/WebAssemblyInstrCall.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrCall.td +++ lib/Target/WebAssembly/WebAssemblyInstrCall.td @@ -1,4 +1,4 @@ -// WebAssemblyInstrSIMD.td - WebAssembly SIMD codegen support -*- tablegen -*-// +// WebAssemblyInstrCall.td-WebAssembly Call codegen support -----*- tablegen -*- // // The LLVM Compiler Infrastructure // @@ -7,9 +7,15 @@ // //===----------------------------------------------------------------------===// // -// WebAssembly SIMD operand code-gen constructs. +// \file +// \brief WebAssembly Call operand code-gen constructs. // //===----------------------------------------------------------------------===// -// TODO: Implement SIMD instructions. -// Note: use Requires<[HasSIMD128]>. +/* + * TODO(jfb): Add the following. + * + * call_direct: call function directly + * call_indirect: call function indirectly + * addressof: obtain a function pointer value for a given function + */ Index: lib/Target/WebAssembly/WebAssemblyInstrConv.td =================================================================== --- /dev/null +++ lib/Target/WebAssembly/WebAssemblyInstrConv.td @@ -0,0 +1,44 @@ +// WebAssemblyInstrConv.td-WebAssembly Conv codegen support -----*- tablegen -*- +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// \file +// \brief WebAssembly datatype conversions, truncations, reinterpretations, promotions, +// and demotions operand code-gen constructs. +// +//===----------------------------------------------------------------------===// + +/* + * TODO(jfb): Add the following. + * + * int32.wrap[int64]: wrap a 64-bit integer to a 32-bit integer + * int32.trunc_signed[float32]: truncate a 32-bit float to a signed 32-bit integer + * int32.trunc_signed[float64]: truncate a 64-bit float to a signed 32-bit integer + * int32.trunc_unsigned[float32]: truncate a 32-bit float to an unsigned 32-bit integer + * int32.trunc_unsigned[float64]: truncate a 64-bit float to an unsigned 32-bit integer + * int32.reinterpret[float32]: reinterpret the bits of a 32-bit float as a 32-bit integer + * int64.extend_signed[int32]: extend a signed 32-bit integer to a 64-bit integer + * int64.extend_unsigned[int32]: extend an unsigned 32-bit integer to a 64-bit integer + * int64.trunc_signed[float32]: truncate a 32-bit float to a signed 64-bit integer + * int64.trunc_signed[float64]: truncate a 64-bit float to a signed 64-bit integer + * int64.trunc_unsigned[float32]: truncate a 32-bit float to an unsigned 64-bit integer + * int64.trunc_unsigned[float64]: truncate a 64-bit float to an unsigned 64-bit integer + * int64.reinterpret[float64]: reinterpret the bits of a 64-bit float as a 64-bit integer + * float32.demote[float64]: demote a 64-bit float to a 32-bit float + * float32.cvt_signed[int32]: convert a signed 32-bit integer to a 32-bit float + * float32.cvt_signed[int64]: convert a signed 64-bit integer to a 32-bit float + * float32.cvt_unsigned[int32]: convert an unsigned 32-bit integer to a 32-bit float + * float32.cvt_unsigned[int64]: convert an unsigned 64-bit integer to a 32-bit float + * float32.reinterpret[int32]: reinterpret the bits of a 32-bit integer as a 32-bit float + * float64.promote[float32]: promote a 32-bit float to a 64-bit float + * float64.cvt_signed[int32]: convert a signed 32-bit integer to a 64-bit float + * float64.cvt_signed[int64]: convert a signed 64-bit integer to a 64-bit float + * float64.cvt_unsigned[int32]: convert an unsigned 32-bit integer to a 64-bit float + * float64.cvt_unsigned[int64]: convert an unsigned 64-bit integer to a 64-bit float + * float64.reinterpret[int64]: reinterpret the bits of a 64-bit integer as a 64-bit float + */ Index: lib/Target/WebAssembly/WebAssemblyInstrFloat.td =================================================================== --- /dev/null +++ lib/Target/WebAssembly/WebAssemblyInstrFloat.td @@ -0,0 +1,37 @@ +// WebAssemblyInstrFloat.td-WebAssembly Float codegen support ---*- tablegen -*- +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// \file +// \brief WebAssembly Floating-point operand code-gen constructs. +// +//===----------------------------------------------------------------------===// + +/* + * TODO(jfb): Add the following for 32-bit and 64-bit. + * + * float32.add: addition + * float32.sub: subtraction + * float32.mul: multiplication + * float32.div: division + * float32.abs: absolute value + * float32.neg: negation + * float32.copysign: copysign + * float32.ceil: ceiling operation + * float32.floor: floor operation + * float32.trunc: round to nearest integer towards zero + * float32.nearestint: round to nearest integer, ties to even + * float32.eq: compare equal + * float32.lt: less than + * float32.le: less than or equal + * float32.gt: greater than + * float32.ge: greater than or equal + * float32.sqrt: square root + * float32.min: minimum (binary operator); if either operand is NaN, returns NaN + * float32.max: maximum (binary operator); if either operand is NaN, returns NaN + */ Index: lib/Target/WebAssembly/WebAssemblyInstrFormats.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrFormats.td +++ lib/Target/WebAssembly/WebAssemblyInstrFormats.td @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// // -// WebAssembly instruction format definitions. +// \file +// \brief WebAssembly instruction format definitions. // //===----------------------------------------------------------------------===// Index: lib/Target/WebAssembly/WebAssemblyInstrInfo.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// // -// WebAssembly Instruction definitions. +// \file +// \brief WebAssembly Instruction definitions. // //===----------------------------------------------------------------------===// @@ -29,18 +30,34 @@ //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// -// WebAssembly-specific Operands. +// WebAssembly Instruction Format Definitions. //===----------------------------------------------------------------------===// +include "WebAssemblyInstrFormats.td" + //===----------------------------------------------------------------------===// -// WebAssembly Instruction Format Definitions. +// WebAssembly-specific Operands. //===----------------------------------------------------------------------===// -include "WebAssemblyInstrFormats.td" +/* + * TODO(jfb): Add the following. + * + * get_local: read the current value of a local variable + * set_local: set the current value of a local variable + * + * comma: evaluate and ignore the result of the first operand, evaluate and + * return the second operand + * conditional: basically ternary ?: operator +*/ //===----------------------------------------------------------------------===// // Additional sets of instructions. //===----------------------------------------------------------------------===// +include "WebAssemblyInstrMemory.td" +include "WebAssemblyInstrCall.td" +include "WebAssemblyInstrInteger.td" +include "WebAssemblyInstrFloat.td" +include "WebAssemblyInstrConv.td" include "WebAssemblyInstrAtomics.td" include "WebAssemblyInstrSIMD.td" Index: lib/Target/WebAssembly/WebAssemblyInstrInteger.td =================================================================== --- /dev/null +++ lib/Target/WebAssembly/WebAssemblyInstrInteger.td @@ -0,0 +1,43 @@ +// WebAssemblyInstrInteger.td-WebAssembly Integer codegen -------*- tablegen -*- +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// \file +// \brief WebAssembly Integer operand code-gen constructs. +// +//===----------------------------------------------------------------------===// + +/* + * TODO(jfb): Add the following for 32-bit and 64-bit. + * + * int32.add: signed-less addition + * int32.sub: signed-less subtraction + * int32.mul: signed-less multiplication (lower 32-bits) + * int32.sdiv: signed division + * int32.udiv: unsigned division + * int32.srem: signed remainder + * int32.urem: unsigned remainder + * int32.and: signed-less logical and + * int32.ior: signed-less inclusive or + * int32.xor: signed-less exclusive or + * int32.shl: signed-less shift left + * int32.shr: signed-less logical shift right + * int32.sar: signed-less arithmetic shift right + * int32.eq: signed-less compare equal + * int32.slt: signed less than + * int32.sle: signed less than or equal + * int32.ult: unsigned less than + * int32.ule: unsigned less than or equal + * int32.sgt: signed greater than + * int32.sge: signed greater than or equal + * int32.ugt: unsigned greater than + * int32.uge: unsigned greater than or equal + * int32.clz: count leading zeroes (defined for all values, including zero) + * int32.ctz: count trailing zeroes (defined for all values, including zero) + * int32.popcnt: count number of ones + */ Index: lib/Target/WebAssembly/WebAssemblyInstrMemory.td =================================================================== --- /dev/null +++ lib/Target/WebAssembly/WebAssemblyInstrMemory.td @@ -0,0 +1,46 @@ +// WebAssemblyInstrMemory.td-WebAssembly Memory codegen support -*- tablegen -*- +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// \file +// \brief WebAssembly Memory operand code-gen constructs. +// +//===----------------------------------------------------------------------===// + +/* + * TODO(jfb): Add the following. + * Each has optional alignment and immediate byte offset. + * + * int32.load_sx[int8]: sign-extend to int32 + * int32.load_sx[int16]: sign-extend to int32 + * int32.load_zx[int8]: zero-extend to int32 + * int32.load_zx[int16]: zero-extend to int32 + * int32.load[int32]: (no conversion) + * int64.load_sx[int8]: sign-extend to int64 + * int64.load_sx[int16]: sign-extend to int64 + * int64.load_sx[int32]: sign-extend to int64 + * int64.load_zx[int8]: zero-extend to int64 + * int64.load_zx[int16]: zero-extend to int64 + * int64.load_zx[int32]: zero-extend to int64 + * int64.load[int64]: (no conversion) + * float32.load[float32]: (no conversion) + * float64.load[float64]: (no conversion) + * + * int32.store[int8]: wrap int32 to int8 + * int32.store[int16]: wrap int32 to int16 + * int32.store[int32]: (no conversion) + * int64.store[int8]: wrap int64 to int8 + * int64.store[int16]: wrap int64 to int16 + * int64.store[int32]: wrap int64 to int32 + * int64.store[int64]: (no conversion) + * float32.store[float32]: (no conversion) + * float64.store[float64]: (no conversion) + * + * load_global: load the value of a given global variable + * store_global: store a given value to a given global variable + */ Index: lib/Target/WebAssembly/WebAssemblyInstrSIMD.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrSIMD.td +++ lib/Target/WebAssembly/WebAssemblyInstrSIMD.td @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// // -// WebAssembly SIMD operand code-gen constructs. +// \file +// \brief WebAssembly SIMD operand code-gen constructs. // //===----------------------------------------------------------------------===// Index: lib/Target/WebAssembly/WebAssemblyRegisterInfo.h =================================================================== --- lib/Target/WebAssembly/WebAssemblyRegisterInfo.h +++ lib/Target/WebAssembly/WebAssemblyRegisterInfo.h @@ -16,6 +16,9 @@ #ifndef LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYREGISTERINFO_H #define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYREGISTERINFO_H +#define GET_REGINFO_HEADER +#include "WebAssemblyGenRegisterInfo.inc" + namespace llvm { class MachineFunction; @@ -23,11 +26,25 @@ class TargetRegisterClass; class Triple; -class WebAssemblyRegisterInfo final { +class WebAssemblyRegisterInfo final : public WebAssemblyGenRegisterInfo { const Triple &TT; public: explicit WebAssemblyRegisterInfo(const Triple &TT); + + // Code Generation virtual methods. + const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override; + BitVector getReservedRegs(const MachineFunction &MF) const override; + void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, + unsigned FIOperandNum, + RegScavenger *RS = nullptr) const override; + + // Debug information queries. + unsigned getFrameRegister(const MachineFunction &MF) const override; + + // Base pointer (stack realignment) support. + bool canRealignStack(const MachineFunction &MF) const; + bool needsStackRealignment(const MachineFunction &MF) const override; }; } // end namespace llvm Index: lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp +++ lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp @@ -30,4 +30,59 @@ #define DEBUG_TYPE "wasm-reg-info" -WebAssemblyRegisterInfo::WebAssemblyRegisterInfo(const Triple &TT) : TT(TT) {} +#define GET_REGINFO_TARGET_DESC +#include "WebAssemblyGenRegisterInfo.inc" + +WebAssemblyRegisterInfo::WebAssemblyRegisterInfo(const Triple &TT) + : WebAssemblyGenRegisterInfo(0), TT(TT) {} + +const MCPhysReg * +WebAssemblyRegisterInfo::getCalleeSavedRegs(const MachineFunction *) const { + static const MCPhysReg CalleeSavedRegs[] = {0}; + return CalleeSavedRegs; +} + +BitVector +WebAssemblyRegisterInfo::getReservedRegs(const MachineFunction &MF) const { + BitVector Reserved(getNumRegs()); + Reserved.set(WebAssembly::SP32); + Reserved.set(WebAssembly::SP64); + return Reserved; +} + +void WebAssemblyRegisterInfo::eliminateFrameIndex( + MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, + RegScavenger *RS) const { + report_fatal_error("WebAssemblyRegisterInfo::eliminateFrameIndex"); // FIXME +} + +unsigned +WebAssemblyRegisterInfo::getFrameRegister(const MachineFunction &MF) const { + static const unsigned char Regs[2][2] = { + /* !isArch64Bit isArch64Bit */ + /* !hasFP */ {WebAssembly::SP32, WebAssembly::SP64}, + /* hasFP */ {WebAssembly::FP32, WebAssembly::FP64}}; + const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); + return Regs[TFI->hasFP(MF)][TT.isArch64Bit()]; +} + +bool WebAssemblyRegisterInfo::canRealignStack(const MachineFunction &MF) const { + return !MF.getFunction()->hasFnAttribute("no-realign-stack"); +} + +// FIXME: share this with other backends with identical implementation? +bool WebAssemblyRegisterInfo::needsStackRealignment( + const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + const Function *F = MF.getFunction(); + unsigned StackAlign = MF.getTarget() + .getSubtargetImpl(*MF.getFunction()) + ->getFrameLowering() + ->getStackAlignment(); + bool requiresRealignment = + ((MFI->getMaxAlignment() > StackAlign) || + F->getAttributes().hasAttribute(AttributeSet::FunctionIndex, + Attribute::StackAlignment)); + + return requiresRealignment && canRealignStack(MF); +} Index: lib/Target/WebAssembly/WebAssemblyRegisterInfo.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyRegisterInfo.td +++ lib/Target/WebAssembly/WebAssemblyRegisterInfo.td @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// // -// This file describes the WebAssembly register classes and some nominal +// \file +// \brief This file describes the WebAssembly register classes and some nominal // physical registers. // //===----------------------------------------------------------------------===// @@ -23,6 +24,29 @@ // Registers //===----------------------------------------------------------------------===// +// Special registers used as the frame and stack pointer. +// +// WebAssembly supports mixed 32-bit and 64-bit heaps in the same application, +// which requires separate width FP and SP. +def FP32 : WebAssemblyReg<"%FP32">; +def FP64 : WebAssemblyReg<"%FP64">; +def SP32 : WebAssemblyReg<"%SP32">; +def SP64 : WebAssemblyReg<"%SP64">; + +// WebAssembly uses virtual registers, but the backend defines a few physical +// registers here to keep SDAG and the MachineInstr layers happy. +foreach i = 0-4 in { + def I#i : WebAssemblyReg<"%i."#i>; // i32 + def L#i : WebAssemblyReg<"%l."#i>; // i64 + def F#i : WebAssemblyReg<"%f."#i>; // f32 + def D#i : WebAssemblyReg<"%d."#i>; // f64 +} + //===----------------------------------------------------------------------===// // Register classes //===----------------------------------------------------------------------===// + +def Int32 : WebAssemblyRegClass<[i32], 32, (add (sequence "I%u", 0, 4), SP32)>; +def Int64 : WebAssemblyRegClass<[i64], 64, (add (sequence "L%u", 0, 4), SP64)>; +def Float32 : WebAssemblyRegClass<[f32], 32, (add (sequence "F%u", 0, 4))>; +def Float64 : WebAssemblyRegClass<[f64], 64, (add (sequence "D%u", 0, 4))>;