Don't use indirect memory destinations for inline asm. Fixes 6841383.

llvm-svn: 70523
This commit is contained in:
Anders Carlsson 2009-05-01 00:16:04 +00:00
parent 31af617924
commit b4e463287e
2 changed files with 37 additions and 15 deletions

View File

@ -781,8 +781,8 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
std::string Constraints;
llvm::Value *ResultAddr = 0;
const llvm::Type *ResultType = llvm::Type::VoidTy;
std::vector<llvm::Value *> ResultAddrs;
std::vector<const llvm::Type *> ResultTypes;
std::vector<const llvm::Type*> ArgTypes;
std::vector<llvm::Value*> Args;
@ -812,18 +812,17 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
LValue Dest = EmitLValue(OutExpr);
const llvm::Type *DestValueType =
cast<llvm::PointerType>(Dest.getAddress()->getType())->getElementType();
// If the first output operand is not a memory dest, we'll
// make it the return value.
if (i == 0 && !Info.allowsMemory() && DestValueType->isSingleValueType()) {
ResultAddr = Dest.getAddress();
ResultType = DestValueType;
if (i != 0)
Constraints += ',';
if (!Info.allowsMemory() && DestValueType->isSingleValueType()) {
ResultAddrs.push_back(Dest.getAddress());
ResultTypes.push_back(DestValueType);
Constraints += "=" + OutputConstraint;
} else {
ArgTypes.push_back(Dest.getAddress()->getType());
Args.push_back(Dest.getAddress());
if (i != 0)
Constraints += ',';
Constraints += "=*";
Constraints += OutputConstraint;
}
@ -900,17 +899,30 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
Constraints += ',';
Constraints += MachineClobbers;
}
const llvm::Type *ResultType;
if (ResultTypes.empty())
ResultType = llvm::Type::VoidTy;
else if (ResultTypes.size() == 1)
ResultType = ResultTypes[0];
else
ResultType = llvm::StructType::get(ResultTypes);
const llvm::FunctionType *FTy =
llvm::FunctionType::get(ResultType, ArgTypes, false);
llvm::InlineAsm *IA =
llvm::InlineAsm::get(FTy, AsmString, Constraints,
S.isVolatile() || S.getNumOutputs() == 0);
llvm::CallInst *Result
= Builder.CreateCall(IA, Args.begin(), Args.end(), "");
llvm::CallInst *Result = Builder.CreateCall(IA, Args.begin(), Args.end());
Result->addAttribute(~0, llvm::Attribute::NoUnwind);
if (ResultAddr) // FIXME: volatility
Builder.CreateStore(Result, ResultAddr);
if (ResultTypes.size() == 1) {
Builder.CreateStore(Result, ResultAddrs[0]);
} else {
for (unsigned i = 0, e = ResultTypes.size(); i != e; ++i) {
llvm::Value *Tmp = Builder.CreateExtractValue(Result, i, "asmresult");
Builder.CreateStore(Tmp, ResultAddrs[i]);
}
}
}

View File

@ -0,0 +1,10 @@
// RUN: clang-cc -emit-llvm %s -o %t -arch=i386 -O2 &&
// RUN: not grep "load" %t
// <rdar://problem/6841383>
int cpuid(unsigned data) {
int a, b;
asm("xyz" :"=a"(a), "=d"(b) : "a"(data));
return a + b;
}