mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-09-07 01:54:50 +00:00
value type, so there is no point in passing it around using an EVT. Use the simpler MVT everywhere. Rather than trying to propagate this information maximally in all the code that using the calling convention stuff, I chose to do a mainly low impact change instead. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118167 91177308-0d34-0410-b5e6-96231b3b80d8
191 lines
6.4 KiB
C++
191 lines
6.4 KiB
C++
//===-- PTXISelLowering.cpp - PTX DAG Lowering Implementation -------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the PTXTargetLowering class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "PTX.h"
|
|
#include "PTXISelLowering.h"
|
|
#include "PTXRegisterInfo.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
#include "llvm/CodeGen/SelectionDAG.h"
|
|
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
|
|
|
|
using namespace llvm;
|
|
|
|
PTXTargetLowering::PTXTargetLowering(TargetMachine &TM)
|
|
: TargetLowering(TM, new TargetLoweringObjectFileELF()) {
|
|
// Set up the register classes.
|
|
addRegisterClass(MVT::i1, PTX::PredsRegisterClass);
|
|
addRegisterClass(MVT::i32, PTX::RRegs32RegisterClass);
|
|
|
|
// Compute derived properties from the register classes
|
|
computeRegisterProperties();
|
|
}
|
|
|
|
const char *PTXTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|
switch (Opcode) {
|
|
default: llvm_unreachable("Unknown opcode");
|
|
case PTXISD::EXIT: return "PTXISD::EXIT";
|
|
case PTXISD::RET: return "PTXISD::RET";
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Calling Convention Implementation
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace {
|
|
struct argmap_entry {
|
|
MVT::SimpleValueType VT;
|
|
TargetRegisterClass *RC;
|
|
TargetRegisterClass::iterator loc;
|
|
|
|
argmap_entry(MVT::SimpleValueType _VT, TargetRegisterClass *_RC)
|
|
: VT(_VT), RC(_RC), loc(_RC->begin()) {}
|
|
|
|
void reset() { loc = RC->begin(); }
|
|
bool operator==(MVT::SimpleValueType _VT) const { return VT == _VT; }
|
|
} argmap[] = {
|
|
argmap_entry(MVT::i1, PTX::PredsRegisterClass),
|
|
argmap_entry(MVT::i32, PTX::RRegs32RegisterClass)
|
|
};
|
|
} // end anonymous namespace
|
|
|
|
static SDValue lower_kernel_argument(int i,
|
|
SDValue Chain,
|
|
DebugLoc dl,
|
|
MVT::SimpleValueType VT,
|
|
argmap_entry *entry,
|
|
SelectionDAG &DAG,
|
|
unsigned *argreg) {
|
|
// TODO
|
|
llvm_unreachable("Not implemented yet");
|
|
}
|
|
|
|
static SDValue lower_device_argument(int i,
|
|
SDValue Chain,
|
|
DebugLoc dl,
|
|
MVT::SimpleValueType VT,
|
|
argmap_entry *entry,
|
|
SelectionDAG &DAG,
|
|
unsigned *argreg) {
|
|
MachineRegisterInfo &RegInfo = DAG.getMachineFunction().getRegInfo();
|
|
|
|
unsigned preg = *++(entry->loc); // allocate start from register 1
|
|
unsigned vreg = RegInfo.createVirtualRegister(entry->RC);
|
|
RegInfo.addLiveIn(preg, vreg);
|
|
|
|
*argreg = preg;
|
|
return DAG.getCopyFromReg(Chain, dl, vreg, VT);
|
|
}
|
|
|
|
typedef SDValue (*lower_argument_func)(int i,
|
|
SDValue Chain,
|
|
DebugLoc dl,
|
|
MVT::SimpleValueType VT,
|
|
argmap_entry *entry,
|
|
SelectionDAG &DAG,
|
|
unsigned *argreg);
|
|
|
|
SDValue PTXTargetLowering::
|
|
LowerFormalArguments(SDValue Chain,
|
|
CallingConv::ID CallConv,
|
|
bool isVarArg,
|
|
const SmallVectorImpl<ISD::InputArg> &Ins,
|
|
DebugLoc dl,
|
|
SelectionDAG &DAG,
|
|
SmallVectorImpl<SDValue> &InVals) const {
|
|
if (isVarArg) llvm_unreachable("PTX does not support varargs");
|
|
|
|
lower_argument_func lower_argument;
|
|
|
|
switch (CallConv) {
|
|
default:
|
|
llvm_unreachable("Unsupported calling convention");
|
|
break;
|
|
case CallingConv::PTX_Kernel:
|
|
lower_argument = lower_kernel_argument;
|
|
break;
|
|
case CallingConv::PTX_Device:
|
|
lower_argument = lower_device_argument;
|
|
break;
|
|
}
|
|
|
|
// Reset argmap before allocation
|
|
for (struct argmap_entry *i = argmap, *e = argmap + array_lengthof(argmap);
|
|
i != e; ++ i)
|
|
i->reset();
|
|
|
|
for (int i = 0, e = Ins.size(); i != e; ++ i) {
|
|
MVT::SimpleValueType VT = Ins[i].VT.SimpleTy;
|
|
|
|
struct argmap_entry *entry = std::find(argmap,
|
|
argmap + array_lengthof(argmap), VT);
|
|
if (entry == argmap + array_lengthof(argmap))
|
|
llvm_unreachable("Type of argument is not supported");
|
|
|
|
unsigned reg;
|
|
SDValue arg = lower_argument(i, Chain, dl, VT, entry, DAG, ®);
|
|
InVals.push_back(arg);
|
|
}
|
|
|
|
return Chain;
|
|
}
|
|
|
|
SDValue PTXTargetLowering::
|
|
LowerReturn(SDValue Chain,
|
|
CallingConv::ID CallConv,
|
|
bool isVarArg,
|
|
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
|
const SmallVectorImpl<SDValue> &OutVals,
|
|
DebugLoc dl,
|
|
SelectionDAG &DAG) const {
|
|
if (isVarArg) llvm_unreachable("PTX does not support varargs");
|
|
|
|
switch (CallConv) {
|
|
default:
|
|
llvm_unreachable("Unsupported calling convention.");
|
|
case CallingConv::PTX_Kernel:
|
|
assert(Outs.size() == 0 && "Kernel must return void.");
|
|
return DAG.getNode(PTXISD::EXIT, dl, MVT::Other, Chain);
|
|
case CallingConv::PTX_Device:
|
|
assert(Outs.size() <= 1 && "Can at most return one value.");
|
|
break;
|
|
}
|
|
|
|
// PTX_Device
|
|
|
|
// return void
|
|
if (Outs.size() == 0)
|
|
return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain);
|
|
|
|
assert(Outs[0].VT == MVT::i32 && "Can return only basic types");
|
|
|
|
SDValue Flag;
|
|
unsigned reg = PTX::R0;
|
|
|
|
// If this is the first return lowered for this function, add the regs to the
|
|
// liveout set for the function
|
|
if (DAG.getMachineFunction().getRegInfo().liveout_empty())
|
|
DAG.getMachineFunction().getRegInfo().addLiveOut(reg);
|
|
|
|
// Copy the result values into the output registers
|
|
Chain = DAG.getCopyToReg(Chain, dl, reg, OutVals[0], Flag);
|
|
|
|
// Guarantee that all emitted copies are stuck together,
|
|
// avoiding something bad
|
|
Flag = Chain.getValue(1);
|
|
|
|
return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain, Flag);
|
|
}
|