243 lines
8.2 KiB
C++
243 lines
8.2 KiB
C++
//===-- WDC65816ISelLowering.cpp - WDC65816 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 interfaces that WDC65816 uses to lower LLVM code into a
|
|
// selection DAG.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "WDC65816ISelLowering.h"
|
|
#include "WDC65816MachineFunctionInfo.h"
|
|
#include "WDC65816RegisterInfo.h"
|
|
#include "WDC65816TargetMachine.h"
|
|
#include "WDC65816TargetObjectFile.h"
|
|
#include "MCTargetDesc/WDC65816BaseInfo.h"
|
|
#include "llvm/CodeGen/CallingConvLower.h"
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
#include "llvm/CodeGen/SelectionDAG.h"
|
|
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
using namespace llvm;
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Calling Convention Implementation
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "WDC65816GenCallingConv.inc"
|
|
|
|
|
|
SDValue WDC65816TargetLowering::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();
|
|
|
|
// Assign locations to all of the incoming arguments.
|
|
SmallVector<CCValAssign, 16> ArgLocs;
|
|
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
|
|
getTargetMachine(), ArgLocs, *DAG.getContext());
|
|
CCInfo.AnalyzeFormalArguments(Ins, CC_WDC);
|
|
|
|
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
|
|
CCValAssign &VA = ArgLocs[i];
|
|
|
|
if (i == 0 && Ins[i].Flags.isSRet()) {
|
|
WDC_LOG("WDC_TODO - Write code for returning a structure as a hidden input arg pointer");
|
|
continue;
|
|
}
|
|
|
|
if (VA.isRegLoc()) {
|
|
if (VA.needsCustom()) {
|
|
WDC_LOG("WDC_TODO - needsCustom() in register location!");
|
|
continue;
|
|
}
|
|
WDC_LOG("WDC_TODO - Write code for register location");
|
|
continue;
|
|
}
|
|
|
|
assert(VA.isMemLoc());
|
|
|
|
unsigned Offset = VA.getLocMemOffset();
|
|
|
|
if (VA.needsCustom()) {
|
|
WDC_LOG("WDC_TODO - needsCustom() in memory location, offset=" << Offset);
|
|
continue;
|
|
}
|
|
|
|
WDC_LOG("WDC_TODO - Write code for memory location, offset=" << Offset);
|
|
}
|
|
|
|
if (MF.getFunction()->hasStructRetAttr()) {
|
|
WDC_LOG("WDC_TODO - Write code for hasStructRetAttr()");
|
|
}
|
|
|
|
if (isVarArg) {
|
|
WDC_LOG("WDC_TODO - Write code for isVarArg");
|
|
}
|
|
|
|
return Chain;
|
|
}
|
|
|
|
|
|
SDValue
|
|
WDC65816TargetLowering::LowerReturn(SDValue Chain,
|
|
CallingConv::ID CallConv, bool IsVarArg,
|
|
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
|
const SmallVectorImpl<SDValue> &OutVals,
|
|
SDLoc DL, SelectionDAG &DAG) const {
|
|
MachineFunction &MF = DAG.getMachineFunction();
|
|
|
|
// CCValAssign - represent the assignment of the return value to locations.
|
|
SmallVector<CCValAssign, 16> RVLocs;
|
|
|
|
// CCState - Info about the registers and stack slot.
|
|
CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(),
|
|
DAG.getTarget(), RVLocs, *DAG.getContext());
|
|
|
|
// Analyze return values.
|
|
CCInfo.AnalyzeReturn(Outs, RetCC_WDC);
|
|
|
|
SDValue Flag;
|
|
SmallVector<SDValue, 4> RetOps(1, Chain);
|
|
|
|
// Copy the result values into the output registers.
|
|
for (unsigned i = 0; i != RVLocs.size(); ++i) {
|
|
CCValAssign &VA = RVLocs[i];
|
|
assert(VA.isRegLoc() && "Can only return in registers!");
|
|
|
|
Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(),
|
|
OutVals[i], Flag);
|
|
|
|
// Guarantee that all emitted copies are stuck together with flags.
|
|
Flag = Chain.getValue(1);
|
|
RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
|
|
}
|
|
|
|
if (MF.getFunction()->hasStructRetAttr()) {
|
|
WDC_LOG("WDC_TODO - Need to implement hasStructRetAttr() case");
|
|
}
|
|
|
|
RetOps[0] = Chain; // Update chain.
|
|
|
|
// Add the flag if we have it.
|
|
if (Flag.getNode())
|
|
RetOps.push_back(Flag);
|
|
|
|
return DAG.getNode(WDCISD::RET_FLAG, DL, MVT::Other,
|
|
&RetOps[0], RetOps.size());
|
|
}
|
|
|
|
|
|
SDValue WDC65816TargetLowering::LowerGlobalAddress(SDValue Op,
|
|
SelectionDAG &DAG) const
|
|
{
|
|
const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
|
|
int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset();
|
|
|
|
// Create the TargetGlobalAddress node, folding in the constant offset.
|
|
SDValue Result = DAG.getTargetGlobalAddress(GV, SDLoc(Op),
|
|
getPointerTy(), Offset);
|
|
return DAG.getNode(WDCISD::Wrapper, SDLoc(Op),
|
|
getPointerTy(), Result);
|
|
}
|
|
|
|
|
|
WDC65816TargetLowering::WDC65816TargetLowering(TargetMachine &TM)
|
|
: TargetLowering(TM, new WDC65816TargetObjectFile()) {
|
|
|
|
addRegisterClass(MVT::i16, &WDC::AccRegsRegClass);
|
|
addRegisterClass(MVT::i16, &WDC::IndexXRegsRegClass);
|
|
addRegisterClass(MVT::i16, &WDC::IndexYRegsRegClass);
|
|
addRegisterClass(MVT::i16, &WDC::Int16RegsRegClass);
|
|
addRegisterClass(MVT::i32, &WDC::Int32RegsRegClass);
|
|
addRegisterClass(MVT::i64, &WDC::Int64RegsRegClass);
|
|
addRegisterClass(MVT::f32, &WDC::Float32RegsRegClass);
|
|
addRegisterClass(MVT::f64, &WDC::Float64RegsRegClass);
|
|
|
|
computeRegisterProperties();
|
|
|
|
// Division is expensive
|
|
setIntDivIsCheap(false);
|
|
|
|
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
|
|
}
|
|
|
|
const char *WDC65816TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|
switch (Opcode) {
|
|
default: return 0;
|
|
case WDCISD::RET_FLAG: return "WDCSD::RET_FLAG";
|
|
case WDCISD::Wrapper: return "WDCISD::Wrapper";
|
|
}
|
|
}
|
|
|
|
|
|
|
|
SDValue WDC65816TargetLowering::
|
|
LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
|
switch (Op.getOpcode()) {
|
|
default: llvm_unreachable("Should not custom lower this!");
|
|
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
WDC65816TargetLowering::LowerOperationWrapper(SDNode *N,
|
|
SmallVectorImpl<SDValue> &Results,
|
|
SelectionDAG &DAG) const {
|
|
SDValue Res = LowerOperation(SDValue(N, 0), DAG);
|
|
|
|
for (unsigned I = 0, E = Res->getNumValues(); I != E; ++I)
|
|
Results.push_back(Res.getValue(I));
|
|
}
|
|
|
|
void
|
|
WDC65816TargetLowering::ReplaceNodeResults(SDNode *N,
|
|
SmallVectorImpl<SDValue> &Results,
|
|
SelectionDAG &DAG) const {
|
|
return LowerOperationWrapper(N, Results, DAG);
|
|
}
|
|
|
|
|
|
// Pin WDC65816Section's and WDC65816TargetObjectFile's vtables to this file.
|
|
void WDC65816Section::anchor() {}
|
|
|
|
WDC65816TargetObjectFile::~WDC65816TargetObjectFile() {
|
|
delete TextSection;
|
|
delete DataSection;
|
|
delete BSSSection;
|
|
delete ReadOnlySection;
|
|
|
|
delete StaticCtorSection;
|
|
delete StaticDtorSection;
|
|
delete LSDASection;
|
|
delete EHFrameSection;
|
|
delete DwarfAbbrevSection;
|
|
delete DwarfInfoSection;
|
|
delete DwarfLineSection;
|
|
delete DwarfFrameSection;
|
|
delete DwarfPubTypesSection;
|
|
delete DwarfDebugInlineSection;
|
|
delete DwarfStrSection;
|
|
delete DwarfLocSection;
|
|
delete DwarfARangesSection;
|
|
delete DwarfRangesSection;
|
|
delete DwarfMacroInfoSection;
|
|
}
|