mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-09 10:31:14 +00:00
Added initial support for small sections on Mips.
Added gp_rel relocations to support addressing small section contents. Added command line to specify small section threshold in bytes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@53869 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6116a73da4
commit
91fd532eb9
@ -360,7 +360,11 @@ printOperand(const MachineInstr *MI, int opNum)
|
|||||||
closeP = true;
|
closeP = true;
|
||||||
} else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isRegister()
|
} else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isRegister()
|
||||||
&& !MO.isImmediate()) {
|
&& !MO.isImmediate()) {
|
||||||
O << "%lo(";
|
const MachineOperand &firstMO = MI->getOperand(opNum-1);
|
||||||
|
if (firstMO.getReg() == Mips::GP)
|
||||||
|
O << "%gp_rel(";
|
||||||
|
else
|
||||||
|
O << "%lo(";
|
||||||
closeP = true;
|
closeP = true;
|
||||||
} else if ((isPIC) && (MI->getOpcode() == Mips::LW)
|
} else if ((isPIC) && (MI->getOpcode() == Mips::LW)
|
||||||
&& (!MO.isRegister()) && (!MO.isImmediate())) {
|
&& (!MO.isRegister()) && (!MO.isImmediate())) {
|
||||||
@ -490,14 +494,13 @@ printModuleLevelGV(const GlobalVariable* GVar) {
|
|||||||
Constant *C = GVar->getInitializer();
|
Constant *C = GVar->getInitializer();
|
||||||
const Type *CTy = C->getType();
|
const Type *CTy = C->getType();
|
||||||
unsigned Size = TD->getABITypeSize(CTy);
|
unsigned Size = TD->getABITypeSize(CTy);
|
||||||
|
const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
|
||||||
bool printSizeAndType = true;
|
bool printSizeAndType = true;
|
||||||
|
|
||||||
// A data structure or array is aligned in memory to the largest
|
// A data structure or array is aligned in memory to the largest
|
||||||
// alignment boundary required by any data type inside it (this matches
|
// alignment boundary required by any data type inside it (this matches
|
||||||
// the Preferred Type Alignment). For integral types, the alignment is
|
// the Preferred Type Alignment). For integral types, the alignment is
|
||||||
// the type size.
|
// the type size.
|
||||||
//unsigned Align = TD->getPreferredAlignmentLog(I);
|
|
||||||
//unsigned Align = TD->getPrefTypeAlignment(C->getType());
|
|
||||||
unsigned Align;
|
unsigned Align;
|
||||||
if (CTy->getTypeID() == Type::IntegerTyID ||
|
if (CTy->getTypeID() == Type::IntegerTyID ||
|
||||||
CTy->getTypeID() == Type::VoidTyID) {
|
CTy->getTypeID() == Type::VoidTyID) {
|
||||||
@ -546,6 +549,8 @@ printModuleLevelGV(const GlobalVariable* GVar) {
|
|||||||
O << TAI->getGlobalDirective() << name << '\n';
|
O << TAI->getGlobalDirective() << name << '\n';
|
||||||
// Fall Through
|
// Fall Through
|
||||||
case GlobalValue::InternalLinkage:
|
case GlobalValue::InternalLinkage:
|
||||||
|
if (CVA && CVA->isCString())
|
||||||
|
printSizeAndType = false;
|
||||||
break;
|
break;
|
||||||
case GlobalValue::GhostLinkage:
|
case GlobalValue::GhostLinkage:
|
||||||
cerr << "Should not have any unmaterialized functions!\n";
|
cerr << "Should not have any unmaterialized functions!\n";
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "MipsSubtarget.h"
|
#include "MipsSubtarget.h"
|
||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
#include "llvm/Function.h"
|
#include "llvm/Function.h"
|
||||||
|
#include "llvm/GlobalVariable.h"
|
||||||
#include "llvm/Intrinsics.h"
|
#include "llvm/Intrinsics.h"
|
||||||
#include "llvm/CallingConv.h"
|
#include "llvm/CallingConv.h"
|
||||||
#include "llvm/CodeGen/CallingConvLower.h"
|
#include "llvm/CodeGen/CallingConvLower.h"
|
||||||
@ -43,6 +44,7 @@ getTargetNodeName(unsigned Opcode) const
|
|||||||
case MipsISD::JmpLink : return "MipsISD::JmpLink";
|
case MipsISD::JmpLink : return "MipsISD::JmpLink";
|
||||||
case MipsISD::Hi : return "MipsISD::Hi";
|
case MipsISD::Hi : return "MipsISD::Hi";
|
||||||
case MipsISD::Lo : return "MipsISD::Lo";
|
case MipsISD::Lo : return "MipsISD::Lo";
|
||||||
|
case MipsISD::GPRel : return "MipsISD::GPRel";
|
||||||
case MipsISD::Ret : return "MipsISD::Ret";
|
case MipsISD::Ret : return "MipsISD::Ret";
|
||||||
case MipsISD::SelectCC : return "MipsISD::SelectCC";
|
case MipsISD::SelectCC : return "MipsISD::SelectCC";
|
||||||
case MipsISD::FPBrcond : return "MipsISD::FPBrcond";
|
case MipsISD::FPBrcond : return "MipsISD::FPBrcond";
|
||||||
@ -89,8 +91,6 @@ MipsTargetLowering(MipsTargetMachine &TM): TargetLowering(TM)
|
|||||||
setOperationAction(ISD::SELECT_CC, MVT::f32, Custom);
|
setOperationAction(ISD::SELECT_CC, MVT::f32, Custom);
|
||||||
|
|
||||||
// Operations not directly supported by Mips.
|
// Operations not directly supported by Mips.
|
||||||
setConvertAction(MVT::f64, MVT::f32, Expand);
|
|
||||||
|
|
||||||
setOperationAction(ISD::BR_JT, MVT::Other, Expand);
|
setOperationAction(ISD::BR_JT, MVT::Other, Expand);
|
||||||
setOperationAction(ISD::BR_CC, MVT::Other, Expand);
|
setOperationAction(ISD::BR_CC, MVT::Other, Expand);
|
||||||
setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
|
setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
|
||||||
@ -234,34 +234,71 @@ AddLiveIn(MachineFunction &MF, unsigned PReg, TargetRegisterClass *RC)
|
|||||||
return VReg;
|
return VReg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Discover if this global address can be placed into small data/bss section.
|
||||||
|
// This should happen for globals with size less than small section size
|
||||||
|
// threshold in no abicall environments. Data in this section must be addressed
|
||||||
|
// using gp_rel operator.
|
||||||
|
bool MipsTargetLowering::IsGlobalInSmallSection(GlobalValue *GV)
|
||||||
|
{
|
||||||
|
const TargetData *TD = getTargetData();
|
||||||
|
const Value *V = dyn_cast<Value>(GV);
|
||||||
|
const GlobalVariable *GVA = dyn_cast<GlobalVariable>(V);
|
||||||
|
|
||||||
|
//const PointerType *PTy = GV->getType();
|
||||||
|
const Type *Ty = GV->getType()->getElementType();
|
||||||
|
unsigned Size = TD->getABITypeSize(Ty);
|
||||||
|
|
||||||
|
// if this is a internal constant string, there is a special
|
||||||
|
// section for it, but not in small data/bss.
|
||||||
|
if (GVA->hasInitializer() && GV->hasInternalLinkage()) {
|
||||||
|
Constant *C = GVA->getInitializer();
|
||||||
|
const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
|
||||||
|
if (CVA && CVA->isCString())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Size > 0 && (Size <= Subtarget->getSSectionThreshold()))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Misc Lower Operation implementation
|
// Misc Lower Operation implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
SDOperand MipsTargetLowering::
|
SDOperand MipsTargetLowering::
|
||||||
LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG)
|
LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG)
|
||||||
{
|
{
|
||||||
SDOperand ResNode;
|
|
||||||
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
|
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
|
||||||
SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32);
|
SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32);
|
||||||
bool isPIC = (getTargetMachine().getRelocationModel() == Reloc::PIC_);
|
|
||||||
|
|
||||||
SDOperand HiPart;
|
if (!Subtarget->hasABICall()) {
|
||||||
if (!isPIC) {
|
if (isa<Function>(GV)) return GA;
|
||||||
const MVT *VTs = DAG.getNodeValueTypes(MVT::i32);
|
const MVT *VTs = DAG.getNodeValueTypes(MVT::i32);
|
||||||
SDOperand Ops[] = { GA };
|
SDOperand Ops[] = { GA };
|
||||||
HiPart = DAG.getNode(MipsISD::Hi, VTs, 1, Ops, 1);
|
|
||||||
} else // Emit Load from Global Pointer
|
|
||||||
HiPart = DAG.getLoad(MVT::i32, DAG.getEntryNode(), GA, NULL, 0);
|
|
||||||
|
|
||||||
// On functions and global targets not internal linked only
|
if (IsGlobalInSmallSection(GV)) { // %gp_rel relocation
|
||||||
// a load from got/GP is necessary for PIC to work.
|
SDOperand GPRelNode = DAG.getNode(MipsISD::GPRel, VTs, 1, Ops, 1);
|
||||||
if ((isPIC) && ((!GV->hasInternalLinkage()) || (isa<Function>(GV))))
|
SDOperand GOT = DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i32);
|
||||||
return HiPart;
|
return DAG.getNode(ISD::ADD, MVT::i32, GOT, GPRelNode);
|
||||||
|
}
|
||||||
|
// %hi/%lo relocation
|
||||||
|
SDOperand HiPart = DAG.getNode(MipsISD::Hi, VTs, 1, Ops, 1);
|
||||||
|
SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA);
|
||||||
|
return DAG.getNode(ISD::ADD, MVT::i32, HiPart, Lo);
|
||||||
|
|
||||||
SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA);
|
} else { // Abicall relocations, TODO: make this cleaner.
|
||||||
ResNode = DAG.getNode(ISD::ADD, MVT::i32, HiPart, Lo);
|
SDOperand ResNode = DAG.getLoad(MVT::i32, DAG.getEntryNode(), GA, NULL, 0);
|
||||||
|
// On functions and global targets not internal linked only
|
||||||
|
// a load from got/GP is necessary for PIC to work.
|
||||||
|
if (!GV->hasInternalLinkage() || isa<Function>(GV))
|
||||||
|
return ResNode;
|
||||||
|
SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA);
|
||||||
|
return DAG.getNode(ISD::ADD, MVT::i32, ResNode, Lo);
|
||||||
|
}
|
||||||
|
|
||||||
return ResNode;
|
assert(0 && "Dont know how to handle GlobalAddress");
|
||||||
|
return SDOperand(0,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDOperand MipsTargetLowering::
|
SDOperand MipsTargetLowering::
|
||||||
@ -596,9 +633,8 @@ LowerCCCArguments(SDOperand Op, SelectionDAG &DAG)
|
|||||||
|
|
||||||
unsigned StackReg = MF.getTarget().getRegisterInfo()->getFrameRegister(MF);
|
unsigned StackReg = MF.getTarget().getRegisterInfo()->getFrameRegister(MF);
|
||||||
|
|
||||||
// GP holds the GOT address on PIC calls.
|
// GP must be live into PIC and non-PIC call target.
|
||||||
if (getTargetMachine().getRelocationModel() == Reloc::PIC_)
|
AddLiveIn(MF, Mips::GP, Mips::CPURegsRegisterClass);
|
||||||
AddLiveIn(MF, Mips::GP, Mips::CPURegsRegisterClass);
|
|
||||||
|
|
||||||
// Assign locations to all of the incoming arguments.
|
// Assign locations to all of the incoming arguments.
|
||||||
SmallVector<CCValAssign, 16> ArgLocs;
|
SmallVector<CCValAssign, 16> ArgLocs;
|
||||||
|
@ -37,6 +37,9 @@ namespace llvm {
|
|||||||
// No relation with Mips Lo register
|
// No relation with Mips Lo register
|
||||||
Lo,
|
Lo,
|
||||||
|
|
||||||
|
// Handle gp_rel (small data/bss sections) relocation.
|
||||||
|
GPRel,
|
||||||
|
|
||||||
// Select CC Pseudo Instruction
|
// Select CC Pseudo Instruction
|
||||||
SelectCC,
|
SelectCC,
|
||||||
|
|
||||||
@ -83,7 +86,7 @@ namespace llvm {
|
|||||||
SDOperand LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC);
|
SDOperand LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC);
|
||||||
SDNode *LowerCallResult(SDOperand Chain, SDOperand InFlag, SDNode*TheCall,
|
SDNode *LowerCallResult(SDOperand Chain, SDOperand InFlag, SDNode*TheCall,
|
||||||
unsigned CallingConv, SelectionDAG &DAG);
|
unsigned CallingConv, SelectionDAG &DAG);
|
||||||
SDOperand getReturnAddressFrameIndex(SelectionDAG &DAG);
|
bool IsGlobalInSmallSection(GlobalValue *GV);
|
||||||
|
|
||||||
// Lower Operand specifics
|
// Lower Operand specifics
|
||||||
SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG);
|
SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG);
|
||||||
|
@ -31,9 +31,9 @@ def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain,
|
|||||||
// Hi and Lo nodes are used to handle global addresses. Used on
|
// Hi and Lo nodes are used to handle global addresses. Used on
|
||||||
// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol
|
// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol
|
||||||
// static model. (nothing to do with Mips Registers Hi and Lo)
|
// static model. (nothing to do with Mips Registers Hi and Lo)
|
||||||
//def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp, [SDNPOutFlag]>;
|
def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp>;
|
||||||
def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp>;
|
def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>;
|
||||||
def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>;
|
def MipsGPRel : SDNode<"MipsISD::GPRel", SDTIntUnaryOp>;
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
def MipsRet : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain,
|
def MipsRet : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain,
|
||||||
@ -555,13 +555,15 @@ def : Pat<(MipsJmpLink CPURegs:$dst),
|
|||||||
|
|
||||||
// GlobalAddress, Constant Pool, ExternalSymbol, and JumpTable
|
// GlobalAddress, Constant Pool, ExternalSymbol, and JumpTable
|
||||||
def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>;
|
def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>;
|
||||||
def : Pat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>;
|
//def : Pat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>;
|
||||||
def : Pat<(add CPURegs:$hi, (MipsLo tglobaladdr:$lo)),
|
def : Pat<(add CPURegs:$hi, (MipsLo tglobaladdr:$lo)),
|
||||||
(ADDiu CPURegs:$hi, tglobaladdr:$lo)>;
|
(ADDiu CPURegs:$hi, tglobaladdr:$lo)>;
|
||||||
def : Pat<(MipsHi tjumptable:$in), (LUi tjumptable:$in)>;
|
def : Pat<(MipsHi tjumptable:$in), (LUi tjumptable:$in)>;
|
||||||
def : Pat<(MipsLo tjumptable:$in), (ADDiu ZERO, tjumptable:$in)>;
|
//def : Pat<(MipsLo tjumptable:$in), (ADDiu ZERO, tjumptable:$in)>;
|
||||||
def : Pat<(add CPURegs:$hi, (MipsLo tjumptable:$lo)),
|
def : Pat<(add CPURegs:$hi, (MipsLo tjumptable:$lo)),
|
||||||
(ADDiu CPURegs:$hi, tjumptable:$lo)>;
|
(ADDiu CPURegs:$hi, tjumptable:$lo)>;
|
||||||
|
def : Pat<(add CPURegs:$gp, (MipsGPRel tglobaladdr:$in)),
|
||||||
|
(ADDiu CPURegs:$gp, tglobaladdr:$in)>;
|
||||||
|
|
||||||
// Mips does not have "not", so we expand our way
|
// Mips does not have "not", so we expand our way
|
||||||
def : Pat<(not CPURegs:$in),
|
def : Pat<(not CPURegs:$in),
|
||||||
|
@ -22,6 +22,9 @@ cl::opt<bool> NotABICall("disable-mips-abicall", cl::Hidden,
|
|||||||
cl::desc("Disable code for SVR4-style dynamic objects"));
|
cl::desc("Disable code for SVR4-style dynamic objects"));
|
||||||
cl::opt<bool> AbsoluteCall("enable-mips-absolute-call", cl::Hidden,
|
cl::opt<bool> AbsoluteCall("enable-mips-absolute-call", cl::Hidden,
|
||||||
cl::desc("Enable absolute call within abicall"));
|
cl::desc("Enable absolute call within abicall"));
|
||||||
|
cl::opt<unsigned> SSThreshold("mips-ssection-threshold", cl::Hidden,
|
||||||
|
cl::desc("Small data and bss section threshold size (default=8)"),
|
||||||
|
cl::init(8));
|
||||||
|
|
||||||
MipsSubtarget::MipsSubtarget(const TargetMachine &TM, const Module &M,
|
MipsSubtarget::MipsSubtarget(const TargetMachine &TM, const Module &M,
|
||||||
const std::string &FS, bool little) :
|
const std::string &FS, bool little) :
|
||||||
@ -35,6 +38,9 @@ MipsSubtarget::MipsSubtarget(const TargetMachine &TM, const Module &M,
|
|||||||
ParseSubtargetFeatures(FS, CPU);
|
ParseSubtargetFeatures(FS, CPU);
|
||||||
const std::string& TT = M.getTargetTriple();
|
const std::string& TT = M.getTargetTriple();
|
||||||
|
|
||||||
|
// Small section size threshold
|
||||||
|
SSectionThreshold = SSThreshold;
|
||||||
|
|
||||||
// Is the target system Linux ?
|
// Is the target system Linux ?
|
||||||
if (TT.find("linux") == std::string::npos)
|
if (TT.find("linux") == std::string::npos)
|
||||||
IsLinux = false;
|
IsLinux = false;
|
||||||
|
@ -71,6 +71,10 @@ protected:
|
|||||||
// isLinux - Target system is Linux. Is false we consider ELFOS for now.
|
// isLinux - Target system is Linux. Is false we consider ELFOS for now.
|
||||||
bool IsLinux;
|
bool IsLinux;
|
||||||
|
|
||||||
|
// Put global and static items less than or equal to SSectionThreshold
|
||||||
|
// bytes into the small data or bss section. The default is 8.
|
||||||
|
unsigned SSectionThreshold;
|
||||||
|
|
||||||
InstrItineraryData InstrItins;
|
InstrItineraryData InstrItins;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -102,6 +106,7 @@ public:
|
|||||||
bool hasABICall() const { return HasABICall; };
|
bool hasABICall() const { return HasABICall; };
|
||||||
bool hasAbsoluteCall() const { return HasAbsoluteCall; };
|
bool hasAbsoluteCall() const { return HasAbsoluteCall; };
|
||||||
bool isLinux() const { return IsLinux; };
|
bool isLinux() const { return IsLinux; };
|
||||||
|
unsigned getSSectionThreshold() const { return SSectionThreshold; }
|
||||||
|
|
||||||
};
|
};
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
@ -31,6 +31,7 @@ MipsTargetAsmInfo::MipsTargetAsmInfo(const MipsTargetMachine &TM):
|
|||||||
ZeroDirective = "\t.space\t";
|
ZeroDirective = "\t.space\t";
|
||||||
BSSSection = "\t.section\t.bss";
|
BSSSection = "\t.section\t.bss";
|
||||||
LCOMMDirective = "\t.lcomm\t";
|
LCOMMDirective = "\t.lcomm\t";
|
||||||
|
CStringSection = ".rodata.str";
|
||||||
|
|
||||||
if (!TM.getSubtarget<MipsSubtarget>().hasABICall())
|
if (!TM.getSubtarget<MipsSubtarget>().hasABICall())
|
||||||
JumpTableDirective = "\t.word\t";
|
JumpTableDirective = "\t.word\t";
|
||||||
|
Loading…
Reference in New Issue
Block a user