mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-15 00:38:42 +00:00
Trampoline codegen support for X86-32.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@40566 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
50f19f5860
commit
b116fac90f
@ -108,6 +108,9 @@ def CC_X86_64_C : CallingConv<[
|
|||||||
CCIfType<[v8i8, v4i16, v2i32, v1i64],
|
CCIfType<[v8i8, v4i16, v2i32, v1i64],
|
||||||
CCAssignToReg<[RDI, RSI, RDX, RCX, R8 , R9 ]>>,
|
CCAssignToReg<[RDI, RSI, RDX, RCX, R8 , R9 ]>>,
|
||||||
|
|
||||||
|
// The 'nest' parameter, if any, is passed in R10.
|
||||||
|
CCIfNest<CCAssignToReg<[R10]>>,
|
||||||
|
|
||||||
// Integer/FP values get stored in stack slots that are 8 bytes in size and
|
// Integer/FP values get stored in stack slots that are 8 bytes in size and
|
||||||
// 8-byte aligned if there are no more registers to hold them.
|
// 8-byte aligned if there are no more registers to hold them.
|
||||||
CCIfType<[i32, i64, f32, f64], CCAssignToStack<8, 8>>,
|
CCIfType<[i32, i64, f32, f64], CCAssignToStack<8, 8>>,
|
||||||
@ -151,6 +154,9 @@ def CC_X86_32_C : CallingConv<[
|
|||||||
// Promote i8/i16 arguments to i32.
|
// Promote i8/i16 arguments to i32.
|
||||||
CCIfType<[i8, i16], CCPromoteToType<i32>>,
|
CCIfType<[i8, i16], CCPromoteToType<i32>>,
|
||||||
|
|
||||||
|
// The 'nest' parameter, if any, is passed in ECX.
|
||||||
|
CCIfNest<CCAssignToReg<[ECX]>>,
|
||||||
|
|
||||||
// The first 3 integer arguments, if marked 'inreg' and if the call is not
|
// The first 3 integer arguments, if marked 'inreg' and if the call is not
|
||||||
// a vararg call, are passed in integer registers.
|
// a vararg call, are passed in integer registers.
|
||||||
CCIfNotVarArg<CCIfInReg<CCIfType<[i32], CCAssignToReg<[EAX, EDX, ECX]>>>>,
|
CCIfNotVarArg<CCIfInReg<CCIfType<[i32], CCAssignToReg<[EAX, EDX, ECX]>>>>,
|
||||||
@ -164,6 +170,9 @@ def CC_X86_32_FastCall : CallingConv<[
|
|||||||
// Promote i8/i16 arguments to i32.
|
// Promote i8/i16 arguments to i32.
|
||||||
CCIfType<[i8, i16], CCPromoteToType<i32>>,
|
CCIfType<[i8, i16], CCPromoteToType<i32>>,
|
||||||
|
|
||||||
|
// The 'nest' parameter, if any, is passed in EAX.
|
||||||
|
CCIfNest<CCAssignToReg<[EAX]>>,
|
||||||
|
|
||||||
// The first 2 integer arguments are passed in ECX/EDX
|
// The first 2 integer arguments are passed in ECX/EDX
|
||||||
CCIfType<[i32], CCAssignToReg<[ECX, EDX]>>,
|
CCIfType<[i32], CCAssignToReg<[ECX, EDX]>>,
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#define DEBUG_TYPE "x86-emitter"
|
#define DEBUG_TYPE "x86-emitter"
|
||||||
|
#include "X86CodeEmitter.h"
|
||||||
#include "X86InstrInfo.h"
|
#include "X86InstrInfo.h"
|
||||||
#include "X86Subtarget.h"
|
#include "X86Subtarget.h"
|
||||||
#include "X86TargetMachine.h"
|
#include "X86TargetMachine.h"
|
||||||
@ -192,14 +193,6 @@ void Emitter::emitJumpTableAddress(unsigned JTI, unsigned Reloc,
|
|||||||
MCE.emitWordLE(0); // The relocated value will be added to the displacement
|
MCE.emitWordLE(0); // The relocated value will be added to the displacement
|
||||||
}
|
}
|
||||||
|
|
||||||
/// N86 namespace - Native X86 Register numbers... used by X86 backend.
|
|
||||||
///
|
|
||||||
namespace N86 {
|
|
||||||
enum {
|
|
||||||
EAX = 0, ECX = 1, EDX = 2, EBX = 3, ESP = 4, EBP = 5, ESI = 6, EDI = 7
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// getX86RegNum - This function maps LLVM register identifiers to their X86
|
// getX86RegNum - This function maps LLVM register identifiers to their X86
|
||||||
// specific numbering, which is used in various places encoding instructions.
|
// specific numbering, which is used in various places encoding instructions.
|
||||||
//
|
//
|
||||||
|
25
lib/Target/X86/X86CodeEmitter.h
Normal file
25
lib/Target/X86/X86CodeEmitter.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
//===-- X86CodeEmitter.h - X86 DAG Lowering Interface -----------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file was developed by Duncan Sands and is distributed under
|
||||||
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file defines utilities for X86 code emission.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef X86CODEEMITTER_H
|
||||||
|
#define X86CODEEMITTER_H
|
||||||
|
|
||||||
|
/// N86 namespace - Native X86 Register numbers... used by X86 backend.
|
||||||
|
///
|
||||||
|
namespace N86 {
|
||||||
|
enum {
|
||||||
|
EAX = 0, ECX = 1, EDX = 2, EBX = 3, ESP = 4, EBP = 5, ESI = 6, EDI = 7
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // X86CODEEMITTER_H
|
@ -13,6 +13,7 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "X86.h"
|
#include "X86.h"
|
||||||
|
#include "X86CodeEmitter.h"
|
||||||
#include "X86InstrBuilder.h"
|
#include "X86InstrBuilder.h"
|
||||||
#include "X86ISelLowering.h"
|
#include "X86ISelLowering.h"
|
||||||
#include "X86MachineFunctionInfo.h"
|
#include "X86MachineFunctionInfo.h"
|
||||||
@ -34,6 +35,7 @@
|
|||||||
#include "llvm/Support/MathExtras.h"
|
#include "llvm/Support/MathExtras.h"
|
||||||
#include "llvm/Target/TargetOptions.h"
|
#include "llvm/Target/TargetOptions.h"
|
||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
|
#include "llvm/ParameterAttributes.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
X86TargetLowering::X86TargetLowering(TargetMachine &TM)
|
X86TargetLowering::X86TargetLowering(TargetMachine &TM)
|
||||||
@ -244,6 +246,10 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
|
|||||||
setExceptionSelectorRegister(X86::EDX);
|
setExceptionSelectorRegister(X86::EDX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setOperationAction(ISD::ADJUST_TRAMP, MVT::i32, Expand);
|
||||||
|
setOperationAction(ISD::ADJUST_TRAMP, MVT::i64, Expand);
|
||||||
|
setOperationAction(ISD::TRAMPOLINE, MVT::Other, Custom);
|
||||||
|
|
||||||
// VASTART needs to be custom lowered to use the VarArgsFrameIndex
|
// VASTART needs to be custom lowered to use the VarArgsFrameIndex
|
||||||
setOperationAction(ISD::VASTART , MVT::Other, Custom);
|
setOperationAction(ISD::VASTART , MVT::Other, Custom);
|
||||||
setOperationAction(ISD::VAARG , MVT::Other, Expand);
|
setOperationAction(ISD::VAARG , MVT::Other, Expand);
|
||||||
@ -4265,6 +4271,89 @@ SDOperand X86TargetLowering::LowerEH_RETURN(SDOperand Op, SelectionDAG &DAG)
|
|||||||
Chain, DAG.getRegister(X86::ECX, getPointerTy()));
|
Chain, DAG.getRegister(X86::ECX, getPointerTy()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDOperand X86TargetLowering::LowerTRAMPOLINE(SDOperand Op,
|
||||||
|
SelectionDAG &DAG) {
|
||||||
|
SDOperand Root = Op.getOperand(0);
|
||||||
|
SDOperand Trmp = Op.getOperand(1); // trampoline
|
||||||
|
SDOperand FPtr = Op.getOperand(2); // nested function
|
||||||
|
SDOperand Nest = Op.getOperand(3); // 'nest' parameter value
|
||||||
|
|
||||||
|
SrcValueSDNode *TrmpSV = cast<SrcValueSDNode>(Op.getOperand(4));
|
||||||
|
|
||||||
|
if (Subtarget->is64Bit()) {
|
||||||
|
return SDOperand(); // not yet supported
|
||||||
|
} else {
|
||||||
|
Function *Func = (Function *)
|
||||||
|
cast<Function>(cast<SrcValueSDNode>(Op.getOperand(5))->getValue());
|
||||||
|
unsigned CC = Func->getCallingConv();
|
||||||
|
unsigned char NestReg;
|
||||||
|
|
||||||
|
switch (CC) {
|
||||||
|
default:
|
||||||
|
assert(0 && "Unsupported calling convention");
|
||||||
|
case CallingConv::C:
|
||||||
|
case CallingConv::Fast:
|
||||||
|
case CallingConv::X86_StdCall: {
|
||||||
|
// Pass 'nest' parameter in ECX.
|
||||||
|
// Must be kept in sync with X86CallingConv.td
|
||||||
|
NestReg = N86::ECX;
|
||||||
|
|
||||||
|
// Check that ECX wasn't needed by an 'inreg' parameter.
|
||||||
|
const FunctionType *FTy = Func->getFunctionType();
|
||||||
|
const ParamAttrsList *Attrs = FTy->getParamAttrs();
|
||||||
|
|
||||||
|
if (Attrs && !Func->isVarArg()) {
|
||||||
|
unsigned InRegCount = 0;
|
||||||
|
unsigned Idx = 1;
|
||||||
|
|
||||||
|
for (FunctionType::param_iterator I = FTy->param_begin(),
|
||||||
|
E = FTy->param_end(); I != E; ++I, ++Idx)
|
||||||
|
if (Attrs->paramHasAttr(Idx, ParamAttr::InReg))
|
||||||
|
// FIXME: should only count parameters that are lowered to integers.
|
||||||
|
InRegCount += (getTargetData()->getTypeSizeInBits(*I) + 31) / 32;
|
||||||
|
|
||||||
|
if (InRegCount > 2) {
|
||||||
|
cerr << "Nest register in use - reduce number of inreg parameters!\n";
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CallingConv::X86_FastCall:
|
||||||
|
// Pass 'nest' parameter in EAX.
|
||||||
|
// Must be kept in sync with X86CallingConv.td
|
||||||
|
NestReg = N86::EAX;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
const unsigned char MOV32ri = 0xB8;
|
||||||
|
const unsigned char JMP = 0xE9;
|
||||||
|
|
||||||
|
OutChains[0] = DAG.getStore(Root, DAG.getConstant(MOV32ri|NestReg, MVT::i8),
|
||||||
|
Trmp, TrmpSV->getValue(), TrmpSV->getOffset());
|
||||||
|
|
||||||
|
Addr = DAG.getNode(ISD::ADD, MVT::i32, Trmp, DAG.getConstant(1, MVT::i32));
|
||||||
|
OutChains[1] = DAG.getStore(Root, Nest, Addr, TrmpSV->getValue(),
|
||||||
|
TrmpSV->getOffset() + 1, false, 1);
|
||||||
|
|
||||||
|
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());
|
||||||
|
|
||||||
|
Addr = DAG.getNode(ISD::ADD, MVT::i32, Trmp, DAG.getConstant(6, MVT::i32));
|
||||||
|
OutChains[3] = DAG.getStore(Root, Disp, Addr, TrmpSV->getValue(),
|
||||||
|
TrmpSV->getOffset() + 6, false, 1);
|
||||||
|
|
||||||
|
return DAG.getNode(ISD::TokenFactor, MVT::Other, OutChains, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// LowerOperation - Provide custom lowering hooks for some operations.
|
/// LowerOperation - Provide custom lowering hooks for some operations.
|
||||||
///
|
///
|
||||||
SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||||
@ -4306,6 +4395,7 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
|||||||
return LowerFRAME_TO_ARGS_OFFSET(Op, DAG);
|
return LowerFRAME_TO_ARGS_OFFSET(Op, DAG);
|
||||||
case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
|
case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
|
||||||
case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG);
|
case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG);
|
||||||
|
case ISD::TRAMPOLINE: return LowerTRAMPOLINE(Op, DAG);
|
||||||
}
|
}
|
||||||
return SDOperand();
|
return SDOperand();
|
||||||
}
|
}
|
||||||
|
@ -423,6 +423,7 @@ namespace llvm {
|
|||||||
SDOperand LowerFRAMEADDR(SDOperand Op, SelectionDAG &DAG);
|
SDOperand LowerFRAMEADDR(SDOperand Op, SelectionDAG &DAG);
|
||||||
SDOperand LowerFRAME_TO_ARGS_OFFSET(SDOperand Op, SelectionDAG &DAG);
|
SDOperand LowerFRAME_TO_ARGS_OFFSET(SDOperand Op, SelectionDAG &DAG);
|
||||||
SDOperand LowerEH_RETURN(SDOperand Op, SelectionDAG &DAG);
|
SDOperand LowerEH_RETURN(SDOperand Op, SelectionDAG &DAG);
|
||||||
|
SDOperand LowerTRAMPOLINE(SDOperand Op, SelectionDAG &DAG);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user