Index: src/IceTargetLoweringX8632.cpp |
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp |
index 52ba7b5aa41e42630c9a5d1f75dd0fbba8f69552..d09bdf41f6e2b6b784261d85786a13489f36a9c5 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)); |
} |
} |