mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-11-14 14:18:32 +00:00
Implement 'large' PIC model
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@76006 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -50,6 +50,7 @@ namespace {
|
|||||||
|
|
||||||
void printOperand(const MachineInstr *MI, int OpNum,
|
void printOperand(const MachineInstr *MI, int OpNum,
|
||||||
const char* Modifier = 0);
|
const char* Modifier = 0);
|
||||||
|
void printPCRelImmOperand(const MachineInstr *MI, int OpNum);
|
||||||
void printRIAddrOperand(const MachineInstr *MI, int OpNum,
|
void printRIAddrOperand(const MachineInstr *MI, int OpNum,
|
||||||
const char* Modifier = 0);
|
const char* Modifier = 0);
|
||||||
void printRRIAddrOperand(const MachineInstr *MI, int OpNum,
|
void printRRIAddrOperand(const MachineInstr *MI, int OpNum,
|
||||||
@@ -186,6 +187,40 @@ void SystemZAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
|
|||||||
assert(0 && "Should not happen");
|
assert(0 && "Should not happen");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SystemZAsmPrinter::printPCRelImmOperand(const MachineInstr *MI, int OpNum) {
|
||||||
|
const MachineOperand &MO = MI->getOperand(OpNum);
|
||||||
|
switch (MO.getType()) {
|
||||||
|
case MachineOperand::MO_GlobalAddress: {
|
||||||
|
const GlobalValue *GV = MO.getGlobal();
|
||||||
|
std::string Name = Mang->getValueName(GV);
|
||||||
|
|
||||||
|
O << Name;
|
||||||
|
|
||||||
|
// Assemble calls via PLT for externally visible symbols if PIC.
|
||||||
|
if (TM.getRelocationModel() == Reloc::PIC_ &&
|
||||||
|
!GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
|
||||||
|
!GV->hasLocalLinkage())
|
||||||
|
O << "@PLT";
|
||||||
|
|
||||||
|
printOffset(MO.getOffset());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case MachineOperand::MO_ExternalSymbol: {
|
||||||
|
std::string Name(TAI->getGlobalPrefix());
|
||||||
|
Name += MO.getSymbolName();
|
||||||
|
O << Name;
|
||||||
|
|
||||||
|
if (TM.getRelocationModel() == Reloc::PIC_)
|
||||||
|
O << "@PLT";
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
assert(0 && "Not implemented yet!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
|
void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
|
||||||
const char* Modifier) {
|
const char* Modifier) {
|
||||||
const MachineOperand &MO = MI->getOperand(OpNum);
|
const MachineOperand &MO = MI->getOperand(OpNum);
|
||||||
@@ -219,23 +254,31 @@ void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
|
|||||||
return;
|
return;
|
||||||
case MachineOperand::MO_GlobalAddress: {
|
case MachineOperand::MO_GlobalAddress: {
|
||||||
const GlobalValue *GV = MO.getGlobal();
|
const GlobalValue *GV = MO.getGlobal();
|
||||||
|
|
||||||
std::string Name = Mang->getValueName(GV);
|
std::string Name = Mang->getValueName(GV);
|
||||||
assert(MO.getOffset() == 0 && "No offsets allowed!");
|
|
||||||
|
|
||||||
O << Name;
|
O << Name;
|
||||||
|
break;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
case MachineOperand::MO_ExternalSymbol: {
|
case MachineOperand::MO_ExternalSymbol: {
|
||||||
std::string Name(TAI->getGlobalPrefix());
|
std::string Name(TAI->getGlobalPrefix());
|
||||||
Name += MO.getSymbolName();
|
Name += MO.getSymbolName();
|
||||||
O << Name;
|
O << Name;
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
assert(0 && "Not implemented yet!");
|
assert(0 && "Not implemented yet!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (MO.getTargetFlags()) {
|
||||||
|
default:
|
||||||
|
assert(0 && "Unknown target flag on GV operand");
|
||||||
|
case SystemZII::MO_NO_FLAG:
|
||||||
|
break;
|
||||||
|
case SystemZII::MO_GOTENT: O << "@GOTENT"; break;
|
||||||
|
case SystemZII::MO_PLT: O << "@PLT"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printOffset(MO.getOffset());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemZAsmPrinter::printRIAddrOperand(const MachineInstr *MI, int OpNum,
|
void SystemZAsmPrinter::printRIAddrOperand(const MachineInstr *MI, int OpNum,
|
||||||
|
|||||||
@@ -545,10 +545,38 @@ SDValue SystemZTargetLowering::LowerGlobalAddress(SDValue Op,
|
|||||||
SelectionDAG &DAG) {
|
SelectionDAG &DAG) {
|
||||||
DebugLoc dl = Op.getDebugLoc();
|
DebugLoc dl = Op.getDebugLoc();
|
||||||
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
|
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
|
||||||
SDValue GA = DAG.getTargetGlobalAddress(GV, getPointerTy());
|
int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset();
|
||||||
|
|
||||||
// FIXME: Verify stuff for constant globals entries
|
bool IsPic = getTargetMachine().getRelocationModel() == Reloc::PIC_;
|
||||||
return DAG.getNode(SystemZISD::PCRelativeWrapper, dl, getPointerTy(), GA);
|
bool ExtraLoadRequired =
|
||||||
|
Subtarget.GVRequiresExtraLoad(GV, getTargetMachine(), false);
|
||||||
|
|
||||||
|
SDValue Result;
|
||||||
|
if (!IsPic && !ExtraLoadRequired) {
|
||||||
|
Result = DAG.getTargetGlobalAddress(GV, getPointerTy(), Offset);
|
||||||
|
Offset = 0;
|
||||||
|
} else {
|
||||||
|
unsigned char OpFlags = 0;
|
||||||
|
if (ExtraLoadRequired)
|
||||||
|
OpFlags = SystemZII::MO_GOTENT;
|
||||||
|
|
||||||
|
Result = DAG.getTargetGlobalAddress(GV, getPointerTy(), 0, OpFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = DAG.getNode(SystemZISD::PCRelativeWrapper, dl,
|
||||||
|
getPointerTy(), Result);
|
||||||
|
|
||||||
|
if (ExtraLoadRequired)
|
||||||
|
Result = DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), Result,
|
||||||
|
PseudoSourceValue::getGOT(), 0);
|
||||||
|
|
||||||
|
// If there was a non-zero offset that we didn't fold, create an explicit
|
||||||
|
// addition for it.
|
||||||
|
if (Offset != 0)
|
||||||
|
Result = DAG.getNode(ISD::ADD, dl, getPointerTy(), Result,
|
||||||
|
DAG.getConstant(Offset, getPointerTy()));
|
||||||
|
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,30 @@ namespace llvm {
|
|||||||
|
|
||||||
class SystemZTargetMachine;
|
class SystemZTargetMachine;
|
||||||
|
|
||||||
|
/// SystemZII - This namespace holds all of the target specific flags that
|
||||||
|
/// instruction info tracks.
|
||||||
|
///
|
||||||
|
namespace SystemZII {
|
||||||
|
enum {
|
||||||
|
//===------------------------------------------------------------------===//
|
||||||
|
// SystemZ Specific MachineOperand flags.
|
||||||
|
|
||||||
|
MO_NO_FLAG = 0,
|
||||||
|
|
||||||
|
/// MO_GOTENT - On a symbol operand this indicates that the immediate is
|
||||||
|
/// the offset to the location of the symbol name from the base of the GOT.
|
||||||
|
///
|
||||||
|
/// SYMBOL_LABEL @GOTENT
|
||||||
|
MO_GOTENT = 1,
|
||||||
|
|
||||||
|
/// MO_PLT - On a symbol operand this indicates that the immediate is
|
||||||
|
/// offset to the PLT entry of symbol name from the current code location.
|
||||||
|
///
|
||||||
|
/// SYMBOL_LABEL @PLT
|
||||||
|
MO_PLT = 2
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
class SystemZInstrInfo : public TargetInstrInfoImpl {
|
class SystemZInstrInfo : public TargetInstrInfoImpl {
|
||||||
const SystemZRegisterInfo RI;
|
const SystemZRegisterInfo RI;
|
||||||
SystemZTargetMachine &TM;
|
SystemZTargetMachine &TM;
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ let isCall = 1 in
|
|||||||
// All calls clobber the non-callee saved registers. Uses for argument
|
// All calls clobber the non-callee saved registers. Uses for argument
|
||||||
// registers are added manually.
|
// registers are added manually.
|
||||||
let Defs = [R0D, R1D, R2D, R3D, R4D, R5D, R14D] in {
|
let Defs = [R0D, R1D, R2D, R3D, R4D, R5D, R14D] in {
|
||||||
def CALLi : Pseudo<(outs), (ins i64imm:$dst, variable_ops),
|
def CALLi : Pseudo<(outs), (ins imm_pcrel:$dst, variable_ops),
|
||||||
"brasl\t%r14, $dst", [(SystemZcall imm:$dst)]>;
|
"brasl\t%r14, $dst", [(SystemZcall imm:$dst)]>;
|
||||||
def CALLr : Pseudo<(outs), (ins ADDR64:$dst, variable_ops),
|
def CALLr : Pseudo<(outs), (ins ADDR64:$dst, variable_ops),
|
||||||
"basr\t%r14, $dst", [(SystemZcall ADDR64:$dst)]>;
|
"basr\t%r14, $dst", [(SystemZcall ADDR64:$dst)]>;
|
||||||
|
|||||||
@@ -244,6 +244,10 @@ def s32imm64 : Operand<i64> {
|
|||||||
let PrintMethod = "printS32ImmOperand";
|
let PrintMethod = "printS32ImmOperand";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def imm_pcrel : Operand<i64> {
|
||||||
|
let PrintMethod = "printPCRelImmOperand";
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// SystemZ Operand Definitions.
|
// SystemZ Operand Definitions.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "SystemZSubtarget.h"
|
#include "SystemZSubtarget.h"
|
||||||
#include "SystemZ.h"
|
#include "SystemZ.h"
|
||||||
#include "SystemZGenSubtarget.inc"
|
#include "SystemZGenSubtarget.inc"
|
||||||
|
#include "llvm/GlobalValue.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
@@ -26,3 +27,21 @@ SystemZSubtarget::SystemZSubtarget(const TargetMachine &TM, const Module &M,
|
|||||||
// Parse features string.
|
// Parse features string.
|
||||||
ParseSubtargetFeatures(FS, CPU);
|
ParseSubtargetFeatures(FS, CPU);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// True if accessing the GV requires an extra load.
|
||||||
|
bool SystemZSubtarget::GVRequiresExtraLoad(const GlobalValue* GV,
|
||||||
|
const TargetMachine& TM,
|
||||||
|
bool isDirectCall) const {
|
||||||
|
if (TM.getRelocationModel() == Reloc::PIC_) {
|
||||||
|
// Extra load is needed for all externally visible.
|
||||||
|
if (isDirectCall)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (GV->hasLocalLinkage() || GV->hasHiddenVisibility())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
namespace llvm {
|
namespace llvm {
|
||||||
class Module;
|
class Module;
|
||||||
class TargetMachine;
|
class TargetMachine;
|
||||||
|
class GlobalValue;
|
||||||
|
|
||||||
class SystemZSubtarget : public TargetSubtarget {
|
class SystemZSubtarget : public TargetSubtarget {
|
||||||
bool HasZ10Insts;
|
bool HasZ10Insts;
|
||||||
@@ -37,6 +38,9 @@ public:
|
|||||||
const std::string &CPU);
|
const std::string &CPU);
|
||||||
|
|
||||||
bool isZ10() const { return HasZ10Insts; }
|
bool isZ10() const { return HasZ10Insts; }
|
||||||
|
|
||||||
|
bool GVRequiresExtraLoad(const GlobalValue* GV, const TargetMachine& TM,
|
||||||
|
bool isDirectCall) const;
|
||||||
};
|
};
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ SystemZTargetMachine::SystemZTargetMachine(const Module &M, const std::string &F
|
|||||||
DataLayout("E-p:64:64:64-i8:8:16-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-a0:16:16"),
|
DataLayout("E-p:64:64:64-i8:8:16-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-a0:16:16"),
|
||||||
InstrInfo(*this), TLInfo(*this),
|
InstrInfo(*this), TLInfo(*this),
|
||||||
FrameInfo(TargetFrameInfo::StackGrowsDown, 8, -160) {
|
FrameInfo(TargetFrameInfo::StackGrowsDown, 8, -160) {
|
||||||
|
|
||||||
|
if (getRelocationModel() == Reloc::Default)
|
||||||
|
setRelocationModel(Reloc::Static);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SystemZTargetMachine::addInstSelector(PassManagerBase &PM,
|
bool SystemZTargetMachine::addInstSelector(PassManagerBase &PM,
|
||||||
|
|||||||
27
test/CodeGen/SystemZ/10-FuncsPic.ll
Normal file
27
test/CodeGen/SystemZ/10-FuncsPic.ll
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
; RUN: llvm-as < %s | llc -relocation-model=pic | grep GOTENT | count 3
|
||||||
|
; RUN: llvm-as < %s | llc -relocation-model=pic | grep PLT | count 1
|
||||||
|
|
||||||
|
target datalayout = "E-p:64:64:64-i8:8:16-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-a0:16:16"
|
||||||
|
target triple = "s390x-linux"
|
||||||
|
@ptr = external global void (...)* ; <void (...)**> [#uses=2]
|
||||||
|
|
||||||
|
define void @foo1() nounwind {
|
||||||
|
entry:
|
||||||
|
store void (...)* @func, void (...)** @ptr
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @func(...)
|
||||||
|
|
||||||
|
define void @foo2() nounwind {
|
||||||
|
entry:
|
||||||
|
tail call void (...)* @func() nounwind
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @foo3() nounwind {
|
||||||
|
entry:
|
||||||
|
%tmp = load void (...)** @ptr ; <void (...)*> [#uses=1]
|
||||||
|
tail call void (...)* %tmp() nounwind
|
||||||
|
ret void
|
||||||
|
}
|
||||||
29
test/CodeGen/SystemZ/10-GlobalsPic.ll
Normal file
29
test/CodeGen/SystemZ/10-GlobalsPic.ll
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
; RUN: llvm-as < %s | llc -relocation-model=pic | grep GOTENT | count 6
|
||||||
|
|
||||||
|
target datalayout = "E-p:64:64:64-i8:8:16-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-a0:16:16"
|
||||||
|
target triple = "s390x-linux"
|
||||||
|
@src = external global i32 ; <i32*> [#uses=2]
|
||||||
|
@dst = external global i32 ; <i32*> [#uses=2]
|
||||||
|
@ptr = external global i32* ; <i32**> [#uses=2]
|
||||||
|
|
||||||
|
define void @foo1() nounwind {
|
||||||
|
entry:
|
||||||
|
%tmp = load i32* @src ; <i32> [#uses=1]
|
||||||
|
store i32 %tmp, i32* @dst
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @foo2() nounwind {
|
||||||
|
entry:
|
||||||
|
store i32* @dst, i32** @ptr
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @foo3() nounwind {
|
||||||
|
entry:
|
||||||
|
%tmp = load i32* @src ; <i32> [#uses=1]
|
||||||
|
%tmp1 = load i32** @ptr ; <i32*> [#uses=1]
|
||||||
|
%arrayidx = getelementptr i32* %tmp1, i64 1 ; <i32*> [#uses=1]
|
||||||
|
store i32 %tmp, i32* %arrayidx
|
||||||
|
ret void
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user