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:
JF Bastien 2015-07-10 18:23:10 +00:00
parent f6bc8667cd
commit 5ca0baca4a
16 changed files with 331 additions and 19 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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"

View File

@ -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

View File

@ -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.

View File

@ -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
*/

View File

@ -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
*/

View File

@ -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
*/

View File

@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// WebAssembly instruction format definitions.
//
///
/// \file
/// \brief WebAssembly instruction format definitions.
///
//===----------------------------------------------------------------------===//
// WebAssembly Instruction Format

View File

@ -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"

View File

@ -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
*/

View File

@ -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
*/

View File

@ -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.

View File

@ -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);
}

View File

@ -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

View File

@ -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))>;