Commit 0c68bef8 by David Sehr

Merge lowerCall and lowerRet between x86 and x64

BUG= R=jpp@chromium.org, stichnot@chromium.org Review URL: https://codereview.chromium.org/1592033002 .
parent 29d15fd6
...@@ -58,9 +58,8 @@ protected: ...@@ -58,9 +58,8 @@ protected:
void initSandbox() {} void initSandbox() {}
void lowerIndirectJump(Variable *JumpTarget); void lowerIndirectJump(Variable *JumpTarget);
void lowerCall(const InstCall *Instr) override; Inst *emitCallToTarget(Operand *CallTarget, Variable *ReturnReg) override;
void lowerArguments() override; Variable *moveReturnValueToRegister(Operand *Value, Type ReturnType) override;
void lowerRet(const InstRet *Inst) override;
void addProlog(CfgNode *Node) override; void addProlog(CfgNode *Node) override;
void addEpilog(CfgNode *Node) override; void addEpilog(CfgNode *Node) override;
......
...@@ -68,10 +68,11 @@ struct TargetX8632Traits { ...@@ -68,10 +68,11 @@ struct TargetX8632Traits {
using Cond = ::Ice::CondX86; using Cond = ::Ice::CondX86;
using RegisterSet = ::Ice::RegX8632; using RegisterSet = ::Ice::RegX8632;
static const SizeT StackPtr = RegX8632::Reg_esp; static constexpr SizeT StackPtr = RegX8632::Reg_esp;
static const SizeT FramePtr = RegX8632::Reg_ebp; static constexpr SizeT FramePtr = RegX8632::Reg_ebp;
static const GPRRegister Encoded_Reg_Accumulator = RegX8632::Encoded_Reg_eax; static constexpr GPRRegister Encoded_Reg_Accumulator =
static const GPRRegister Encoded_Reg_Counter = RegX8632::Encoded_Reg_ecx; RegX8632::Encoded_Reg_eax;
static constexpr GPRRegister Encoded_Reg_Counter = RegX8632::Encoded_Reg_ecx;
static constexpr FixupKind FK_PcRel = llvm::ELF::R_386_PC32; static constexpr FixupKind FK_PcRel = llvm::ELF::R_386_PC32;
static constexpr FixupKind FK_Abs = llvm::ELF::R_386_32; static constexpr FixupKind FK_Abs = llvm::ELF::R_386_32;
static constexpr FixupKind FK_Gotoff = llvm::ELF::R_386_GOTOFF; static constexpr FixupKind FK_Gotoff = llvm::ELF::R_386_GOTOFF;
...@@ -658,21 +659,50 @@ public: ...@@ -658,21 +659,50 @@ public:
llvm::report_fatal_error("no rdx in non-64-bit mode."); llvm::report_fatal_error("no rdx in non-64-bit mode.");
} }
// x86-32 calling convention:
//
// * The first four arguments of vector type, regardless of their position
// relative to the other arguments in the argument list, are placed in
// registers xmm0 - xmm3.
//
// This intends to match the section "IA-32 Function Calling Convention" of
// the document "OS X ABI Function Call Guide" by Apple.
/// The maximum number of arguments to pass in XMM registers /// The maximum number of arguments to pass in XMM registers
static const uint32_t X86_MAX_XMM_ARGS = 4; static constexpr uint32_t X86_MAX_XMM_ARGS = 4;
/// The maximum number of arguments to pass in GPR registers /// The maximum number of arguments to pass in GPR registers
static const uint32_t X86_MAX_GPR_ARGS = 0; static constexpr uint32_t X86_MAX_GPR_ARGS = 0;
/// Whether scalar floating point arguments are passed in XMM registers
static constexpr bool X86_PASS_SCALAR_FP_IN_XMM = false;
/// Get the register for a given argument slot in the XMM registers.
static int32_t getRegisterForXmmArgNum(uint32_t ArgNum) {
// TODO(sehr): Change to use the CCArg technique used in ARM32.
static_assert(RegisterSet::Reg_xmm0 + 1 == RegisterSet::Reg_xmm1,
"Inconsistency between XMM register numbers and ordinals");
if (ArgNum >= X86_MAX_XMM_ARGS) {
return Variable::NoRegister;
}
return static_cast<int32_t>(RegisterSet::Reg_xmm0 + ArgNum);
}
/// Get the register for a given argument slot in the GPRs.
static int32_t getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
assert(Ty == IceType_i64 || Ty == IceType_i32);
(void)Ty;
(void)ArgNum;
return Variable::NoRegister;
}
/// The number of bits in a byte /// The number of bits in a byte
static const uint32_t X86_CHAR_BIT = 8; static constexpr uint32_t X86_CHAR_BIT = 8;
/// Stack alignment. This is defined in IceTargetLoweringX8632.cpp because it /// Stack alignment. This is defined in IceTargetLoweringX8632.cpp because it
/// is used as an argument to std::max(), and the default std::less<T> has an /// is used as an argument to std::max(), and the default std::less<T> has an
/// operator(T const&, T const&) which requires this member to have an /// operator(T const&, T const&) which requires this member to have an
/// address. /// address.
static const uint32_t X86_STACK_ALIGNMENT_BYTES; static const uint32_t X86_STACK_ALIGNMENT_BYTES;
/// Size of the return address on the stack /// Size of the return address on the stack
static const uint32_t X86_RET_IP_SIZE_BYTES = 4; static constexpr uint32_t X86_RET_IP_SIZE_BYTES = 4;
/// The number of different NOP instructions /// The number of different NOP instructions
static const uint32_t X86_NUM_NOP_VARIANTS = 5; static constexpr uint32_t X86_NUM_NOP_VARIANTS = 5;
/// \name Limits for unrolling memory intrinsics. /// \name Limits for unrolling memory intrinsics.
/// @{ /// @{
......
...@@ -60,9 +60,8 @@ protected: ...@@ -60,9 +60,8 @@ protected:
void initSandbox(); void initSandbox();
void lowerIndirectJump(Variable *JumpTarget); void lowerIndirectJump(Variable *JumpTarget);
void lowerCall(const InstCall *Instr) override; Inst *emitCallToTarget(Operand *CallTarget, Variable *ReturnReg) override;
void lowerArguments() override; Variable *moveReturnValueToRegister(Operand *Value, Type ReturnType) override;
void lowerRet(const InstRet *Inst) override;
void addProlog(CfgNode *Node) override; void addProlog(CfgNode *Node) override;
void addEpilog(CfgNode *Node) override; void addEpilog(CfgNode *Node) override;
......
...@@ -68,10 +68,11 @@ struct TargetX8664Traits { ...@@ -68,10 +68,11 @@ struct TargetX8664Traits {
using Cond = ::Ice::CondX8664; using Cond = ::Ice::CondX8664;
using RegisterSet = ::Ice::RegX8664; using RegisterSet = ::Ice::RegX8664;
static const SizeT StackPtr = RegX8664::Reg_rsp; static constexpr SizeT StackPtr = RegX8664::Reg_rsp;
static const SizeT FramePtr = RegX8664::Reg_rbp; static constexpr SizeT FramePtr = RegX8664::Reg_rbp;
static const GPRRegister Encoded_Reg_Accumulator = RegX8664::Encoded_Reg_eax; static constexpr GPRRegister Encoded_Reg_Accumulator =
static const GPRRegister Encoded_Reg_Counter = RegX8664::Encoded_Reg_ecx; RegX8664::Encoded_Reg_eax;
static constexpr GPRRegister Encoded_Reg_Counter = RegX8664::Encoded_Reg_ecx;
static constexpr FixupKind FK_PcRel = llvm::ELF::R_X86_64_PC32; static constexpr FixupKind FK_PcRel = llvm::ELF::R_X86_64_PC32;
static constexpr FixupKind FK_Abs = llvm::ELF::R_X86_64_32; static constexpr FixupKind FK_Abs = llvm::ELF::R_X86_64_32;
static constexpr FixupKind FK_Gotoff = llvm::ELF::R_X86_64_GOTOFF64; static constexpr FixupKind FK_Gotoff = llvm::ELF::R_X86_64_GOTOFF64;
...@@ -715,21 +716,61 @@ public: ...@@ -715,21 +716,61 @@ public:
static int32_t getRdxOrDie() { return RegisterSet::Reg_rdx; } static int32_t getRdxOrDie() { return RegisterSet::Reg_rdx; }
// x86-64 calling convention:
//
// * The first eight arguments of vector/fp type, regardless of their
// position relative to the other arguments in the argument list, are placed
// in registers %xmm0 - %xmm7.
//
// * The first six arguments of integer types, regardless of their position
// relative to the other arguments in the argument list, are placed in
// registers %rdi, %rsi, %rdx, %rcx, %r8, and %r9.
//
// This intends to match the section "Function Calling Sequence" of the
// document "System V Application Binary Interface."
/// The maximum number of arguments to pass in XMM registers /// The maximum number of arguments to pass in XMM registers
static const uint32_t X86_MAX_XMM_ARGS = 8; static constexpr uint32_t X86_MAX_XMM_ARGS = 8;
/// The maximum number of arguments to pass in GPR registers /// The maximum number of arguments to pass in GPR registers
static const uint32_t X86_MAX_GPR_ARGS = 6; static constexpr uint32_t X86_MAX_GPR_ARGS = 6;
/// Whether scalar floating point arguments are passed in XMM registers
static constexpr bool X86_PASS_SCALAR_FP_IN_XMM = true;
/// Get the register for a given argument slot in the XMM registers.
static int32_t getRegisterForXmmArgNum(uint32_t ArgNum) {
// TODO(sehr): Change to use the CCArg technique used in ARM32.
static_assert(RegisterSet::Reg_xmm0 + 1 == RegisterSet::Reg_xmm1,
"Inconsistency between XMM register numbers and ordinals");
if (ArgNum >= X86_MAX_XMM_ARGS) {
return Variable::NoRegister;
}
return static_cast<int32_t>(RegisterSet::Reg_xmm0 + ArgNum);
}
/// Get the register for a given argument slot in the GPRs.
static int32_t getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
if (ArgNum >= X86_MAX_GPR_ARGS) {
return Variable::NoRegister;
}
static const RegisterSet::AllRegisters GprForArgNum[] = {
RegisterSet::Reg_rdi, RegisterSet::Reg_rsi, RegisterSet::Reg_rdx,
RegisterSet::Reg_rcx, RegisterSet::Reg_r8, RegisterSet::Reg_r9,
};
static_assert(llvm::array_lengthof(GprForArgNum) == X86_MAX_GPR_ARGS,
"Mismatch between MAX_GPR_ARGS and GprForArgNum.");
assert(Ty == IceType_i64 || Ty == IceType_i32);
return static_cast<int32_t>(getGprForType(Ty, GprForArgNum[ArgNum]));
}
/// The number of bits in a byte /// The number of bits in a byte
static const uint32_t X86_CHAR_BIT = 8; static constexpr uint32_t X86_CHAR_BIT = 8;
/// Stack alignment. This is defined in IceTargetLoweringX8664.cpp because it /// Stack alignment. This is defined in IceTargetLoweringX8664.cpp because it
/// is used as an argument to std::max(), and the default std::less<T> has an /// is used as an argument to std::max(), and the default std::less<T> has an
/// operator(T const&, T const&) which requires this member to have an /// operator(T const&, T const&) which requires this member to have an
/// address. /// address.
static const uint32_t X86_STACK_ALIGNMENT_BYTES; static const uint32_t X86_STACK_ALIGNMENT_BYTES;
/// Size of the return address on the stack /// Size of the return address on the stack
static const uint32_t X86_RET_IP_SIZE_BYTES = 8; static constexpr uint32_t X86_RET_IP_SIZE_BYTES = 8;
/// The number of different NOP instructions /// The number of different NOP instructions
static const uint32_t X86_NUM_NOP_VARIANTS = 5; static constexpr uint32_t X86_NUM_NOP_VARIANTS = 5;
/// \name Limits for unrolling memory intrinsics. /// \name Limits for unrolling memory intrinsics.
/// @{ /// @{
......
...@@ -197,9 +197,11 @@ protected: ...@@ -197,9 +197,11 @@ protected:
} }
void lowerAlloca(const InstAlloca *Inst) override; void lowerAlloca(const InstAlloca *Inst) override;
void lowerArguments() override;
void lowerArithmetic(const InstArithmetic *Inst) override; void lowerArithmetic(const InstArithmetic *Inst) override;
void lowerAssign(const InstAssign *Inst) override; void lowerAssign(const InstAssign *Inst) override;
void lowerBr(const InstBr *Inst) override; void lowerBr(const InstBr *Inst) override;
void lowerCall(const InstCall *Inst) override;
void lowerCast(const InstCast *Inst) override; void lowerCast(const InstCast *Inst) override;
void lowerExtractElement(const InstExtractElement *Inst) override; void lowerExtractElement(const InstExtractElement *Inst) override;
void lowerFcmp(const InstFcmp *Inst) override; void lowerFcmp(const InstFcmp *Inst) override;
...@@ -209,6 +211,7 @@ protected: ...@@ -209,6 +211,7 @@ protected:
void lowerInsertElement(const InstInsertElement *Inst) override; void lowerInsertElement(const InstInsertElement *Inst) override;
void lowerLoad(const InstLoad *Inst) override; void lowerLoad(const InstLoad *Inst) override;
void lowerPhi(const InstPhi *Inst) override; void lowerPhi(const InstPhi *Inst) override;
void lowerRet(const InstRet *Inst) override;
void lowerSelect(const InstSelect *Inst) override; void lowerSelect(const InstSelect *Inst) override;
void lowerStore(const InstStore *Inst) override; void lowerStore(const InstStore *Inst) override;
void lowerSwitch(const InstSwitch *Inst) override; void lowerSwitch(const InstSwitch *Inst) override;
...@@ -279,6 +282,13 @@ protected: ...@@ -279,6 +282,13 @@ protected:
void scalarizeArithmetic(InstArithmetic::OpKind K, Variable *Dest, void scalarizeArithmetic(InstArithmetic::OpKind K, Variable *Dest,
Operand *Src0, Operand *Src1); Operand *Src0, Operand *Src1);
/// Emit just the call instruction (without argument or return variable
/// processing), sandboxing if needed.
virtual Inst *emitCallToTarget(Operand *CallTarget, Variable *ReturnReg) = 0;
/// Materialize the moves needed to return a value of the specified type.
virtual Variable *moveReturnValueToRegister(Operand *Value,
Type ReturnType) = 0;
/// Emit a fake use of esp to make sure esp stays alive for the entire /// Emit a fake use of esp to make sure esp stays alive for the entire
/// function. Otherwise some esp adjustments get dead-code eliminated. /// function. Otherwise some esp adjustments get dead-code eliminated.
void keepEspLiveAtExit() { void keepEspLiveAtExit() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment