diff options
author | Anders Carlsson <andersca@mac.com> | 2009-05-01 00:16:04 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-05-01 00:16:04 +0000 |
commit | bad3a94d506874355fc15b336c6f0ed360e46a06 (patch) | |
tree | d669bfd97a6cbefc8add49c205a962f2a920fc76 /lib/CodeGen/CGStmt.cpp | |
parent | 7786d1c5d752b90ff74093bd1ffda37daf0dbe6e (diff) |
Don't use indirect memory destinations for inline asm. Fixes 6841383.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70523 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGStmt.cpp')
-rw-r--r-- | lib/CodeGen/CGStmt.cpp | 42 |
1 files changed, 27 insertions, 15 deletions
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 0837dd0489..63664e1a3a 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -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]); + } + } } |