From 32b0ff6814a739e9f83e1db23cf2a545e5726cac Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Wed, 16 Jan 2008 22:55:25 +0000 Subject: Trampoline support for x86-64. This looks like it should work, but I have no machine to test it on. Committed because it will at least cause no harm, and maybe someone can test it for me! llvm-svn: 46098 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 63 +++++++++++++++++++++++--- llvm/test/CodeGen/X86/2008-01-16-Trampoline.ll | 14 ++++++ 2 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 llvm/test/CodeGen/X86/2008-01-16-Trampoline.ll diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 7cc14546..7cca047 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -4802,8 +4802,59 @@ SDOperand X86TargetLowering::LowerTRAMPOLINE(SDOperand Op, SrcValueSDNode *TrmpSV = cast(Op.getOperand(4)); + const X86InstrInfo *TII = + ((X86TargetMachine&)getTargetMachine()).getInstrInfo(); + if (Subtarget->is64Bit()) { - return SDOperand(); // not yet supported + SDOperand OutChains[6]; + + // Large code-model. + + const unsigned char JMP64r = TII->getBaseOpcodeFor(X86::JMP64r); + const unsigned char MOV64ri = TII->getBaseOpcodeFor(X86::MOV64ri); + + const unsigned char N86R10 = + ((X86RegisterInfo*)RegInfo)->getX86RegNum(X86::R10); + const unsigned char N86R11 = + ((X86RegisterInfo*)RegInfo)->getX86RegNum(X86::R11); + + const unsigned char REX_WB = 0x40 | 0x08 | 0x01; // REX prefix + + // Load the pointer to the nested function into R11. + unsigned OpCode = ((MOV64ri | N86R11) << 8) | REX_WB; // movabsq r11 + SDOperand Addr = Trmp; + OutChains[0] = DAG.getStore(Root, DAG.getConstant(OpCode, MVT::i16), Addr, + TrmpSV->getValue(), TrmpSV->getOffset()); + + Addr = DAG.getNode(ISD::ADD, MVT::i64, Trmp, DAG.getConstant(2, MVT::i64)); + OutChains[1] = DAG.getStore(Root, FPtr, Addr, TrmpSV->getValue(), + TrmpSV->getOffset() + 2, false, 2); + + // Load the 'nest' parameter value into R10. + // R10 is specified in X86CallingConv.td + OpCode = ((MOV64ri | N86R10) << 8) | REX_WB; // movabsq r10 + Addr = DAG.getNode(ISD::ADD, MVT::i64, Trmp, DAG.getConstant(10, MVT::i64)); + OutChains[2] = DAG.getStore(Root, DAG.getConstant(OpCode, MVT::i16), Addr, + TrmpSV->getValue(), TrmpSV->getOffset() + 10); + + Addr = DAG.getNode(ISD::ADD, MVT::i64, Trmp, DAG.getConstant(12, MVT::i64)); + OutChains[3] = DAG.getStore(Root, Nest, Addr, TrmpSV->getValue(), + TrmpSV->getOffset() + 12, false, 2); + + // Jump to the nested function. + OpCode = (JMP64r << 8) | REX_WB; // jmpq *... + Addr = DAG.getNode(ISD::ADD, MVT::i64, Trmp, DAG.getConstant(20, MVT::i64)); + OutChains[4] = DAG.getStore(Root, DAG.getConstant(OpCode, MVT::i16), Addr, + TrmpSV->getValue(), TrmpSV->getOffset() + 20); + + unsigned char ModRM = N86R11 | (4 << 3) | (3 << 6); // ...r11 + Addr = DAG.getNode(ISD::ADD, MVT::i64, Trmp, DAG.getConstant(22, MVT::i64)); + OutChains[5] = DAG.getStore(Root, DAG.getConstant(ModRM, MVT::i8), Addr, + TrmpSV->getValue(), TrmpSV->getOffset() + 22); + + SDOperand Ops[] = + { Trmp, DAG.getNode(ISD::TokenFactor, MVT::Other, OutChains, 6) }; + return DAG.getNode(ISD::MERGE_VALUES, Op.Val->getVTList(), Ops, 2); } else { Function *Func = (Function *) cast(cast(Op.getOperand(5))->getValue()); @@ -4847,17 +4898,15 @@ SDOperand X86TargetLowering::LowerTRAMPOLINE(SDOperand Op, break; } - const X86InstrInfo *TII = - ((X86TargetMachine&)getTargetMachine()).getInstrInfo(); - SDOperand OutChains[4]; SDOperand Addr, Disp; Addr = DAG.getNode(ISD::ADD, MVT::i32, Trmp, DAG.getConstant(10, MVT::i32)); Disp = DAG.getNode(ISD::SUB, MVT::i32, FPtr, Addr); - unsigned char MOV32ri = TII->getBaseOpcodeFor(X86::MOV32ri); - unsigned char N86Reg = ((X86RegisterInfo*)RegInfo)->getX86RegNum(NestReg); + const unsigned char MOV32ri = TII->getBaseOpcodeFor(X86::MOV32ri); + const unsigned char N86Reg = + ((X86RegisterInfo*)RegInfo)->getX86RegNum(NestReg); OutChains[0] = DAG.getStore(Root, DAG.getConstant(MOV32ri|N86Reg, MVT::i8), Trmp, TrmpSV->getValue(), TrmpSV->getOffset()); @@ -4865,7 +4914,7 @@ SDOperand X86TargetLowering::LowerTRAMPOLINE(SDOperand Op, OutChains[1] = DAG.getStore(Root, Nest, Addr, TrmpSV->getValue(), TrmpSV->getOffset() + 1, false, 1); - unsigned char JMP = TII->getBaseOpcodeFor(X86::JMP); + const unsigned char JMP = TII->getBaseOpcodeFor(X86::JMP); Addr = DAG.getNode(ISD::ADD, MVT::i32, Trmp, DAG.getConstant(5, MVT::i32)); OutChains[2] = DAG.getStore(Root, DAG.getConstant(JMP, MVT::i8), Addr, TrmpSV->getValue() + 5, TrmpSV->getOffset()); diff --git a/llvm/test/CodeGen/X86/2008-01-16-Trampoline.ll b/llvm/test/CodeGen/X86/2008-01-16-Trampoline.ll new file mode 100644 index 0000000..4510edb --- /dev/null +++ b/llvm/test/CodeGen/X86/2008-01-16-Trampoline.ll @@ -0,0 +1,14 @@ +; RUN: llvm-as < %s | llc -march=x86 +; RUN: llvm-as < %s | llc -march=x86-64 + + %struct.FRAME.gnat__perfect_hash_generators__select_char_position__build_identical_keys_sets = type { i32, i32, void (i32, i32)*, i8 (i32, i32)* } + +define fastcc i32 @gnat__perfect_hash_generators__select_char_position__build_identical_keys_sets.5146(i64 %table.0.0, i64 %table.0.1, i32 %last, i32 %pos) { +entry: + %tramp22 = call i8* @llvm.init.trampoline( i8* null, i8* bitcast (void (%struct.FRAME.gnat__perfect_hash_generators__select_char_position__build_identical_keys_sets*, i32, i32)* @gnat__perfect_hash_generators__select_char_position__build_identical_keys_sets__move.5177 to i8*), i8* null ) ; [#uses=0] + unreachable +} + +declare void @gnat__perfect_hash_generators__select_char_position__build_identical_keys_sets__move.5177(%struct.FRAME.gnat__perfect_hash_generators__select_char_position__build_identical_keys_sets* nest , i32, i32) nounwind + +declare i8* @llvm.init.trampoline(i8*, i8*, i8*) nounwind -- cgit v1.1