mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-09 11:25:55 +00:00
WebAssembly: basic bitcode → assembly CodeGen test
Summary: Add a basic CodeGen bitcode test which (for now) only prints out the function name and nothing else. The current code merely implements the basic needed for the test run to not crash / assert. Getting to that point required: - Basic InstPrinter. - Basic AsmPrinter. - DiagnosticInfoUnsupported (not strictly required, but nice to have, duplicated from AMDGPU/BPF's ISelLowering). - Some SP and register setup in WebAssemblyTargetLowering. - Basic LowerFormalArguments. - GenInstrInfo. - Placeholder LowerFormalArguments. - Placeholder CanLowerReturn and LowerReturn. - Basic DAGToDAGISel::Select, which requiresGenDAGISel.inc as well as GET_INSTRINFO_ENUM with GenInstrInfo.inc. - Remove WebAssemblyFrameLowering::determineCalleeSaves and rely on default. - Implement WebAssemblyFrameLowering::hasFP, same as AArch64's implementation. Follow-up patches will implement a real AsmPrinter, which will require adding MI opcodes specific to WebAssembly. Reviewers: sunfish Subscribers: aemerson, jfb, llvm-commits Differential Revision: http://reviews.llvm.org/D11369 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@242939 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -1,15 +1,19 @@
|
|||||||
set(LLVM_TARGET_DEFINITIONS WebAssembly.td)
|
set(LLVM_TARGET_DEFINITIONS WebAssembly.td)
|
||||||
|
|
||||||
|
tablegen(LLVM WebAssemblyGenAsmWriter.inc -gen-asm-writer)
|
||||||
|
tablegen(LLVM WebAssemblyGenDAGISel.inc -gen-dag-isel)
|
||||||
|
tablegen(LLVM WebAssemblyGenInstrInfo.inc -gen-instr-info)
|
||||||
tablegen(LLVM WebAssemblyGenMCCodeEmitter.inc -gen-emitter)
|
tablegen(LLVM WebAssemblyGenMCCodeEmitter.inc -gen-emitter)
|
||||||
tablegen(LLVM WebAssemblyGenRegisterInfo.inc -gen-register-info)
|
tablegen(LLVM WebAssemblyGenRegisterInfo.inc -gen-register-info)
|
||||||
tablegen(LLVM WebAssemblyGenSubtargetInfo.inc -gen-subtarget)
|
tablegen(LLVM WebAssemblyGenSubtargetInfo.inc -gen-subtarget)
|
||||||
add_public_tablegen_target(WebAssemblyCommonTableGen)
|
add_public_tablegen_target(WebAssemblyCommonTableGen)
|
||||||
|
|
||||||
add_llvm_target(WebAssemblyCodeGen
|
add_llvm_target(WebAssemblyCodeGen
|
||||||
|
WebAssemblyAsmPrinter.cpp
|
||||||
WebAssemblyFrameLowering.cpp
|
WebAssemblyFrameLowering.cpp
|
||||||
WebAssemblyInstrInfo.cpp
|
|
||||||
WebAssemblyISelDAGToDAG.cpp
|
WebAssemblyISelDAGToDAG.cpp
|
||||||
WebAssemblyISelLowering.cpp
|
WebAssemblyISelLowering.cpp
|
||||||
|
WebAssemblyInstrInfo.cpp
|
||||||
WebAssemblyMachineFunctionInfo.cpp
|
WebAssemblyMachineFunctionInfo.cpp
|
||||||
WebAssemblyRegisterInfo.cpp
|
WebAssemblyRegisterInfo.cpp
|
||||||
WebAssemblySelectionDAGInfo.cpp
|
WebAssemblySelectionDAGInfo.cpp
|
||||||
|
@@ -26,6 +26,8 @@ using namespace llvm;
|
|||||||
|
|
||||||
#define DEBUG_TYPE "asm-printer"
|
#define DEBUG_TYPE "asm-printer"
|
||||||
|
|
||||||
|
#include "WebAssemblyGenAsmWriter.inc"
|
||||||
|
|
||||||
WebAssemblyInstPrinter::WebAssemblyInstPrinter(const MCAsmInfo &MAI,
|
WebAssemblyInstPrinter::WebAssemblyInstPrinter(const MCAsmInfo &MAI,
|
||||||
const MCInstrInfo &MII,
|
const MCInstrInfo &MII,
|
||||||
const MCRegisterInfo &MRI)
|
const MCRegisterInfo &MRI)
|
||||||
@@ -33,11 +35,12 @@ WebAssemblyInstPrinter::WebAssemblyInstPrinter(const MCAsmInfo &MAI,
|
|||||||
|
|
||||||
void WebAssemblyInstPrinter::printRegName(raw_ostream &OS,
|
void WebAssemblyInstPrinter::printRegName(raw_ostream &OS,
|
||||||
unsigned RegNo) const {
|
unsigned RegNo) const {
|
||||||
llvm_unreachable("TODO: implement printRegName");
|
OS << getRegisterName(RegNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
|
void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
|
||||||
StringRef Annot,
|
StringRef Annot,
|
||||||
const MCSubtargetInfo &STI) {
|
const MCSubtargetInfo &STI) {
|
||||||
llvm_unreachable("TODO: implement printInst");
|
printInstruction(MI, OS);
|
||||||
|
printAnnotation(OS, Annot);
|
||||||
}
|
}
|
||||||
|
@@ -31,6 +31,10 @@ public:
|
|||||||
void printRegName(raw_ostream &OS, unsigned RegNo) const override;
|
void printRegName(raw_ostream &OS, unsigned RegNo) const override;
|
||||||
void printInst(const MCInst *MI, raw_ostream &OS, StringRef Annot,
|
void printInst(const MCInst *MI, raw_ostream &OS, StringRef Annot,
|
||||||
const MCSubtargetInfo &STI) override;
|
const MCSubtargetInfo &STI) override;
|
||||||
|
|
||||||
|
// Autogenerated by tblgen.
|
||||||
|
void printInstruction(const MCInst *MI, raw_ostream &O);
|
||||||
|
static const char *getRegisterName(unsigned RegNo);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
@@ -26,6 +26,9 @@ using namespace llvm;
|
|||||||
|
|
||||||
#define DEBUG_TYPE "wasm-mc-target-desc"
|
#define DEBUG_TYPE "wasm-mc-target-desc"
|
||||||
|
|
||||||
|
#define GET_INSTRINFO_MC_DESC
|
||||||
|
#include "WebAssemblyGenInstrInfo.inc"
|
||||||
|
|
||||||
#define GET_SUBTARGETINFO_MC_DESC
|
#define GET_SUBTARGETINFO_MC_DESC
|
||||||
#include "WebAssemblyGenSubtargetInfo.inc"
|
#include "WebAssemblyGenSubtargetInfo.inc"
|
||||||
|
|
||||||
|
@@ -50,6 +50,11 @@ MCAsmBackend *createWebAssemblyAsmBackend(const Target &T,
|
|||||||
#define GET_REGINFO_ENUM
|
#define GET_REGINFO_ENUM
|
||||||
#include "WebAssemblyGenRegisterInfo.inc"
|
#include "WebAssemblyGenRegisterInfo.inc"
|
||||||
|
|
||||||
|
// Defines symbolic names for the WebAssembly instructions.
|
||||||
|
//
|
||||||
|
#define GET_INSTRINFO_ENUM
|
||||||
|
#include "WebAssemblyGenInstrInfo.inc"
|
||||||
|
|
||||||
#define GET_SUBTARGETINFO_ENUM
|
#define GET_SUBTARGETINFO_ENUM
|
||||||
#include "WebAssemblyGenSubtargetInfo.inc"
|
#include "WebAssemblyGenSubtargetInfo.inc"
|
||||||
|
|
||||||
|
@@ -12,8 +12,13 @@ LIBRARYNAME = LLVMWebAssemblyCodeGen
|
|||||||
TARGET = WebAssembly
|
TARGET = WebAssembly
|
||||||
|
|
||||||
# Make sure that tblgen is run, first thing.
|
# Make sure that tblgen is run, first thing.
|
||||||
BUILT_SOURCES = WebAssemblyGenRegisterInfo.inc WebAssemblyGenSubtargetInfo.inc \
|
BUILT_SOURCES = \
|
||||||
WebAssemblyGenMCCodeEmitter.inc
|
WebAssemblyGenAsmWriter.inc \
|
||||||
|
WebAssemblyGenDAGISel.inc \
|
||||||
|
WebAssemblyGenInstrInfo.inc \
|
||||||
|
WebAssemblyGenMCCodeEmitter.inc \
|
||||||
|
WebAssemblyGenRegisterInfo.inc \
|
||||||
|
WebAssemblyGenSubtargetInfo.inc
|
||||||
|
|
||||||
DIRS = InstPrinter TargetInfo MCTargetDesc
|
DIRS = InstPrinter TargetInfo MCTargetDesc
|
||||||
|
|
||||||
|
91
lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
Normal file
91
lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
//===-- WebAssemblyAsmPrinter.cpp - WebAssembly LLVM assembly writer ------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
///
|
||||||
|
/// \file
|
||||||
|
/// \brief This file contains a printer that converts from our internal
|
||||||
|
/// representation of machine-dependent LLVM code to the WebAssembly assembly
|
||||||
|
/// language.
|
||||||
|
///
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "WebAssembly.h"
|
||||||
|
#include "WebAssemblyMachineFunctionInfo.h"
|
||||||
|
#include "WebAssemblyRegisterInfo.h"
|
||||||
|
#include "WebAssemblySubtarget.h"
|
||||||
|
#include "InstPrinter/WebAssemblyInstPrinter.h"
|
||||||
|
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
|
||||||
|
|
||||||
|
#include "llvm/ADT/SmallString.h"
|
||||||
|
#include "llvm/CodeGen/AsmPrinter.h"
|
||||||
|
#include "llvm/CodeGen/MachineInstr.h"
|
||||||
|
#include "llvm/IR/DataLayout.h"
|
||||||
|
#include "llvm/IR/DebugInfo.h"
|
||||||
|
#include "llvm/MC/MCStreamer.h"
|
||||||
|
#include "llvm/Support/Debug.h"
|
||||||
|
#include "llvm/Support/TargetRegistry.h"
|
||||||
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
#define DEBUG_TYPE "asm-printer"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class WebAssemblyAsmPrinter final : public AsmPrinter {
|
||||||
|
public:
|
||||||
|
WebAssemblyAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
|
||||||
|
: AsmPrinter(TM, std::move(Streamer)) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char *getPassName() const override {
|
||||||
|
return "WebAssembly Assembly Printer";
|
||||||
|
}
|
||||||
|
|
||||||
|
//===------------------------------------------------------------------===//
|
||||||
|
// MachineFunctionPass Implementation.
|
||||||
|
//===------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||||
|
AsmPrinter::getAnalysisUsage(AU);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool runOnMachineFunction(MachineFunction &F) override {
|
||||||
|
return AsmPrinter::runOnMachineFunction(F);
|
||||||
|
}
|
||||||
|
|
||||||
|
//===------------------------------------------------------------------===//
|
||||||
|
// AsmPrinter Implementation.
|
||||||
|
//===------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
void EmitInstruction(const MachineInstr *MI) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||||
|
SmallString<128> Str;
|
||||||
|
raw_svector_ostream OS(Str);
|
||||||
|
|
||||||
|
switch (MI->getOpcode()) {
|
||||||
|
default:
|
||||||
|
DEBUG(MI->print(dbgs()));
|
||||||
|
llvm_unreachable("Unhandled instruction");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
OutStreamer->EmitRawText(OS.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force static initialization.
|
||||||
|
extern "C" void LLVMInitializeWebAssemblyAsmPrinter() {
|
||||||
|
RegisterAsmPrinter<WebAssemblyAsmPrinter> X(TheWebAssemblyTarget32);
|
||||||
|
RegisterAsmPrinter<WebAssemblyAsmPrinter> Y(TheWebAssemblyTarget64);
|
||||||
|
}
|
@@ -39,7 +39,12 @@ using namespace llvm;
|
|||||||
/// Return true if the specified function should have a dedicated frame pointer
|
/// Return true if the specified function should have a dedicated frame pointer
|
||||||
/// register.
|
/// register.
|
||||||
bool WebAssemblyFrameLowering::hasFP(const MachineFunction &MF) const {
|
bool WebAssemblyFrameLowering::hasFP(const MachineFunction &MF) const {
|
||||||
llvm_unreachable("TODO: implement hasFP");
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
const auto *RegInfo = static_cast<const WebAssemblyRegisterInfo *>(
|
||||||
|
MF.getSubtarget().getRegisterInfo());
|
||||||
|
return MFI->hasCalls() || MFI->hasVarSizedObjects() ||
|
||||||
|
MFI->isFrameAddressTaken() || MFI->hasStackMap() ||
|
||||||
|
MFI->hasPatchPoint() || RegInfo->needsStackRealignment(MF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Under normal circumstances, when a frame pointer is not required, we reserve
|
/// Under normal circumstances, when a frame pointer is not required, we reserve
|
||||||
@@ -60,16 +65,10 @@ void WebAssemblyFrameLowering::eliminateCallFramePseudoInstr(
|
|||||||
|
|
||||||
void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
|
void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
|
||||||
MachineBasicBlock &MBB) const {
|
MachineBasicBlock &MBB) const {
|
||||||
llvm_unreachable("TODO: implement emitPrologue");
|
// FIXME: Implement WebAssemblyFrameLowering::emitPrologue.
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF,
|
void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||||
MachineBasicBlock &MBB) const {
|
MachineBasicBlock &MBB) const {
|
||||||
llvm_unreachable("TODO: implement emitEpilogue");
|
llvm_unreachable("TODO: implement emitEpilogue");
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebAssemblyFrameLowering::determineCalleeSaves(MachineFunction &MF,
|
|
||||||
BitVector &SavedRegs,
|
|
||||||
RegScavenger *RS) const {
|
|
||||||
llvm_unreachable("TODO: implement determineCalleeSaves");
|
|
||||||
}
|
|
||||||
|
@@ -38,9 +38,6 @@ public:
|
|||||||
|
|
||||||
bool hasFP(const MachineFunction &MF) const override;
|
bool hasFP(const MachineFunction &MF) const override;
|
||||||
bool hasReservedCallFrame(const MachineFunction &MF) const override;
|
bool hasReservedCallFrame(const MachineFunction &MF) const override;
|
||||||
|
|
||||||
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
|
|
||||||
RegScavenger *RS = nullptr) const override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
@@ -56,13 +56,49 @@ public:
|
|||||||
|
|
||||||
SDNode *Select(SDNode *Node) override;
|
SDNode *Select(SDNode *Node) override;
|
||||||
|
|
||||||
|
// Include the pieces autogenerated from the target description.
|
||||||
|
#include "WebAssemblyGenDAGISel.inc"
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// add select functions here...
|
// add select functions here...
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
SDNode *WebAssemblyDAGToDAGISel::Select(SDNode *Node) {
|
SDNode *WebAssemblyDAGToDAGISel::Select(SDNode *Node) {
|
||||||
llvm_unreachable("TODO: implement Select");
|
// Dump information about the Node being selected.
|
||||||
|
DEBUG(errs() << "Selecting: ");
|
||||||
|
DEBUG(Node->dump(CurDAG));
|
||||||
|
DEBUG(errs() << "\n");
|
||||||
|
|
||||||
|
// If we have a custom node, we already have selected!
|
||||||
|
if (Node->isMachineOpcode()) {
|
||||||
|
DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
|
||||||
|
Node->setNodeId(-1);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Few custom selection stuff.
|
||||||
|
SDNode *ResNode = nullptr;
|
||||||
|
EVT VT = Node->getValueType(0);
|
||||||
|
|
||||||
|
switch (Node->getOpcode()) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
// FIXME: Implement WebAssembly-specific selection.
|
||||||
|
(void)VT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select the default instruction.
|
||||||
|
ResNode = SelectCode(Node);
|
||||||
|
|
||||||
|
DEBUG(errs() << "=> ");
|
||||||
|
if (ResNode == nullptr || ResNode == Node)
|
||||||
|
DEBUG(Node->dump(CurDAG));
|
||||||
|
else
|
||||||
|
DEBUG(ResNode->dump(CurDAG));
|
||||||
|
DEBUG(errs() << "\n");
|
||||||
|
|
||||||
|
return ResNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This pass converts a legalized DAG into a WebAssembly-specific DAG, ready
|
/// This pass converts a legalized DAG into a WebAssembly-specific DAG, ready
|
||||||
|
@@ -21,6 +21,8 @@
|
|||||||
#include "llvm/CodeGen/Analysis.h"
|
#include "llvm/CodeGen/Analysis.h"
|
||||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
#include "llvm/CodeGen/SelectionDAG.h"
|
#include "llvm/CodeGen/SelectionDAG.h"
|
||||||
|
#include "llvm/IR/DiagnosticInfo.h"
|
||||||
|
#include "llvm/IR/DiagnosticPrinter.h"
|
||||||
#include "llvm/IR/Function.h"
|
#include "llvm/IR/Function.h"
|
||||||
#include "llvm/IR/Intrinsics.h"
|
#include "llvm/IR/Intrinsics.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
@@ -28,10 +30,65 @@
|
|||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include "llvm/Target/TargetOptions.h"
|
#include "llvm/Target/TargetOptions.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
#define DEBUG_TYPE "wasm-lower"
|
#define DEBUG_TYPE "wasm-lower"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// Diagnostic information for unimplemented or unsupported feature reporting.
|
||||||
|
// FIXME copied from BPF and AMDGPU.
|
||||||
|
class DiagnosticInfoUnsupported : public DiagnosticInfo {
|
||||||
|
private:
|
||||||
|
// Debug location where this diagnostic is triggered.
|
||||||
|
DebugLoc DLoc;
|
||||||
|
const Twine &Description;
|
||||||
|
const Function &Fn;
|
||||||
|
SDValue Value;
|
||||||
|
|
||||||
|
static int KindID;
|
||||||
|
|
||||||
|
static int getKindID() {
|
||||||
|
if (KindID == 0)
|
||||||
|
KindID = llvm::getNextAvailablePluginDiagnosticKind();
|
||||||
|
return KindID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
DiagnosticInfoUnsupported(SDLoc DLoc, const Function &Fn, const Twine &Desc,
|
||||||
|
SDValue Value)
|
||||||
|
: DiagnosticInfo(getKindID(), DS_Error), DLoc(DLoc.getDebugLoc()),
|
||||||
|
Description(Desc), Fn(Fn), Value(Value) {}
|
||||||
|
|
||||||
|
void print(DiagnosticPrinter &DP) const override {
|
||||||
|
std::string Str;
|
||||||
|
raw_string_ostream OS(Str);
|
||||||
|
|
||||||
|
if (DLoc) {
|
||||||
|
auto DIL = DLoc.get();
|
||||||
|
StringRef Filename = DIL->getFilename();
|
||||||
|
unsigned Line = DIL->getLine();
|
||||||
|
unsigned Column = DIL->getColumn();
|
||||||
|
OS << Filename << ':' << Line << ':' << Column << ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
OS << "in function " << Fn.getName() << ' ' << *Fn.getFunctionType() << '\n'
|
||||||
|
<< Description;
|
||||||
|
if (Value)
|
||||||
|
Value->print(OS);
|
||||||
|
OS << '\n';
|
||||||
|
OS.flush();
|
||||||
|
DP << Str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool classof(const DiagnosticInfo *DI) {
|
||||||
|
return DI->getKind() == getKindID();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int DiagnosticInfoUnsupported::KindID = 0;
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
WebAssemblyTargetLowering::WebAssemblyTargetLowering(
|
WebAssemblyTargetLowering::WebAssemblyTargetLowering(
|
||||||
const TargetMachine &TM, const WebAssemblySubtarget &STI)
|
const TargetMachine &TM, const WebAssemblySubtarget &STI)
|
||||||
: TargetLowering(TM), Subtarget(&STI) {
|
: TargetLowering(TM), Subtarget(&STI) {
|
||||||
@@ -40,6 +97,18 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
|
|||||||
setHasFloatingPointExceptions(false);
|
setHasFloatingPointExceptions(false);
|
||||||
// We don't know the microarchitecture here, so just reduce register pressure.
|
// We don't know the microarchitecture here, so just reduce register pressure.
|
||||||
setSchedulingPreference(Sched::RegPressure);
|
setSchedulingPreference(Sched::RegPressure);
|
||||||
|
// Tell ISel that we have a stack pointer.
|
||||||
|
setStackPointerRegisterToSaveRestore(
|
||||||
|
Subtarget->hasAddr64() ? WebAssembly::SP64 : WebAssembly::SP32);
|
||||||
|
// Set up the register classes.
|
||||||
|
addRegisterClass(MVT::i32, &WebAssembly::Int32RegClass);
|
||||||
|
addRegisterClass(MVT::i64, &WebAssembly::Int64RegClass);
|
||||||
|
addRegisterClass(MVT::f32, &WebAssembly::Float32RegClass);
|
||||||
|
addRegisterClass(MVT::f64, &WebAssembly::Float64RegClass);
|
||||||
|
// Compute derived properties from the register classes.
|
||||||
|
computeRegisterProperties(Subtarget->getRegisterInfo());
|
||||||
|
|
||||||
|
// FIXME: setOperationAction...
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@@ -50,6 +119,54 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
|
|||||||
// Lowering Code
|
// Lowering Code
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
static void fail(SDLoc DL, SelectionDAG &DAG, const char *msg) {
|
||||||
|
MachineFunction &MF = DAG.getMachineFunction();
|
||||||
|
DAG.getContext()->diagnose(
|
||||||
|
DiagnosticInfoUnsupported(DL, *MF.getFunction(), msg, SDValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebAssemblyTargetLowering::CanLowerReturn(
|
||||||
|
CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
|
||||||
|
const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
|
||||||
|
// WebAssembly can't currently handle returning tuples.
|
||||||
|
return Outs.size() <= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDValue WebAssemblyTargetLowering::LowerReturn(
|
||||||
|
SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
|
||||||
|
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
||||||
|
const SmallVectorImpl<SDValue> &OutVals, SDLoc DL,
|
||||||
|
SelectionDAG &DAG) const {
|
||||||
|
|
||||||
|
assert(Outs.size() <= 1 && "WebAssembly can only return up to one value");
|
||||||
|
if (CallConv != CallingConv::C)
|
||||||
|
fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
|
||||||
|
|
||||||
|
// FIXME: Implement LowerReturn.
|
||||||
|
|
||||||
|
return Chain;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDValue WebAssemblyTargetLowering::LowerFormalArguments(
|
||||||
|
SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
|
||||||
|
const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc DL, SelectionDAG &DAG,
|
||||||
|
SmallVectorImpl<SDValue> &InVals) const {
|
||||||
|
MachineFunction &MF = DAG.getMachineFunction();
|
||||||
|
|
||||||
|
if (CallConv != CallingConv::C)
|
||||||
|
fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
|
||||||
|
if (IsVarArg)
|
||||||
|
fail(DL, DAG, "WebAssembly doesn't support varargs yet");
|
||||||
|
if (MF.getFunction()->hasStructRetAttr())
|
||||||
|
fail(DL, DAG, "WebAssembly doesn't support struct return yet");
|
||||||
|
|
||||||
|
// FIXME: Implement LowerFormalArguments.
|
||||||
|
for (const ISD::InputArg &In : Ins)
|
||||||
|
InVals.push_back(DAG.getNode(ISD::UNDEF, DL, In.VT));
|
||||||
|
|
||||||
|
return Chain;
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Other Lowering Code
|
// Other Lowering Code
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@@ -42,6 +42,22 @@ private:
|
|||||||
/// Keep a pointer to the WebAssemblySubtarget around so that we can make the
|
/// Keep a pointer to the WebAssemblySubtarget around so that we can make the
|
||||||
/// right decision when generating code for different targets.
|
/// right decision when generating code for different targets.
|
||||||
const WebAssemblySubtarget *Subtarget;
|
const WebAssemblySubtarget *Subtarget;
|
||||||
|
|
||||||
|
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
|
||||||
|
bool isVarArg,
|
||||||
|
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
||||||
|
LLVMContext &Context) const override;
|
||||||
|
|
||||||
|
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
|
||||||
|
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
||||||
|
const SmallVectorImpl<SDValue> &OutVals, SDLoc dl,
|
||||||
|
SelectionDAG &DAG) const override;
|
||||||
|
|
||||||
|
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
|
||||||
|
bool IsVarArg,
|
||||||
|
const SmallVectorImpl<ISD::InputArg> &Ins,
|
||||||
|
SDLoc DL, SelectionDAG &DAG,
|
||||||
|
SmallVectorImpl<SDValue> &InVals) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
@@ -24,5 +24,8 @@ using namespace llvm;
|
|||||||
|
|
||||||
#define DEBUG_TYPE "wasm-instr-info"
|
#define DEBUG_TYPE "wasm-instr-info"
|
||||||
|
|
||||||
|
#define GET_INSTRINFO_CTOR_DTOR
|
||||||
|
#include "WebAssemblyGenInstrInfo.inc"
|
||||||
|
|
||||||
WebAssemblyInstrInfo::WebAssemblyInstrInfo(const WebAssemblySubtarget &STI)
|
WebAssemblyInstrInfo::WebAssemblyInstrInfo(const WebAssemblySubtarget &STI)
|
||||||
: RI(STI.getTargetTriple()) {}
|
: RI(STI.getTargetTriple()) {}
|
||||||
|
@@ -19,11 +19,14 @@
|
|||||||
#include "WebAssemblyRegisterInfo.h"
|
#include "WebAssemblyRegisterInfo.h"
|
||||||
#include "llvm/Target/TargetInstrInfo.h"
|
#include "llvm/Target/TargetInstrInfo.h"
|
||||||
|
|
||||||
|
#define GET_INSTRINFO_HEADER
|
||||||
|
#include "WebAssemblyGenInstrInfo.inc"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
class WebAssemblySubtarget;
|
class WebAssemblySubtarget;
|
||||||
|
|
||||||
class WebAssemblyInstrInfo final {
|
class WebAssemblyInstrInfo final : public WebAssemblyGenInstrInfo {
|
||||||
const WebAssemblyRegisterInfo RI;
|
const WebAssemblyRegisterInfo RI;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@@ -61,6 +61,12 @@ public:
|
|||||||
const WebAssemblyTargetLowering *getTargetLowering() const override {
|
const WebAssemblyTargetLowering *getTargetLowering() const override {
|
||||||
return &TLInfo;
|
return &TLInfo;
|
||||||
}
|
}
|
||||||
|
const WebAssemblyInstrInfo *getInstrInfo() const override {
|
||||||
|
return &InstrInfo;
|
||||||
|
}
|
||||||
|
const WebAssemblyRegisterInfo *getRegisterInfo() const override {
|
||||||
|
return &getInstrInfo()->getRegisterInfo();
|
||||||
|
}
|
||||||
const Triple &getTargetTriple() const { return TargetTriple; }
|
const Triple &getTargetTriple() const { return TargetTriple; }
|
||||||
bool enableMachineScheduler() const override;
|
bool enableMachineScheduler() const override;
|
||||||
bool useAA() const override { return true; }
|
bool useAA() const override { return true; }
|
||||||
|
10
test/CodeGen/WebAssembly/integer.ll
Normal file
10
test/CodeGen/WebAssembly/integer.ll
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
; RUN: llc < %s -asm-verbose=false | FileCheck %s
|
||||||
|
|
||||||
|
target datalayout = "e-p:32:32-i64:64-v128:8:128-n32:64-S128"
|
||||||
|
target triple = "wasm32-unknown-unknown"
|
||||||
|
|
||||||
|
; CHECK-LABEL: add32:
|
||||||
|
define i32 @add32(i32 %x, i32 %y) {
|
||||||
|
%a = add i32 %x, %y
|
||||||
|
ret i32 %a
|
||||||
|
}
|
Reference in New Issue
Block a user