From: Chris Lattner Date: Sun, 3 May 2009 07:53:25 +0000 (+0000) Subject: implement support for asm outputs targetting non-simple lvalue destinations X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ede9d900809c4fd0298d52f5a63088ecb8302275;p=clang implement support for asm outputs targetting non-simple lvalue destinations like bitfields. incidentally llvm-gcc crashes on this sort of thing also. :) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70675 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index f435f9cfb4..aefb3e5f95 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -803,7 +803,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { std::string Constraints; - std::vector ResultAddrs; + std::vector ResultRegDests; + std::vector ResultRegQualTys; + std::vector ResultTypes; std::vector ArgTypes; @@ -827,15 +829,13 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { OutExpr = OutExpr->IgnoreParenNoopCasts(getContext()); LValue Dest = EmitLValue(OutExpr); - const llvm::Type *DestValueType = - cast(Dest.getAddress()->getType())->getElementType(); - - if (i != 0) + if (!Constraints.empty()) Constraints += ','; - if (!Info.allowsMemory() && DestValueType->isSingleValueType()) { - ResultAddrs.push_back(Dest.getAddress()); - ResultTypes.push_back(DestValueType); + if (!Info.allowsMemory() && !hasAggregateLLVMType(OutExpr->getType())) { + ResultRegQualTys.push_back(OutExpr->getType()); + ResultRegDests.push_back(Dest); + ResultTypes.push_back(ConvertTypeForMem(OutExpr->getType())); Constraints += "=" + OutputConstraint; } else { ArgTypes.push_back(Dest.getAddress()->getType()); @@ -867,7 +867,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; - if (i != 0 || S.getNumOutputs() > 0) + if (!Constraints.empty()) Constraints += ','; // Simplify the input constraint. @@ -952,11 +952,13 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { Result->addAttribute(~0, llvm::Attribute::NoUnwind); if (ResultTypes.size() == 1) { - Builder.CreateStore(Result, ResultAddrs[0]); + EmitStoreThroughLValue(RValue::get(Result), ResultRegDests[0], + ResultRegQualTys[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]); + EmitStoreThroughLValue(RValue::get(Tmp), ResultRegDests[i], + ResultRegQualTys[i]); } } } diff --git a/test/CodeGen/asm.c b/test/CodeGen/asm.c index 757a2740a7..0e9c7b243f 100644 --- a/test/CodeGen/asm.c +++ b/test/CodeGen/asm.c @@ -59,3 +59,14 @@ unsigned t11(signed char input) { : "0" (input)); return output; } + + + + +struct S { + int a : 4; +}; + +void test13(struct S *P) { + __asm__("abc %0" : "=r"(P->a) ); +}