mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-30 16:34:03 +00:00
- Fix codegen for pc relative constant (e.g. JT) in thumb mode:
.set PCRELV0, (LJTI1_0_0-(LPCRELL0+4)) LPCRELL0: add r1, pc, #PCRELV0 This is not legal since add r1, pc, #c requires the constant be a multiple of 4. Do the following instead: .set PCRELV0, (LJTI1_0_0-(LPCRELL0+4)) LPCRELL0: mov r1, #PCRELV0 add r1, pc - In thumb mode, it's not possible to use .set generate a pc relative stub address. The stub is ARM code which is in a different section from the thumb code. Load the value from a constpool instead. - Some asm printing clean up. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33664 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5cbf985dcb
commit
c60e76d139
@ -122,10 +122,15 @@ namespace {
|
||||
|
||||
ARMConstantPoolValue *ACPV = (ARMConstantPoolValue*)MCPV;
|
||||
GlobalValue *GV = ACPV->getGV();
|
||||
std::string Name = Mang->getValueName(GV);
|
||||
std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix();
|
||||
if (!GV)
|
||||
Name += ACPV->getSymbol();
|
||||
if (ACPV->isNonLazyPointer()) {
|
||||
GVNonLazyPtrs.insert(Name);
|
||||
O << TAI->getPrivateGlobalPrefix() << Name << "$non_lazy_ptr";
|
||||
} else if (ACPV->isStub()) {
|
||||
FnStubs.insert(Name);
|
||||
O << TAI->getPrivateGlobalPrefix() << Name << "$stub";
|
||||
} else
|
||||
O << Name;
|
||||
if (ACPV->getPCAdjustment() != 0)
|
||||
@ -136,7 +141,7 @@ namespace {
|
||||
|
||||
// If the constant pool value is a extern weak symbol, remember to emit
|
||||
// the weak reference.
|
||||
if (GV->hasExternalWeakLinkage())
|
||||
if (GV && GV->hasExternalWeakLinkage())
|
||||
ExtWeakSymbols.insert(GV);
|
||||
}
|
||||
|
||||
@ -680,18 +685,29 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
|
||||
++EmittedInsts;
|
||||
|
||||
if (MI->getOpcode() == ARM::CONSTPOOL_ENTRY) {
|
||||
int Opc = MI->getOpcode();
|
||||
switch (Opc) {
|
||||
case ARM::CONSTPOOL_ENTRY:
|
||||
if (!InCPMode && AFI->isThumbFunction()) {
|
||||
EmitAlignment(2);
|
||||
InCPMode = true;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
default: {
|
||||
if (InCPMode && AFI->isThumbFunction()) {
|
||||
EmitAlignment(1);
|
||||
InCPMode = false;
|
||||
}
|
||||
O << "\t";
|
||||
}
|
||||
switch (Opc) {
|
||||
case ARM::PICADD:
|
||||
case ARM::PICLD:
|
||||
case ARM::tPICADD:
|
||||
break;
|
||||
default:
|
||||
O << "\t";
|
||||
break;
|
||||
}
|
||||
}}
|
||||
|
||||
// Call the autogenerated instruction printer routines.
|
||||
printInstruction(MI);
|
||||
|
@ -14,12 +14,20 @@
|
||||
#include "ARMConstantPoolValue.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/GlobalValue.h"
|
||||
#include "llvm/Type.h"
|
||||
using namespace llvm;
|
||||
|
||||
ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv, unsigned id,
|
||||
bool isNonLazy, unsigned char PCAdj)
|
||||
ARMCP::ARMCPKind k,
|
||||
unsigned char PCAdj)
|
||||
: MachineConstantPoolValue((const Type*)gv->getType()),
|
||||
GV(gv), LabelId(id), isNonLazyPtr(isNonLazy), PCAdjust(PCAdj) {}
|
||||
GV(gv), S(NULL), LabelId(id), Kind(k), PCAdjust(PCAdj) {}
|
||||
|
||||
ARMConstantPoolValue::ARMConstantPoolValue(const char *s, unsigned id,
|
||||
ARMCP::ARMCPKind k,
|
||||
unsigned char PCAdj)
|
||||
: MachineConstantPoolValue((const Type*)Type::Int32Ty),
|
||||
GV(NULL), S(s), LabelId(id), Kind(k), PCAdjust(PCAdj) {}
|
||||
|
||||
int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
|
||||
unsigned Alignment) {
|
||||
@ -30,8 +38,11 @@ int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
|
||||
(Constants[i].Offset & AlignMask) == 0) {
|
||||
ARMConstantPoolValue *CPV =
|
||||
(ARMConstantPoolValue *)Constants[i].Val.MachineCPVal;
|
||||
if (CPV->GV == GV && CPV->LabelId == LabelId &&
|
||||
CPV->isNonLazyPtr == isNonLazyPtr)
|
||||
if (CPV->GV == GV &&
|
||||
CPV->S == S &&
|
||||
CPV->LabelId == LabelId &&
|
||||
CPV->Kind == Kind &&
|
||||
CPV->PCAdjust == PCAdjust)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@ -42,14 +53,19 @@ int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
|
||||
void
|
||||
ARMConstantPoolValue::AddSelectionDAGCSEId(FoldingSetNodeID &ID) {
|
||||
ID.AddPointer(GV);
|
||||
ID.AddPointer(S);
|
||||
ID.AddInteger(LabelId);
|
||||
ID.AddInteger((unsigned)isNonLazyPtr);
|
||||
ID.AddInteger((unsigned)Kind);
|
||||
ID.AddInteger(PCAdjust);
|
||||
}
|
||||
|
||||
void ARMConstantPoolValue::print(std::ostream &O) const {
|
||||
O << GV->getName();
|
||||
if (isNonLazyPtr) O << "$non_lazy_ptr";
|
||||
if (GV)
|
||||
O << GV->getName();
|
||||
else
|
||||
O << S;
|
||||
if (isNonLazyPointer()) O << "$non_lazy_ptr";
|
||||
else if (isStub()) O << "$stub";
|
||||
if (PCAdjust != 0) O << "-(LPIC" << LabelId << "+"
|
||||
<< (unsigned)PCAdjust << ")";
|
||||
}
|
||||
|
@ -18,23 +18,38 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
namespace ARMCP {
|
||||
enum ARMCPKind {
|
||||
CPValue,
|
||||
CPNonLazyPtr,
|
||||
CPStub
|
||||
};
|
||||
}
|
||||
|
||||
/// ARMConstantPoolValue - ARM specific constantpool value. This is used to
|
||||
/// represent PC relative displacement between the address of the load
|
||||
/// instruction and the global value being loaded, i.e. (&GV-(LPIC+8)).
|
||||
class ARMConstantPoolValue : public MachineConstantPoolValue {
|
||||
GlobalValue *GV; // GlobalValue being loaded.
|
||||
const char *S; // ExtSymbol being loaded.
|
||||
unsigned LabelId; // Label id of the load.
|
||||
bool isNonLazyPtr; // True if loading a Mac OS X non_lazy_ptr stub.
|
||||
ARMCP::ARMCPKind Kind; // non_lazy_ptr or stub?
|
||||
unsigned char PCAdjust; // Extra adjustment if constantpool is pc relative.
|
||||
// 8 for ARM, 4 for Thumb.
|
||||
|
||||
public:
|
||||
ARMConstantPoolValue(GlobalValue *gv, unsigned id, bool isNonLazy = false,
|
||||
ARMConstantPoolValue(GlobalValue *gv, unsigned id,
|
||||
ARMCP::ARMCPKind Kind = ARMCP::CPValue,
|
||||
unsigned char PCAdj = 0);
|
||||
ARMConstantPoolValue(const char *s, unsigned id,
|
||||
ARMCP::ARMCPKind Kind = ARMCP::CPValue,
|
||||
unsigned char PCAdj = 0);
|
||||
|
||||
GlobalValue *getGV() const { return GV; }
|
||||
const char *getSymbol() const { return S; }
|
||||
unsigned getLabelId() const { return LabelId; }
|
||||
bool isNonLazyPointer() const { return isNonLazyPtr; }
|
||||
bool isNonLazyPointer() const { return Kind == ARMCP::CPNonLazyPtr; }
|
||||
bool isStub() const { return Kind == ARMCP::CPStub; }
|
||||
unsigned char getPCAdjustment() const { return PCAdjust; }
|
||||
|
||||
virtual int getExistingMachineCPValue(MachineConstantPool *CP,
|
||||
|
@ -230,7 +230,6 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
switch (Opcode) {
|
||||
default: return 0;
|
||||
case ARMISD::Wrapper: return "ARMISD::Wrapper";
|
||||
case ARMISD::WrapperCall: return "ARMISD::WrapperCall";
|
||||
case ARMISD::WrapperJT: return "ARMISD::WrapperJT";
|
||||
case ARMISD::CALL: return "ARMISD::CALL";
|
||||
case ARMISD::CALL_NOLINK: return "ARMISD::CALL_NOLINK";
|
||||
@ -465,25 +464,40 @@ SDOperand ARMTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) {
|
||||
bool isARMFunc = false;
|
||||
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
|
||||
GlobalValue *GV = G->getGlobal();
|
||||
Callee = DAG.getTargetGlobalAddress(GV, getPointerTy());
|
||||
isDirect = true;
|
||||
bool isExt = (GV->isDeclaration() || GV->hasWeakLinkage() ||
|
||||
GV->hasLinkOnceLinkage());
|
||||
bool isStub = (isExt && Subtarget->isTargetDarwin()) &&
|
||||
getTargetMachine().getRelocationModel() != Reloc::Static;
|
||||
isARMFunc = !Subtarget->isThumb() || isStub;
|
||||
// Wrap it since tBX takes a register source operand.
|
||||
if (isARMFunc && Subtarget->isThumb() && !Subtarget->hasV5TOps())
|
||||
Callee = DAG.getNode(ARMISD::WrapperCall, MVT::i32, Callee);
|
||||
// tBX takes a register source operand.
|
||||
if (isARMFunc && Subtarget->isThumb() && !Subtarget->hasV5TOps()) {
|
||||
ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, ARMPCLabelIndex,
|
||||
ARMCP::CPStub, 4);
|
||||
SDOperand CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 2);
|
||||
CPAddr = DAG.getNode(ARMISD::Wrapper, MVT::i32, CPAddr);
|
||||
Callee = DAG.getLoad(getPointerTy(), DAG.getEntryNode(), CPAddr, NULL, 0);
|
||||
SDOperand PICLabel = DAG.getConstant(ARMPCLabelIndex++, MVT::i32);
|
||||
Callee = DAG.getNode(ARMISD::PIC_ADD, getPointerTy(), Callee, PICLabel);
|
||||
} else
|
||||
Callee = DAG.getTargetGlobalAddress(GV, getPointerTy());
|
||||
} else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
|
||||
Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
|
||||
isDirect = true;
|
||||
bool isStub = Subtarget->isTargetDarwin() &&
|
||||
getTargetMachine().getRelocationModel() != Reloc::Static;
|
||||
isARMFunc = !Subtarget->isThumb() || isStub;
|
||||
// Wrap it since tBX takes a register source operand.
|
||||
if (isARMFunc && Subtarget->isThumb() && !Subtarget->hasV5TOps())
|
||||
Callee = DAG.getNode(ARMISD::WrapperCall, MVT::i32, Callee);
|
||||
// tBX takes a register source operand.
|
||||
const char *Sym = S->getSymbol();
|
||||
if (isARMFunc && Subtarget->isThumb() && !Subtarget->hasV5TOps()) {
|
||||
ARMConstantPoolValue *CPV = new ARMConstantPoolValue(Sym, ARMPCLabelIndex,
|
||||
ARMCP::CPStub, 4);
|
||||
SDOperand CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 2);
|
||||
CPAddr = DAG.getNode(ARMISD::Wrapper, MVT::i32, CPAddr);
|
||||
Callee = DAG.getLoad(getPointerTy(), DAG.getEntryNode(), CPAddr, NULL, 0);
|
||||
SDOperand PICLabel = DAG.getConstant(ARMPCLabelIndex++, MVT::i32);
|
||||
Callee = DAG.getNode(ARMISD::PIC_ADD, getPointerTy(), Callee, PICLabel);
|
||||
} else
|
||||
Callee = DAG.getTargetExternalSymbol(Sym, getPointerTy());
|
||||
}
|
||||
|
||||
std::vector<MVT::ValueType> NodeTys;
|
||||
@ -647,8 +661,10 @@ SDOperand ARMTargetLowering::LowerGlobalAddress(SDOperand Op,
|
||||
else {
|
||||
unsigned PCAdj = (RelocM != Reloc::PIC_)
|
||||
? 0 : (Subtarget->isThumb() ? 4 : 8);
|
||||
ARMCP::ARMCPKind Kind = IsIndirect ? ARMCP::CPNonLazyPtr
|
||||
: ARMCP::CPValue;
|
||||
ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, ARMPCLabelIndex,
|
||||
IsIndirect, PCAdj);
|
||||
Kind, PCAdj);
|
||||
CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 2);
|
||||
}
|
||||
CPAddr = DAG.getNode(ARMISD::Wrapper, MVT::i32, CPAddr);
|
||||
|
@ -31,8 +31,6 @@ namespace llvm {
|
||||
|
||||
Wrapper, // Wrapper - A wrapper node for TargetConstantPool,
|
||||
// TargetExternalSymbol, and TargetGlobalAddress.
|
||||
WrapperCall, // WrapperCall - Same as wrapper, but mark the wrapped
|
||||
// node as call operand.
|
||||
WrapperJT, // WrapperJT - A wrapper node for TargetJumpTable
|
||||
|
||||
CALL, // Function call.
|
||||
|
@ -41,7 +41,6 @@ def SDT_ARMPICAdd : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>,
|
||||
|
||||
// Node definitions.
|
||||
def ARMWrapper : SDNode<"ARMISD::Wrapper", SDTIntUnaryOp>;
|
||||
def ARMWrapperCall : SDNode<"ARMISD::WrapperCall", SDTIntUnaryOp>;
|
||||
def ARMWrapperJT : SDNode<"ARMISD::WrapperJT", SDTIntBinOp>;
|
||||
|
||||
def ARMcallseq_start : SDNode<"ISD::CALLSEQ_START", SDT_ARMCallSeq,
|
||||
@ -514,11 +513,11 @@ PseudoInst<(ops i32imm:$line, i32imm:$col, i32imm:$file),
|
||||
[(dwarf_loc (i32 imm:$line), (i32 imm:$col), (i32 imm:$file))]>;
|
||||
|
||||
def PICADD : AI1<(ops GPR:$dst, GPR:$a, pclabel:$cp),
|
||||
"\n$cp:\n\tadd $dst, pc, $a",
|
||||
"$cp:\n\tadd $dst, pc, $a",
|
||||
[(set GPR:$dst, (ARMpic_add GPR:$a, imm:$cp))]>;
|
||||
let AddedComplexity = 10 in
|
||||
def PICLD : AI2<(ops GPR:$dst, addrmodepc:$addr),
|
||||
"\n${addr:label}:\n\tldr $dst, $addr",
|
||||
"${addr:label}:\n\tldr $dst, $addr",
|
||||
[(set GPR:$dst, (load addrmodepc:$addr))]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -158,7 +158,7 @@ def t_addrmode_sp : Operand<i32>,
|
||||
//
|
||||
|
||||
def tPICADD : TIt<(ops GPR:$dst, GPR:$lhs, pclabel:$cp),
|
||||
"\n$cp:\n\tadd $dst, pc",
|
||||
"$cp:\n\tadd $dst, pc",
|
||||
[(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -475,25 +475,18 @@ let usesCustomDAGSchedInserter = 1 in // Expanded by the scheduler.
|
||||
|
||||
// tLEApcrel - Load a pc-relative address into a register without offending the
|
||||
// assembler.
|
||||
def tLEApcrel : TI<(ops GPR:$dst, i32imm:$label),
|
||||
def tLEApcrel : TIx2<(ops GPR:$dst, i32imm:$label),
|
||||
!strconcat(!strconcat(".set PCRELV${:uid}, ($label-(",
|
||||
"${:private}PCRELL${:uid}+4))\n"),
|
||||
!strconcat("${:private}PCRELL${:uid}:\n\t",
|
||||
"add $dst, pc, #PCRELV${:uid}")),
|
||||
"mov $dst, #PCRELV${:uid}\n\tadd $dst, pc")),
|
||||
[]>;
|
||||
|
||||
def tLEApcrelCall : TI<(ops GPR:$dst, i32imm:$label),
|
||||
!strconcat(!strconcat(".set PCRELV${:uid}, (${label:call}-(",
|
||||
"${:private}PCRELL${:uid}+4))\n"),
|
||||
!strconcat("${:private}PCRELL${:uid}:\n\t",
|
||||
"add $dst, pc, #PCRELV${:uid}")),
|
||||
[]>;
|
||||
|
||||
def tLEApcrelJT : TI<(ops GPR:$dst, i32imm:$label, i32imm:$id),
|
||||
def tLEApcrelJT : TIx2<(ops GPR:$dst, i32imm:$label, i32imm:$id),
|
||||
!strconcat(!strconcat(".set PCRELV${:uid}, (${label}_${id:no_hash}-(",
|
||||
"${:private}PCRELL${:uid}+4))\n"),
|
||||
!strconcat("${:private}PCRELL${:uid}:\n\t",
|
||||
"add $dst, pc, #PCRELV${:uid}")),
|
||||
"mov $dst, #PCRELV${:uid}\n\tadd $dst, pc")),
|
||||
[]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -503,10 +496,6 @@ def tLEApcrelJT : TI<(ops GPR:$dst, i32imm:$label, i32imm:$id),
|
||||
// ConstantPool, GlobalAddress
|
||||
def : ThumbPat<(ARMWrapper tglobaladdr :$dst), (tLEApcrel tglobaladdr :$dst)>;
|
||||
def : ThumbPat<(ARMWrapper tconstpool :$dst), (tLEApcrel tconstpool :$dst)>;
|
||||
def : ThumbPat<(ARMWrapperCall tglobaladdr :$dst),
|
||||
(tLEApcrelCall tglobaladdr :$dst)>;
|
||||
def : ThumbPat<(ARMWrapperCall texternalsym:$dst),
|
||||
(tLEApcrelCall texternalsym:$dst)>;
|
||||
|
||||
// JumpTable
|
||||
def : ThumbPat<(ARMWrapperJT tjumptable:$dst, imm:$id),
|
||||
|
Loading…
Reference in New Issue
Block a user