diff options
author | Chris Lattner <sabre@nondot.org> | 2009-05-03 07:53:25 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-05-03 07:53:25 +0000 |
commit | ede9d900809c4fd0298d52f5a63088ecb8302275 (patch) | |
tree | b00e4cab64d73ab565be220b49b6b777fd0ae870 | |
parent | e38df86a6ddc48d4a6d37478ac7d20e92edfb63a (diff) |
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
-rw-r--r-- | lib/CodeGen/CGStmt.cpp | 24 | ||||
-rw-r--r-- | test/CodeGen/asm.c | 11 |
2 files changed, 24 insertions, 11 deletions
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<llvm::Value *> ResultAddrs; + std::vector<LValue> ResultRegDests; + std::vector<QualType> ResultRegQualTys; + std::vector<const llvm::Type *> ResultTypes; std::vector<const llvm::Type*> ArgTypes; @@ -827,15 +829,13 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { OutExpr = OutExpr->IgnoreParenNoopCasts(getContext()); LValue Dest = EmitLValue(OutExpr); - const llvm::Type *DestValueType = - cast<llvm::PointerType>(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) ); +} |