aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaStmt.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-04-23 17:27:29 +0000
committerChris Lattner <sabre@nondot.org>2010-04-23 17:27:29 +0000
commitaab64d0b7f41ed30b15ba9210ed859424cbc7455 (patch)
tree07fe1e39bdb62c245c6bfc265c04711e7816a38c /lib/Sema/SemaStmt.cpp
parentca5cec3b5da9aa6b41c4aeccd0ee1c177825bca4 (diff)
Implement PR6845. We allow matching constraints to have different
input and output types when the smaller value isn't mentioned in the asm string. Extend this support from integers to also allowing fp values to be mismatched (if not mentioned in the asm string). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102188 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r--lib/Sema/SemaStmt.cpp101
1 files changed, 60 insertions, 41 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 9c7affdb96..ee7cc69242 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -1446,53 +1446,72 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
if (Context.hasSameType(InTy, OutTy))
continue; // All types can be tied to themselves.
- // Int/ptr operands have some special cases that we allow.
- if ((OutTy->isIntegerType() || OutTy->isPointerType()) &&
- (InTy->isIntegerType() || InTy->isPointerType())) {
-
- // They are ok if they are the same size. Tying void* to int is ok if
- // they are the same size, for example. This also allows tying void* to
- // int*.
- uint64_t OutSize = Context.getTypeSize(OutTy);
- uint64_t InSize = Context.getTypeSize(InTy);
- if (OutSize == InSize)
- continue;
-
- // If the smaller input/output operand is not mentioned in the asm string,
- // then we can promote it and the asm string won't notice. Check this
- // case now.
- bool SmallerValueMentioned = false;
- for (unsigned p = 0, e = Pieces.size(); p != e; ++p) {
- AsmStmt::AsmStringPiece &Piece = Pieces[p];
- if (!Piece.isOperand()) continue;
-
- // If this is a reference to the input and if the input was the smaller
- // one, then we have to reject this asm.
- if (Piece.getOperandNo() == i+NumOutputs) {
- if (InSize < OutSize) {
- SmallerValueMentioned = true;
- break;
- }
- }
+ // Decide if the input and output are in the same domain (integer/ptr or
+ // floating point.
+ enum AsmDomain {
+ AD_Int, AD_FP, AD_Other
+ } InputDomain, OutputDomain;
+
+ if (InTy->isIntegerType() || InTy->isPointerType())
+ InputDomain = AD_Int;
+ else if (InTy->isFloatingType())
+ InputDomain = AD_FP;
+ else
+ InputDomain = AD_Other;
- // If this is a reference to the input and if the input was the smaller
- // one, then we have to reject this asm.
- if (Piece.getOperandNo() == TiedTo) {
- if (InSize > OutSize) {
- SmallerValueMentioned = true;
- break;
- }
+ if (OutTy->isIntegerType() || OutTy->isPointerType())
+ OutputDomain = AD_Int;
+ else if (OutTy->isFloatingType())
+ OutputDomain = AD_FP;
+ else
+ OutputDomain = AD_Other;
+
+ // They are ok if they are the same size and in the same domain. This
+ // allows tying things like:
+ // void* to int*
+ // void* to int if they are the same size.
+ // double to long double if they are the same size.
+ //
+ uint64_t OutSize = Context.getTypeSize(OutTy);
+ uint64_t InSize = Context.getTypeSize(InTy);
+ if (OutSize == InSize && InputDomain == OutputDomain &&
+ InputDomain != AD_Other)
+ continue;
+
+ // If the smaller input/output operand is not mentioned in the asm string,
+ // then we can promote it and the asm string won't notice. Check this
+ // case now.
+ bool SmallerValueMentioned = false;
+ for (unsigned p = 0, e = Pieces.size(); p != e; ++p) {
+ AsmStmt::AsmStringPiece &Piece = Pieces[p];
+ if (!Piece.isOperand()) continue;
+
+ // If this is a reference to the input and if the input was the smaller
+ // one, then we have to reject this asm.
+ if (Piece.getOperandNo() == i+NumOutputs) {
+ if (InSize < OutSize) {
+ SmallerValueMentioned = true;
+ break;
}
}
- // If the smaller value wasn't mentioned in the asm string, and if the
- // output was a register, just extend the shorter one to the size of the
- // larger one.
- if (!SmallerValueMentioned &&
- OutputConstraintInfos[TiedTo].allowsRegister())
- continue;
+ // If this is a reference to the input and if the input was the smaller
+ // one, then we have to reject this asm.
+ if (Piece.getOperandNo() == TiedTo) {
+ if (InSize > OutSize) {
+ SmallerValueMentioned = true;
+ break;
+ }
+ }
}
+ // If the smaller value wasn't mentioned in the asm string, and if the
+ // output was a register, just extend the shorter one to the size of the
+ // larger one.
+ if (!SmallerValueMentioned && InputDomain != AD_Other &&
+ OutputConstraintInfos[TiedTo].allowsRegister())
+ continue;
+
Diag(InputExpr->getLocStart(),
diag::err_asm_tying_incompatible_types)
<< InTy << OutTy << OutputExpr->getSourceRange()