diff options
author | Chris Lattner <sabre@nondot.org> | 2011-02-21 22:09:29 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2011-02-21 22:09:29 +0000 |
commit | 935f0f01c1ed3c2052b797ac035d57a85b78adc4 (patch) | |
tree | b55ef3e832410363c4faa8fdba992a497c73b891 /lib/Sema/SemaStmt.cpp | |
parent | f0c4d28020fb13fdbf7d6fccfab1b7b6a118ad0e (diff) |
add one more case of mismatched input/output constraints.
When the mismatch is due to a larger input operand that is
a constant, truncate it down to the size of the output. This
allows us to accept some cases in the linux kernel and elsewhere.
Pedantically speaking, we generate different code than GCC, though
I can't imagine how it would matter:
Clang:
movb $-1, %al
frob %al
GCC:
movl $255, %eax
frob %al
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126148 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 6801dd4c2e..3815deae58 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -1542,8 +1542,9 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, if (!Info.hasTiedOperand()) continue; unsigned TiedTo = Info.getTiedOperand(); + unsigned InputOpNo = i+NumOutputs; Expr *OutputExpr = Exprs[TiedTo]; - Expr *InputExpr = Exprs[i+NumOutputs]; + Expr *InputExpr = Exprs[InputOpNo]; QualType InTy = InputExpr->getType(); QualType OutTy = OutputExpr->getType(); if (Context.hasSameType(InTy, OutTy)) @@ -1588,7 +1589,7 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, // If this is a reference to the input and if the input was the smaller // one, then we have to reject this asm. - if (isOperandMentioned(i+NumOutputs, Pieces)) { + if (isOperandMentioned(InputOpNo, Pieces)) { // This is a use in the asm string of the smaller operand. Since we // codegen this by promoting to a wider value, the asm will get printed // "wrong". @@ -1607,6 +1608,19 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, OutputConstraintInfos[TiedTo].allowsRegister()) continue; + // Either both of the operands were mentioned or the smaller one was + // mentioned. One more special case that we'll allow: if the tied input is + // integer, unmentioned, and is a constant, then we'll allow truncating it + // down to the size of the destination. + if (InputDomain == AD_Int && OutputDomain == AD_Int && + !isOperandMentioned(InputOpNo, Pieces) && + InputExpr->isEvaluatable(Context)) { + ImpCastExprToType(InputExpr, OutTy, CK_IntegralCast); + Exprs[InputOpNo] = InputExpr; + NS->setInputExpr(i, InputExpr); + continue; + } + Diag(InputExpr->getLocStart(), diag::err_asm_tying_incompatible_types) << InTy << OutTy << OutputExpr->getSourceRange() |