mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-02 07:11:49 +00:00
[PowerPC] Load BlockAddress values from the TOC in 64-bit SVR4 code
Since block address values can be larger than 2GB in 64-bit code, they cannot be loaded simply using an @l / @ha pair, but instead must be loaded from the TOC, just like GlobalAddress, ConstantPool, and JumpTable values are. The commit also fixes a bug in PPCLinuxAsmPrinter::doFinalization where temporary labels could not be used as TOC values, since code would attempt (and fail) to use GetOrCreateSymbol to create a symbol of the same name as the temporary label. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220959 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
42187d2c00
commit
8a9c531e9a
@ -385,7 +385,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
const MachineOperand &MO = MI->getOperand(1);
|
||||
|
||||
// Map symbol -> label of TOC entry
|
||||
assert(MO.isGlobal() || MO.isCPI() || MO.isJTI());
|
||||
assert(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress());
|
||||
MCSymbol *MOSymbol = nullptr;
|
||||
if (MO.isGlobal())
|
||||
MOSymbol = getSymbol(MO.getGlobal());
|
||||
@ -393,6 +393,8 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
MOSymbol = GetCPISymbol(MO.getIndex());
|
||||
else if (MO.isJTI())
|
||||
MOSymbol = GetJTISymbol(MO.getIndex());
|
||||
else if (MO.isBlockAddress())
|
||||
MOSymbol = GetBlockAddressSymbol(MO.getBlockAddress());
|
||||
|
||||
MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol);
|
||||
|
||||
@ -409,6 +411,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
}
|
||||
case PPC::LDtocJTI:
|
||||
case PPC::LDtocCPT:
|
||||
case PPC::LDtocBA:
|
||||
case PPC::LDtoc: {
|
||||
// Transform %X3 = LDtoc <ga:@min1>, %X2
|
||||
LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
|
||||
@ -419,7 +422,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
const MachineOperand &MO = MI->getOperand(1);
|
||||
|
||||
// Map symbol -> label of TOC entry
|
||||
assert(MO.isGlobal() || MO.isCPI() || MO.isJTI());
|
||||
assert(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress());
|
||||
MCSymbol *MOSymbol = nullptr;
|
||||
if (MO.isGlobal())
|
||||
MOSymbol = getSymbol(MO.getGlobal());
|
||||
@ -427,6 +430,8 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
MOSymbol = GetCPISymbol(MO.getIndex());
|
||||
else if (MO.isJTI())
|
||||
MOSymbol = GetJTISymbol(MO.getIndex());
|
||||
else if (MO.isBlockAddress())
|
||||
MOSymbol = GetBlockAddressSymbol(MO.getBlockAddress());
|
||||
|
||||
MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol);
|
||||
|
||||
@ -448,7 +453,8 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
// reference the symbol directly.
|
||||
TmpInst.setOpcode(PPC::ADDIS8);
|
||||
const MachineOperand &MO = MI->getOperand(2);
|
||||
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI()) &&
|
||||
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() ||
|
||||
MO.isBlockAddress()) &&
|
||||
"Invalid operand for ADDIStocHA!");
|
||||
MCSymbol *MOSymbol = nullptr;
|
||||
bool IsExternal = false;
|
||||
@ -468,9 +474,12 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
MOSymbol = GetCPISymbol(MO.getIndex());
|
||||
else if (MO.isJTI())
|
||||
MOSymbol = GetJTISymbol(MO.getIndex());
|
||||
else if (MO.isBlockAddress())
|
||||
MOSymbol = GetBlockAddressSymbol(MO.getBlockAddress());
|
||||
|
||||
if (IsExternal || IsNonLocalFunction || IsCommon || IsAvailExt ||
|
||||
MO.isJTI() || TM.getCodeModel() == CodeModel::Large)
|
||||
MO.isJTI() || MO.isBlockAddress() ||
|
||||
TM.getCodeModel() == CodeModel::Large)
|
||||
MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
|
||||
|
||||
const MCExpr *Exp =
|
||||
@ -489,12 +498,17 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
// associated TOC entry. Otherwise reference the symbol directly.
|
||||
TmpInst.setOpcode(PPC::LD);
|
||||
const MachineOperand &MO = MI->getOperand(1);
|
||||
assert((MO.isGlobal() || MO.isJTI() || MO.isCPI()) &&
|
||||
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() ||
|
||||
MO.isBlockAddress()) &&
|
||||
"Invalid operand for LDtocL!");
|
||||
MCSymbol *MOSymbol = nullptr;
|
||||
|
||||
if (MO.isJTI())
|
||||
MOSymbol = lookUpOrCreateTOCEntry(GetJTISymbol(MO.getIndex()));
|
||||
else if (MO.isBlockAddress()) {
|
||||
MOSymbol = GetBlockAddressSymbol(MO.getBlockAddress());
|
||||
MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
|
||||
}
|
||||
else if (MO.isCPI()) {
|
||||
MOSymbol = GetCPISymbol(MO.getIndex());
|
||||
if (TM.getCodeModel() == CodeModel::Large)
|
||||
@ -978,7 +992,7 @@ bool PPCLinuxAsmPrinter::doFinalization(Module &M) {
|
||||
for (MapVector<MCSymbol*, MCSymbol*>::iterator I = TOC.begin(),
|
||||
E = TOC.end(); I != E; ++I) {
|
||||
OutStreamer.EmitLabel(I->second);
|
||||
MCSymbol *S = OutContext.GetOrCreateSymbol(I->first->getName());
|
||||
MCSymbol *S = I->first;
|
||||
if (isPPC64)
|
||||
TS.emitTCEntry(*S);
|
||||
else
|
||||
|
@ -1452,7 +1452,7 @@ SDNode *PPCDAGToDAGISel::Select(SDNode *N) {
|
||||
|
||||
// For medium and large code model, we generate two instructions as
|
||||
// described below. Otherwise we allow SelectCodeCommon to handle this,
|
||||
// selecting one of LDtoc, LDtocJTI, and LDtocCPT.
|
||||
// selecting one of LDtoc, LDtocJTI, LDtocCPT, and LDtocBA.
|
||||
CodeModel::Model CModel = TM.getCodeModel();
|
||||
if (CModel != CodeModel::Medium && CModel != CodeModel::Large)
|
||||
break;
|
||||
@ -1469,7 +1469,8 @@ SDNode *PPCDAGToDAGISel::Select(SDNode *N) {
|
||||
SDNode *Tmp = CurDAG->getMachineNode(PPC::ADDIStocHA, dl, MVT::i64,
|
||||
TOCbase, GA);
|
||||
|
||||
if (isa<JumpTableSDNode>(GA) || CModel == CodeModel::Large)
|
||||
if (isa<JumpTableSDNode>(GA) || isa<BlockAddressSDNode>(GA) ||
|
||||
CModel == CodeModel::Large)
|
||||
return CurDAG->getMachineNode(PPC::LDtocL, dl, MVT::i64, GA,
|
||||
SDValue(Tmp, 0));
|
||||
|
||||
|
@ -1638,8 +1638,16 @@ SDValue PPCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const {
|
||||
SDValue PPCTargetLowering::LowerBlockAddress(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
EVT PtrVT = Op.getValueType();
|
||||
BlockAddressSDNode *BASDN = cast<BlockAddressSDNode>(Op);
|
||||
const BlockAddress *BA = BASDN->getBlockAddress();
|
||||
|
||||
const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
|
||||
// 64-bit SVR4 ABI code is always position-independent.
|
||||
// The actual BlockAddress is stored in the TOC.
|
||||
if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) {
|
||||
SDValue GA = DAG.getTargetBlockAddress(BA, PtrVT, BASDN->getOffset());
|
||||
return DAG.getNode(PPCISD::TOC_ENTRY, SDLoc(BASDN), MVT::i64, GA,
|
||||
DAG.getRegister(PPC::X2, MVT::i64));
|
||||
}
|
||||
|
||||
unsigned MOHiFlag, MOLoFlag;
|
||||
bool isPIC = GetLabelAccessInfo(DAG.getTarget(), MOHiFlag, MOLoFlag);
|
||||
|
@ -786,7 +786,7 @@ let canFoldAsLoad = 1, PPC970_Unit = 2 in {
|
||||
def LD : DSForm_1<58, 0, (outs g8rc:$rD), (ins memrix:$src),
|
||||
"ld $rD, $src", IIC_LdStLD,
|
||||
[(set i64:$rD, (aligned4load ixaddr:$src))]>, isPPC64;
|
||||
// The following three definitions are selected for small code model only.
|
||||
// The following four definitions are selected for small code model only.
|
||||
// Otherwise, we need to create two instructions to form a 32-bit offset,
|
||||
// so we have a custom matcher for TOC_ENTRY in PPCDAGToDAGIsel::Select().
|
||||
def LDtoc: Pseudo<(outs g8rc:$rD), (ins tocentry:$disp, g8rc:$reg),
|
||||
@ -801,6 +801,10 @@ def LDtocCPT: Pseudo<(outs g8rc:$rD), (ins tocentry:$disp, g8rc:$reg),
|
||||
"#LDtocCPT",
|
||||
[(set i64:$rD,
|
||||
(PPCtoc_entry tconstpool:$disp, i64:$reg))]>, isPPC64;
|
||||
def LDtocBA: Pseudo<(outs g8rc:$rD), (ins tocentry:$disp, g8rc:$reg),
|
||||
"#LDtocCPT",
|
||||
[(set i64:$rD,
|
||||
(PPCtoc_entry tblockaddress:$disp, i64:$reg))]>, isPPC64;
|
||||
|
||||
let hasSideEffects = 1, isCodeGenOnly = 1, RST = 2, Defs = [X2] in
|
||||
def LDinto_toc: DSForm_1<58, 0, (outs), (ins memrix:$src),
|
||||
|
26
test/CodeGen/PowerPC/blockaddress.ll
Normal file
26
test/CodeGen/PowerPC/blockaddress.ll
Normal file
@ -0,0 +1,26 @@
|
||||
; RUN: llc < %s -code-model=small -march=ppc64 -mtriple=powerpc64-unknown-linux-gnu | FileCheck %s -check-prefix=SMALL
|
||||
; RUN: llc < %s -code-model=medium -march=ppc64 -mtriple=powerpc64-unknown-linux-gnu | FileCheck %s -check-prefix=MEDIUM
|
||||
; RUN: llc < %s -code-model=large -march=ppc64 -mtriple=powerpc64-unknown-linux-gnu | FileCheck %s -check-prefix=MEDIUM
|
||||
; RUN: llc < %s -code-model=small -march=ppc64 -mtriple=powerpc64le-unknown-linux-gnu | FileCheck %s -check-prefix=SMALL
|
||||
; RUN: llc < %s -code-model=medium -march=ppc64 -mtriple=powerpc64le-unknown-linux-gnu | FileCheck %s -check-prefix=MEDIUM
|
||||
; RUN: llc < %s -code-model=large -march=ppc64 -mtriple=powerpc64le-unknown-linux-gnu | FileCheck %s -check-prefix=MEDIUM
|
||||
|
||||
define i8* @test() {
|
||||
entry:
|
||||
br label %here
|
||||
|
||||
here: ; preds = %entry
|
||||
; MEDIUM: .Ltmp[[TMP0:[0-9]+]]:
|
||||
; MEDIUM: addis [[R0:[0-9]+]], 2, .LC[[LC0:[0-9]+]]@toc@ha
|
||||
; MEDIUM: ld 3, .LC[[LC0]]@toc@l([[R0]])
|
||||
; MEDIUM: blr
|
||||
; MEDIUM: .LC[[LC0]]:
|
||||
; MEDIUM: .tc .Ltmp[[TMP0]][TC],.Ltmp[[TMP0]]
|
||||
; SMALL: .Ltmp[[TMP0:[0-9]+]]:
|
||||
; SMALL: ld 3, .LC[[LC0:[0-9]+]]@toc(2)
|
||||
; SMALL: blr
|
||||
; SMALL: .LC[[LC0]]:
|
||||
; SMALL: .tc .Ltmp[[TMP0]][TC],.Ltmp[[TMP0]]
|
||||
ret i8* blockaddress(@test, %here)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user