forked from OSchip/llvm-project
WebAssembly: basic instructions todo, and basic register info.
Summary: This code is based on AArch64 for modern backend good practice, and NVPTX for virtual ISA concerns. Reviewers: sunfish Subscribers: aemerson, llvm-commits, jfb Differential Revision: http://reviews.llvm.org/D11070 llvm-svn: 241923
This commit is contained in:
parent
f6bc8667cd
commit
5ca0baca4a
|
@ -1,6 +1,7 @@
|
|||
set(LLVM_TARGET_DEFINITIONS WebAssembly.td)
|
||||
|
||||
tablegen(LLVM WebAssemblyGenMCCodeEmitter.inc -gen-emitter)
|
||||
tablegen(LLVM WebAssemblyGenRegisterInfo.inc -gen-register-info)
|
||||
tablegen(LLVM WebAssemblyGenSubtargetInfo.inc -gen-subtarget)
|
||||
add_public_tablegen_target(WebAssemblyCommonTableGen)
|
||||
|
||||
|
|
|
@ -29,6 +29,9 @@ using namespace llvm;
|
|||
#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);
|
||||
|
|
|
@ -47,6 +47,9 @@ MCAsmBackend *createWebAssemblyAsmBackend(const Target &T,
|
|||
// 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"
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@ LIBRARYNAME = LLVMWebAssemblyCodeGen
|
|||
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
|
||||
|
||||
|
|
|
@ -6,9 +6,10 @@
|
|||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// WebAssembly Atomic operand code-gen constructs.
|
||||
//
|
||||
///
|
||||
/// \file
|
||||
/// \brief WebAssembly Atomic operand code-gen constructs.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// TODO: Implement atomic instructions.
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
//===- WebAssemblyInstrCall.td-WebAssembly Call 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 Call operand code-gen constructs.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
|
@ -0,0 +1,44 @@
|
|||
//===-- WebAssemblyInstrConv.td-WebAssembly Conversion 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
|
||||
*/
|
|
@ -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
|
||||
*/
|
|
@ -6,9 +6,10 @@
|
|||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// WebAssembly instruction format definitions.
|
||||
//
|
||||
///
|
||||
/// \file
|
||||
/// \brief WebAssembly instruction format definitions.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// WebAssembly Instruction Format
|
||||
|
|
|
@ -6,9 +6,10 @@
|
|||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// WebAssembly Instruction definitions.
|
||||
//
|
||||
///
|
||||
/// \file
|
||||
/// \brief WebAssembly Instruction definitions.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -32,6 +33,13 @@ def HasSIMD128 : Predicate<"Subtarget->hasSIMD128()">,
|
|||
// WebAssembly-specific Operands.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// WebAssembly Instruction Format Definitions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -42,5 +50,10 @@ include "WebAssemblyInstrFormats.td"
|
|||
// 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"
|
||||
|
|
|
@ -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
|
||||
*/
|
|
@ -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
|
||||
*/
|
|
@ -6,9 +6,10 @@
|
|||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// WebAssembly SIMD operand code-gen constructs.
|
||||
//
|
||||
///
|
||||
/// \file
|
||||
/// \brief WebAssembly SIMD operand code-gen constructs.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// TODO: Implement SIMD instructions.
|
||||
|
|
|
@ -30,4 +30,58 @@ using namespace llvm;
|
|||
|
||||
#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());
|
||||
for (auto Reg : {WebAssembly::SP32, WebAssembly::SP64, WebAssembly::FP32,
|
||||
WebAssembly::FP64})
|
||||
Reserved.set(Reg);
|
||||
return Reserved;
|
||||
}
|
||||
|
||||
void WebAssemblyRegisterInfo::eliminateFrameIndex(
|
||||
MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum,
|
||||
RegScavenger *RS) const {
|
||||
llvm_unreachable("WebAssemblyRegisterInfo::eliminateFrameIndex"); // FIXME
|
||||
}
|
||||
|
||||
unsigned
|
||||
WebAssemblyRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
|
||||
static const unsigned Regs[2][2] = {
|
||||
/* !isArch64Bit isArch64Bit */
|
||||
/* !hasFP */ {WebAssembly::SP32, WebAssembly::SP64},
|
||||
/* hasFP */ {WebAssembly::FP32, WebAssembly::FP64}};
|
||||
const WebAssemblyFrameLowering *TFI = getFrameLowering(MF);
|
||||
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 WebAssemblyFrameLowering *TFI = getFrameLowering(MF);
|
||||
const Function *F = MF.getFunction();
|
||||
unsigned StackAlign = TFI->getStackAlignment();
|
||||
bool requiresRealignment =
|
||||
((MFI->getMaxAlignment() > StackAlign) ||
|
||||
F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
|
||||
Attribute::StackAlignment));
|
||||
|
||||
return requiresRealignment && canRealignStack(MF);
|
||||
}
|
||||
|
|
|
@ -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 RegScavenger;
|
|||
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
|
||||
|
|
|
@ -6,10 +6,11 @@
|
|||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file describes the WebAssembly register classes and some nominal
|
||||
// physical registers.
|
||||
//
|
||||
///
|
||||
/// \file
|
||||
/// \brief This file describes the WebAssembly register classes and some nominal
|
||||
/// physical registers.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class WebAssemblyReg<string n> : Register<n> {
|
||||
|
@ -23,6 +24,31 @@ class WebAssemblyRegClass<list<ValueType> regTypes, int alignment, dag regList>
|
|||
// Registers
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Special registers used as the frame and stack pointer.
|
||||
//
|
||||
// WebAssembly may someday 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">;
|
||||
|
||||
// TODO(jfb) The following comes from NVPTX. Is it really needed, or can we do
|
||||
// away with it? Try deleting once the backend works.
|
||||
// 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))>;
|
||||
|
|
Loading…
Reference in New Issue