Fix the problems exposed by the callingconv1.d test case.

The first was that unless otherwise specified, inputs are assumed to be in
registers even if they specify a "matching output" that's in memory.

While testing that fix, I also ran into a bug causing the generated "matching
output" for any input was always the first one instead of the correct one.
This commit is contained in:
Frits van Bommel
2009-02-17 00:08:20 +01:00
parent 7c7ed26a17
commit 9cad440d4c
2 changed files with 18 additions and 8 deletions

View File

@@ -385,18 +385,25 @@ assert(0);
for(it i = output_constraints.begin(), e = output_constraints.end(); i != e; ++i, ++n) {
// rewrite update constraint to in and out constraints
if((*i)[0] == '+') {
(*i)[0] = '=';
std::string input_constraint;
std::stringstream ss;
ss << n;
ss >> input_constraint;
//FIXME: I think multiple inout constraints will mess up the order!
input_constraints.push_front(input_constraint);
assert(*i == mrw_cns && "What else are we updating except memory?");
/* LLVM doesn't support updating operands, so split into an input
* and an output operand.
*/
// Change update operand to pure output operand.
*i = mw_cns;
// Add input operand with same value, with original as "matching output".
std::ostringstream ss;
ss << m_cns << (n + asmblock->outputcount);
input_constraints.push_front(ss.str());
input_values.push_front(output_values[n]);
}
llvmOutConstraints += *i;
llvmOutConstraints += ",";
}
asmblock->outputcount += n;
for(it i = input_constraints.begin(), e = input_constraints.end(); i != e; ++i) {
llvmInConstraints += *i;
llvmInConstraints += ",";

View File

@@ -81,6 +81,7 @@ struct IRAsmBlock
{
std::deque<IRAsmStmt*> s;
std::set<std::string> clobs;
size_t outputcount;
// stores the labels within the asm block
std::vector<Identifier*> internalLabels;
@@ -92,7 +93,9 @@ struct IRAsmBlock
LLValue* (*retfixup)(IRBuilderHelper b, LLValue* orig); // Modifies retval
IRAsmBlock(AsmBlockStatement* b)
: asmBlock(b), retty(NULL), retn(0), retemu(false), retfixup(NULL) {}
: asmBlock(b), retty(NULL), retn(0), retemu(false), retfixup(NULL),
outputcount(0)
{}
};
// llvm::CallInst and llvm::InvokeInst don't share a common base