aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-05-03 07:53:25 +0000
committerChris Lattner <sabre@nondot.org>2009-05-03 07:53:25 +0000
commitede9d900809c4fd0298d52f5a63088ecb8302275 (patch)
treeb00e4cab64d73ab565be220b49b6b777fd0ae870
parente38df86a6ddc48d4a6d37478ac7d20e92edfb63a (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.cpp24
-rw-r--r--test/CodeGen/asm.c11
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) );
+}