Index: src/IceTargetLoweringX8632.cpp |
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp |
index 52ba7b5aa41e42630c9a5d1f75dd0fbba8f69552..27f9ae00064e6fc8f57fcce995becebd6c91eee1 100644 |
--- a/src/IceTargetLoweringX8632.cpp |
+++ b/src/IceTargetLoweringX8632.cpp |
@@ -131,7 +131,7 @@ void TargetX8632::lowerCall(const InstCall *Instr) { |
OperandList XmmArgs; |
OperandList StackArgs, StackArgLocations; |
- uint32_t ParameterAreaSizeBytes = 0; |
+ int32_t ParameterAreaSizeBytes = 0; |
// Classify each argument operand according to the location where the |
// argument is passed. |
@@ -158,6 +158,13 @@ void TargetX8632::lowerCall(const InstCall *Instr) { |
ParameterAreaSizeBytes += typeWidthInBytesOnStack(Arg->getType()); |
} |
} |
+ // Ensure there is enough space for the fstp/movs for floating returns. |
+ Variable *Dest = Instr->getDest(); |
+ if (Dest != nullptr && isScalarFloatingType(Dest->getType())) { |
+ ParameterAreaSizeBytes = |
+ std::max(static_cast<size_t>(ParameterAreaSizeBytes), |
+ typeWidthInBytesOnStack(Dest->getType())); |
+ } |
// Adjust the parameter area so that the stack is aligned. It is assumed that |
// the stack is already aligned at the start of the calling sequence. |
@@ -197,7 +204,6 @@ void TargetX8632::lowerCall(const InstCall *Instr) { |
} |
// Generate the call instruction. Assign its result to a temporary with high |
// register allocation weight. |
- Variable *Dest = Instr->getDest(); |
// ReturnReg doubles as ReturnRegLo as necessary. |
Variable *ReturnReg = nullptr; |
Variable *ReturnRegHi = nullptr; |
@@ -255,17 +261,24 @@ void TargetX8632::lowerCall(const InstCall *Instr) { |
if (ReturnRegHi) |
Context.insert(InstFakeDef::create(Func, ReturnRegHi)); |
- // Add the appropriate offset to esp. The call instruction takes care of |
- // resetting the stack offset during emission. |
- if (ParameterAreaSizeBytes) { |
- Variable *esp = |
- Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp); |
- _add(esp, Ctx->getConstantInt32(ParameterAreaSizeBytes)); |
- } |
- |
// Insert a register-kill pseudo instruction. |
Context.insert(InstFakeKill::create(Func, NewCall)); |
+ if (Dest != nullptr && isScalarFloatingType(Dest->getType())) { |
+ // Special treatment for an FP function which returns its result in st(0). |
+ // If Dest ends up being a physical xmm register, the fstp emit code will |
+ // route st(0) through the space reserved in the function argument area |
+ // we allocated. |
+ _fstp(Dest); |
+ // Create a fake use of Dest in case it actually isn't used, because st(0) |
+ // still needs to be popped. |
+ Context.insert(InstFakeUse::create(Func, Dest)); |
+ } |
+ |
+ // Add the appropriate offset to esp. |
+ if (ParameterAreaSizeBytes) |
+ _adjust_stack(-ParameterAreaSizeBytes); |
+ |
// Generate a FakeUse to keep the call live if necessary. |
if (Instr->hasSideEffects() && ReturnReg) { |
Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); |
@@ -293,14 +306,6 @@ void TargetX8632::lowerCall(const InstCall *Instr) { |
_mov(Dest, ReturnReg); |
} |
} |
- } else if (isScalarFloatingType(Dest->getType())) { |
- // Special treatment for an FP function which returns its result in st(0). |
- // If Dest ends up being a physical xmm register, the fstp emit code will |
- // route st(0) through a temporary stack slot. |
- _fstp(Dest); |
- // Create a fake use of Dest in case it actually isn't used, because st(0) |
- // still needs to be popped. |
- Context.insert(InstFakeUse::create(Func, Dest)); |
} |
} |
@@ -363,11 +368,7 @@ void TargetX8632::lowerRet(const InstRet *Inst) { |
_ret(Reg); |
// Add a fake use of esp to make sure esp stays alive for the entire |
// function. Otherwise post-call esp adjustments get dead-code eliminated. |
- // TODO: Are there more places where the fake use should be inserted? E.g. |
- // "void f(int n){while(1) g(n);}" may not have a ret instruction. |
- Variable *esp = |
- Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp); |
- Context.insert(InstFakeUse::create(Func, esp)); |
+ keepEspLiveAtExit(); |
} |
void TargetX8632::addProlog(CfgNode *Node) { |