From 3351f1145aa91ddd8022fcd3ca16c219db9e8277 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 3 May 2009 08:32:32 +0000 Subject: [PATCH] allow references to the larger value in a tied constraint from the asm string, but reject references to the smaller one. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70679 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaStmt.cpp | 40 ++++++++++++++++++++++++++++------------ test/CodeGen/asm.c | 13 ++++++++++++- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index cb237870f8..0c181ecf01 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -1052,26 +1052,42 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, // 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*. - if (Context.getTypeSize(OutTy) == Context.getTypeSize(InTy)) + uint64_t OutSize = Context.getTypeSize(OutTy); + uint64_t InSize = Context.getTypeSize(InTy); + if (OutSize == InSize) continue; - // If the input and output operands are not mentioned in the asm string, - // then we can promote them and the asm string won't notice. Check this + // 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 MentionedInput = false; - bool MentionedOutput = false; + bool SmallerValueMentioned = false; for (unsigned p = 0, e = Pieces.size(); p != e; ++p) { AsmStmt::AsmStringPiece &Piece = Pieces[p]; if (!Piece.isOperand()) continue; - MentionedInput |= Piece.getOperandNo() == i+NumOutputs; - MentionedOutput |= Piece.getOperandNo() == TiedTo; + + // 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 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 neither the input nor the output was mentioned in the asm string, - // and if the output was a register, just extend the shorter one to the - // size of the larger one. - // TODO: if only the larger one is mentioned, we could also support this. - if (!MentionedInput && !MentionedOutput && + // 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; } diff --git a/test/CodeGen/asm.c b/test/CodeGen/asm.c index d7309149eb..8aa392aa80 100644 --- a/test/CodeGen/asm.c +++ b/test/CodeGen/asm.c @@ -69,11 +69,22 @@ unsigned char t12(unsigned input) { return output; } +unsigned char t13(unsigned input) { + unsigned char output; + __asm__("xyz %1" + : "=a" (output) + : "0" (input)); + return output; +} + +// bitfield destination of an asm. struct S { int a : 4; }; -void test13(struct S *P) { +void t14(struct S *P) { __asm__("abc %0" : "=r"(P->a) ); } + + -- 2.40.0