From bad3a94d506874355fc15b336c6f0ed360e46a06 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Fri, 1 May 2009 00:16:04 +0000 Subject: [PATCH] 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 --- lib/CodeGen/CGStmt.cpp | 42 +++++++++++++++++++++++++++--------------- test/CodeGen/asm-2.c | 10 ++++++++++ 2 files changed, 37 insertions(+), 15 deletions(-) create mode 100644 test/CodeGen/asm-2.c 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 ResultAddrs; + std::vector ResultTypes; std::vector ArgTypes; std::vector Args; @@ -812,18 +812,17 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { LValue Dest = EmitLValue(OutExpr); const llvm::Type *DestValueType = cast(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]); + } + } } diff --git a/test/CodeGen/asm-2.c b/test/CodeGen/asm-2.c new file mode 100644 index 0000000000..a58a781e72 --- /dev/null +++ b/test/CodeGen/asm-2.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -emit-llvm %s -o %t -arch=i386 -O2 && +// RUN: not grep "load" %t + +// +int cpuid(unsigned data) { + int a, b; + + asm("xyz" :"=a"(a), "=d"(b) : "a"(data)); + return a + b; +} \ No newline at end of file -- 2.40.0