mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-03-07 11:59:09 +00:00
Add first pass at darwin tls compiler support.
llvm-svn: 105381
This commit is contained in:
parent
86df2ed097
commit
30010cae3a
@ -200,6 +200,11 @@ void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO,
|
||||
case X86II::MO_GOT: O << "@GOT"; break;
|
||||
case X86II::MO_GOTOFF: O << "@GOTOFF"; break;
|
||||
case X86II::MO_PLT: O << "@PLT"; break;
|
||||
case X86II::MO_TLVP: O << "@TLVP"; break;
|
||||
case X86II::MO_TLVP_PIC_BASE:
|
||||
O << "@TLVP" << '-';
|
||||
PrintPICBaseSymbol(O);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,6 +152,17 @@ MCOperand X86MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
|
||||
case X86II::MO_DARWIN_STUB:
|
||||
break;
|
||||
|
||||
case X86II::MO_TLVP: RefKind = MCSymbolRefExpr::VK_TLVP; break;
|
||||
case X86II::MO_TLVP_PIC_BASE:
|
||||
Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_TLVP, Ctx);
|
||||
// Subtract the pic base.
|
||||
Expr
|
||||
= MCBinaryExpr::CreateSub(Expr,
|
||||
MCSymbolRefExpr::Create(GetPICBaseSymbol(),
|
||||
Ctx),
|
||||
Ctx);
|
||||
|
||||
break;
|
||||
case X86II::MO_TLSGD: RefKind = MCSymbolRefExpr::VK_TLSGD; break;
|
||||
case X86II::MO_GOTTPOFF: RefKind = MCSymbolRefExpr::VK_GOTTPOFF; break;
|
||||
case X86II::MO_INDNTPOFF: RefKind = MCSymbolRefExpr::VK_INDNTPOFF; break;
|
||||
|
@ -1295,7 +1295,7 @@ bool X86DAGToDAGISel::SelectTLSADDRAddr(SDNode *Op, SDValue N, SDValue &Base,
|
||||
SDValue &Disp) {
|
||||
assert(N.getOpcode() == ISD::TargetGlobalTLSAddress);
|
||||
const GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(N);
|
||||
|
||||
|
||||
X86ISelAddressMode AM;
|
||||
AM.GV = GA->getGlobal();
|
||||
AM.Disp += GA->getOffset();
|
||||
|
@ -5381,33 +5381,80 @@ static SDValue LowerToTLSExecModel(GlobalAddressSDNode *GA, SelectionDAG &DAG,
|
||||
|
||||
SDValue
|
||||
X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {
|
||||
// TODO: implement the "local dynamic" model
|
||||
// TODO: implement the "initial exec"model for pic executables
|
||||
assert(Subtarget->isTargetELF() &&
|
||||
"TLS not implemented for non-ELF targets");
|
||||
|
||||
GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
|
||||
const GlobalValue *GV = GA->getGlobal();
|
||||
|
||||
// If GV is an alias then use the aliasee for determining
|
||||
// thread-localness.
|
||||
if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
|
||||
GV = GA->resolveAliasedGlobal(false);
|
||||
if (Subtarget->isTargetELF()) {
|
||||
// TODO: implement the "local dynamic" model
|
||||
// TODO: implement the "initial exec"model for pic executables
|
||||
|
||||
// If GV is an alias then use the aliasee for determining
|
||||
// thread-localness.
|
||||
if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
|
||||
GV = GA->resolveAliasedGlobal(false);
|
||||
|
||||
TLSModel::Model model
|
||||
= getTLSModel(GV, getTargetMachine().getRelocationModel());
|
||||
|
||||
switch (model) {
|
||||
case TLSModel::GeneralDynamic:
|
||||
case TLSModel::LocalDynamic: // not implemented
|
||||
if (Subtarget->is64Bit())
|
||||
return LowerToTLSGeneralDynamicModel64(GA, DAG, getPointerTy());
|
||||
return LowerToTLSGeneralDynamicModel32(GA, DAG, getPointerTy());
|
||||
|
||||
case TLSModel::InitialExec:
|
||||
case TLSModel::LocalExec:
|
||||
return LowerToTLSExecModel(GA, DAG, getPointerTy(), model,
|
||||
Subtarget->is64Bit());
|
||||
}
|
||||
} else if (Subtarget->isTargetDarwin()) {
|
||||
// Darwin only has one model of TLS. Lower to that.
|
||||
unsigned char OpFlag = 0;
|
||||
unsigned WrapperKind = Subtarget->isPICStyleRIPRel() ?
|
||||
X86ISD::WrapperRIP : X86ISD::Wrapper;
|
||||
|
||||
// In PIC mode (unless we're in RIPRel PIC mode) we add an offset to the
|
||||
// global base reg.
|
||||
bool PIC32 = (getTargetMachine().getRelocationModel() == Reloc::PIC_) &&
|
||||
!Subtarget->is64Bit();
|
||||
if (PIC32)
|
||||
OpFlag = X86II::MO_TLVP_PIC_BASE;
|
||||
else
|
||||
OpFlag = X86II::MO_TLVP;
|
||||
|
||||
SDValue Result = DAG.getTargetGlobalAddress(GA->getGlobal(),
|
||||
getPointerTy(),
|
||||
GA->getOffset(), OpFlag);
|
||||
|
||||
DebugLoc DL = Op.getDebugLoc();
|
||||
SDValue Offset = DAG.getNode(WrapperKind, DL, getPointerTy(), Result);
|
||||
|
||||
// With PIC32, the address is actually $g + Offset.
|
||||
if (PIC32)
|
||||
Offset = DAG.getNode(ISD::ADD, DL, getPointerTy(),
|
||||
DAG.getNode(X86ISD::GlobalBaseReg,
|
||||
DebugLoc(), getPointerTy()),
|
||||
Offset);
|
||||
|
||||
// Lowering the machine isd will make sure everything is in the right
|
||||
// location.
|
||||
SDValue Args[] = { Offset };
|
||||
SDValue Chain = DAG.getNode(X86ISD::TLSCALL, DL, MVT::Other, Args, 1);
|
||||
|
||||
// TLSCALL will be codegen'ed as call. Inform MFI that function has calls.
|
||||
MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
|
||||
MFI->setAdjustsStack(true);
|
||||
|
||||
TLSModel::Model model = getTLSModel(GV,
|
||||
getTargetMachine().getRelocationModel());
|
||||
|
||||
switch (model) {
|
||||
case TLSModel::GeneralDynamic:
|
||||
case TLSModel::LocalDynamic: // not implemented
|
||||
if (Subtarget->is64Bit())
|
||||
return LowerToTLSGeneralDynamicModel64(GA, DAG, getPointerTy());
|
||||
return LowerToTLSGeneralDynamicModel32(GA, DAG, getPointerTy());
|
||||
|
||||
case TLSModel::InitialExec:
|
||||
case TLSModel::LocalExec:
|
||||
return LowerToTLSExecModel(GA, DAG, getPointerTy(), model,
|
||||
Subtarget->is64Bit());
|
||||
// And our return value (tls address) is in the standard call return value
|
||||
// location.
|
||||
unsigned Reg = Subtarget->is64Bit() ? X86::RAX : X86::EAX;
|
||||
return DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy());
|
||||
}
|
||||
|
||||
assert(false &&
|
||||
"TLS not implemented for this target.");
|
||||
|
||||
llvm_unreachable("Unreachable");
|
||||
return SDValue();
|
||||
@ -7748,6 +7795,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case X86ISD::FRSQRT: return "X86ISD::FRSQRT";
|
||||
case X86ISD::FRCP: return "X86ISD::FRCP";
|
||||
case X86ISD::TLSADDR: return "X86ISD::TLSADDR";
|
||||
case X86ISD::TLSCALL: return "X86ISD::TLSCALL";
|
||||
case X86ISD::SegmentBaseAddress: return "X86ISD::SegmentBaseAddress";
|
||||
case X86ISD::EH_RETURN: return "X86ISD::EH_RETURN";
|
||||
case X86ISD::TC_RETURN: return "X86ISD::TC_RETURN";
|
||||
@ -8477,6 +8525,33 @@ X86TargetLowering::EmitLoweredMingwAlloca(MachineInstr *MI,
|
||||
return BB;
|
||||
}
|
||||
|
||||
MachineBasicBlock *
|
||||
X86TargetLowering::EmitLoweredTLSCall(MachineInstr *MI,
|
||||
MachineBasicBlock *BB) const {
|
||||
// This is pretty easy. We're taking the value that we received from
|
||||
// our load from the relocation, sticking it in either RDI (x86-64)
|
||||
// or EAX and doing an indirect call. The return value will then
|
||||
// be in the normal return register.
|
||||
const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
|
||||
DebugLoc DL = MI->getDebugLoc();
|
||||
MachineFunction *F = BB->getParent();
|
||||
|
||||
if (Subtarget->is64Bit()) {
|
||||
MachineInstrBuilder MIB = BuildMI(BB, DL, TII->get(X86::MOV64rr), X86::RDI)
|
||||
.addReg(MI->getOperand(0).getReg());
|
||||
MIB = BuildMI(BB, DL, TII->get(X86::CALL64m));
|
||||
addDirectMem(MIB, X86::RDI).addReg(0);
|
||||
} else {
|
||||
MachineInstrBuilder MIB = BuildMI(BB, DL, TII->get(X86::MOV32rr), X86::EAX)
|
||||
.addReg(MI->getOperand(0).getReg());
|
||||
MIB = BuildMI(BB, DL, TII->get(X86::CALL32m));
|
||||
addDirectMem(MIB, X86::EAX).addReg(0);
|
||||
}
|
||||
|
||||
F->DeleteMachineInstr(MI); // The pseudo instruction is gone now.
|
||||
return BB;
|
||||
}
|
||||
|
||||
MachineBasicBlock *
|
||||
X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||
MachineBasicBlock *BB) const {
|
||||
@ -8484,6 +8559,9 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||
default: assert(false && "Unexpected instr type to insert");
|
||||
case X86::MINGW_ALLOCA:
|
||||
return EmitLoweredMingwAlloca(MI, BB);
|
||||
case X86::TLSCall_32:
|
||||
case X86::TLSCall_64:
|
||||
return EmitLoweredTLSCall(MI, BB);
|
||||
case X86::CMOV_GR8:
|
||||
case X86::CMOV_V1I64:
|
||||
case X86::CMOV_FR32:
|
||||
|
@ -196,6 +196,10 @@ namespace llvm {
|
||||
|
||||
// TLSADDR - Thread Local Storage.
|
||||
TLSADDR,
|
||||
|
||||
// TLSCALL - Thread Local Storage. When calling to an OS provided
|
||||
// thunk at the address from an earlier relocation.
|
||||
TLSCALL,
|
||||
|
||||
// SegmentBaseAddress - The address segment:0
|
||||
SegmentBaseAddress,
|
||||
@ -794,6 +798,9 @@ namespace llvm {
|
||||
|
||||
MachineBasicBlock *EmitLoweredMingwAlloca(MachineInstr *MI,
|
||||
MachineBasicBlock *BB) const;
|
||||
|
||||
MachineBasicBlock *EmitLoweredTLSCall(MachineInstr *MI,
|
||||
MachineBasicBlock *BB) const;
|
||||
|
||||
/// Emit nodes that will be selected as "test Op0,Op0", or something
|
||||
/// equivalent, for use with the given x86 condition code.
|
||||
|
@ -1709,6 +1709,19 @@ def TLS_addr64 : I<0, Pseudo, (outs), (ins lea64mem:$sym),
|
||||
[(X86tlsaddr tls64addr:$sym)]>,
|
||||
Requires<[In64BitMode]>;
|
||||
|
||||
// FIXME: Not true for darwin
|
||||
let Defs = [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11,
|
||||
FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0, ST1,
|
||||
MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
|
||||
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
|
||||
XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS],
|
||||
Uses = [RSP],
|
||||
usesCustomInserter = 1 in
|
||||
def TLSCall_64 : I<0, Pseudo, (outs), (ins GR64:$sym),
|
||||
"# Fixme into a call",
|
||||
[(X86TLSCall GR64:$sym)]>,
|
||||
Requires<[In64BitMode]>;
|
||||
|
||||
let AddedComplexity = 5, isCodeGenOnly = 1 in
|
||||
def MOV64GSrm : RI<0x8B, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src),
|
||||
"movq\t%gs:$src, $dst",
|
||||
|
@ -173,7 +173,19 @@ namespace X86II {
|
||||
/// indicates that the reference is actually to "FOO$non_lazy_ptr -PICBASE",
|
||||
/// which is a PIC-base-relative reference to a hidden dyld lazy pointer
|
||||
/// stub.
|
||||
MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE
|
||||
MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE,
|
||||
|
||||
/// MO_TLVP - On a symbol operand this indicates that the immediate is
|
||||
/// some TLS offset.
|
||||
///
|
||||
/// This is the TLS offset for the Darwin TLS mechanism.
|
||||
MO_TLVP,
|
||||
|
||||
/// MO_TLVP_PIC_BASE - On a symbol operand this indicates that the immediate
|
||||
/// is some TLS offset from the picbase.
|
||||
///
|
||||
/// This is the 32-bit TLS offset for Darwin TLS in PIC mode.
|
||||
MO_TLVP_PIC_BASE
|
||||
};
|
||||
}
|
||||
|
||||
@ -203,6 +215,7 @@ inline static bool isGlobalRelativeToPICBase(unsigned char TargetFlag) {
|
||||
case X86II::MO_PIC_BASE_OFFSET: // Darwin local global.
|
||||
case X86II::MO_DARWIN_NONLAZY_PIC_BASE: // Darwin/32 external global.
|
||||
case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: // Darwin/32 hidden global.
|
||||
case X86II::MO_TLVP: // ??? Pretty sure..
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -72,6 +72,8 @@ def SDTX86Wrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>;
|
||||
|
||||
def SDT_X86TLSADDR : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
|
||||
|
||||
def SDT_X86TLSCALL : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;
|
||||
|
||||
def SDT_X86SegmentBaseAddress : SDTypeProfile<1, 1, [SDTCisPtrTy<0>]>;
|
||||
|
||||
def SDT_X86EHRET : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
|
||||
@ -182,6 +184,9 @@ def X86mul_imm : SDNode<"X86ISD::MUL_IMM", SDTIntBinOp>;
|
||||
|
||||
def X86MingwAlloca : SDNode<"X86ISD::MINGW_ALLOCA", SDTX86Void,
|
||||
[SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
|
||||
|
||||
def X86TLSCall : SDNode<"X86ISD::TLSCALL", SDT_X86TLSCALL,
|
||||
[]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// X86 Operand Definitions.
|
||||
@ -3825,6 +3830,18 @@ def TLS_addr32 : I<0, Pseudo, (outs), (ins lea32mem:$sym),
|
||||
[(X86tlsaddr tls32addr:$sym)]>,
|
||||
Requires<[In32BitMode]>;
|
||||
|
||||
// FIXME: Not true for darwin
|
||||
let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0,
|
||||
MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
|
||||
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
|
||||
XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS],
|
||||
Uses = [ESP],
|
||||
usesCustomInserter = 1 in
|
||||
def TLSCall_32 : I<0, Pseudo, (outs), (ins GR32:$sym),
|
||||
"# Fixme into a call",
|
||||
[(X86TLSCall GR32:$sym)]>,
|
||||
Requires<[In32BitMode]>;
|
||||
|
||||
let AddedComplexity = 5, isCodeGenOnly = 1 in
|
||||
def GS_MOV32rm : I<0x8B, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src),
|
||||
"movl\t%gs:$src, $dst",
|
||||
|
Loading…
x
Reference in New Issue
Block a user