[cfe-commits] r162132 - in /cfe/trunk/lib/Sema: CMakeLists.txt SemaStmt.cpp SemaStmtAsm.cpp

Chad Rosier mcrosier at apple.com
Fri Aug 24 16:16:38 PDT 2012


On Aug 24, 2012, at 4:08 PM, Matt Beaumont-Gay wrote:

> On Wed, Aug 22, 2012 at 6:37 PM, Sean Silva <silvas at purdue.edu> wrote:
>> +    for (unsigned i = 0, e = IDVal.size(); i != e; ++i)
>> +      Opcode.push_back(tolower(IDVal[i]));
>> 
>> Hey Chad, sorry for commenting on this rather old email, but this use
>> of 'i' as a variable name inside a loop whose index variable is
>> already 'i' seems questionable, especially since you're using 'j' for
>> another inner loop. I discovered this because GCC just gave me an odd
>> warning over it:
>> 
>> SemaStmtAsm.cpp:594:63: warning: name lookup of ‘i’ changed [enabled by default]
>> SemaStmtAsm.cpp:509:17: warning:   matches this ‘i’ under ISO standard
>> rules [enabled by default]
>> SemaStmtAsm.cpp:536:19: warning:   matches this ‘i’ under old rules
>> [enabled by default]
>> 
>> IMO this warning is pointless, but nonetheless, I think it would be
>> good to change the loop variable to be 'j'.
> 
> For posterity, I fixed this in r162424.

You beat me to it.  I renamed the outer 'i' in r162444.  Regardless, thanks.

 Chad

> 
>> 
>> --Sean Silva
>> 
>> On Fri, Aug 17, 2012 at 5:19 PM, Chad Rosier <mcrosier at apple.com> wrote:
>>> Author: mcrosier
>>> Date: Fri Aug 17 16:19:40 2012
>>> New Revision: 162132
>>> 
>>> URL: http://llvm.org/viewvc/llvm-project?rev=162132&view=rev
>>> Log:
>>> [ms-inline asm] Extract AsmStmt handling into a separate file, so as to not
>>> pollute SemaStmt with extraneous asm handling logic.
>>> 
>>> Added:
>>>    cfe/trunk/lib/Sema/SemaStmtAsm.cpp
>>> Modified:
>>>    cfe/trunk/lib/Sema/CMakeLists.txt
>>>    cfe/trunk/lib/Sema/SemaStmt.cpp
>>> 
>>> Modified: cfe/trunk/lib/Sema/CMakeLists.txt
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=162132&r1=162131&r2=162132&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/CMakeLists.txt (original)
>>> +++ cfe/trunk/lib/Sema/CMakeLists.txt Fri Aug 17 16:19:40 2012
>>> @@ -39,6 +39,7 @@
>>>   SemaOverload.cpp
>>>   SemaPseudoObject.cpp
>>>   SemaStmt.cpp
>>> +  SemaStmtAsm.cpp
>>>   SemaStmtAttr.cpp
>>>   SemaTemplate.cpp
>>>   SemaTemplateDeduction.cpp
>>> 
>>> Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=162132&r1=162131&r2=162132&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
>>> +++ cfe/trunk/lib/Sema/SemaStmt.cpp Fri Aug 17 16:19:40 2012
>>> @@ -28,27 +28,10 @@
>>> #include "clang/Lex/Preprocessor.h"
>>> #include "clang/Basic/TargetInfo.h"
>>> #include "llvm/ADT/ArrayRef.h"
>>> -#include "llvm/ADT/BitVector.h"
>>> #include "llvm/ADT/STLExtras.h"
>>> #include "llvm/ADT/SmallPtrSet.h"
>>> #include "llvm/ADT/SmallString.h"
>>> #include "llvm/ADT/SmallVector.h"
>>> -#include "llvm/ADT/Triple.h"
>>> -#include "llvm/MC/MCAsmInfo.h"
>>> -#include "llvm/MC/MCContext.h"
>>> -#include "llvm/MC/MCInst.h"
>>> -#include "llvm/MC/MCInstPrinter.h"
>>> -#include "llvm/MC/MCInstrInfo.h"
>>> -#include "llvm/MC/MCObjectFileInfo.h"
>>> -#include "llvm/MC/MCRegisterInfo.h"
>>> -#include "llvm/MC/MCStreamer.h"
>>> -#include "llvm/MC/MCSubtargetInfo.h"
>>> -#include "llvm/MC/MCTargetAsmParser.h"
>>> -#include "llvm/MC/MCParser/MCAsmLexer.h"
>>> -#include "llvm/MC/MCParser/MCAsmParser.h"
>>> -#include "llvm/Support/SourceMgr.h"
>>> -#include "llvm/Support/TargetRegistry.h"
>>> -#include "llvm/Support/TargetSelect.h"
>>> using namespace clang;
>>> using namespace sema;
>>> 
>>> @@ -2485,600 +2468,6 @@
>>>   return Owned(Result);
>>> }
>>> 
>>> -/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently
>>> -/// ignore "noop" casts in places where an lvalue is required by an inline asm.
>>> -/// We emulate this behavior when -fheinous-gnu-extensions is specified, but
>>> -/// provide a strong guidance to not use it.
>>> -///
>>> -/// This method checks to see if the argument is an acceptable l-value and
>>> -/// returns false if it is a case we can handle.
>>> -static bool CheckAsmLValue(const Expr *E, Sema &S) {
>>> -  // Type dependent expressions will be checked during instantiation.
>>> -  if (E->isTypeDependent())
>>> -    return false;
>>> -
>>> -  if (E->isLValue())
>>> -    return false;  // Cool, this is an lvalue.
>>> -
>>> -  // Okay, this is not an lvalue, but perhaps it is the result of a cast that we
>>> -  // are supposed to allow.
>>> -  const Expr *E2 = E->IgnoreParenNoopCasts(S.Context);
>>> -  if (E != E2 && E2->isLValue()) {
>>> -    if (!S.getLangOpts().HeinousExtensions)
>>> -      S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue)
>>> -        << E->getSourceRange();
>>> -    else
>>> -      S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
>>> -        << E->getSourceRange();
>>> -    // Accept, even if we emitted an error diagnostic.
>>> -    return false;
>>> -  }
>>> -
>>> -  // None of the above, just randomly invalid non-lvalue.
>>> -  return true;
>>> -}
>>> -
>>> -/// isOperandMentioned - Return true if the specified operand # is mentioned
>>> -/// anywhere in the decomposed asm string.
>>> -static bool isOperandMentioned(unsigned OpNo,
>>> -                         ArrayRef<AsmStmt::AsmStringPiece> AsmStrPieces) {
>>> -  for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) {
>>> -    const AsmStmt::AsmStringPiece &Piece = AsmStrPieces[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() == OpNo)
>>> -      return true;
>>> -  }
>>> -  return false;
>>> -}
>>> -
>>> -StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple,
>>> -                              bool IsVolatile, unsigned NumOutputs,
>>> -                              unsigned NumInputs, IdentifierInfo **Names,
>>> -                              MultiExprArg constraints, MultiExprArg exprs,
>>> -                              Expr *asmString, MultiExprArg clobbers,
>>> -                              SourceLocation RParenLoc, bool MSAsm) {
>>> -  unsigned NumClobbers = clobbers.size();
>>> -  StringLiteral **Constraints =
>>> -    reinterpret_cast<StringLiteral**>(constraints.get());
>>> -  Expr **Exprs = exprs.get();
>>> -  StringLiteral *AsmString = cast<StringLiteral>(asmString);
>>> -  StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.get());
>>> -
>>> -  SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;
>>> -
>>> -  // The parser verifies that there is a string literal here.
>>> -  if (!AsmString->isAscii())
>>> -    return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character)
>>> -      << AsmString->getSourceRange());
>>> -
>>> -  for (unsigned i = 0; i != NumOutputs; i++) {
>>> -    StringLiteral *Literal = Constraints[i];
>>> -    if (!Literal->isAscii())
>>> -      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
>>> -        << Literal->getSourceRange());
>>> -
>>> -    StringRef OutputName;
>>> -    if (Names[i])
>>> -      OutputName = Names[i]->getName();
>>> -
>>> -    TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
>>> -    if (!Context.getTargetInfo().validateOutputConstraint(Info))
>>> -      return StmtError(Diag(Literal->getLocStart(),
>>> -                            diag::err_asm_invalid_output_constraint)
>>> -                       << Info.getConstraintStr());
>>> -
>>> -    // Check that the output exprs are valid lvalues.
>>> -    Expr *OutputExpr = Exprs[i];
>>> -    if (CheckAsmLValue(OutputExpr, *this)) {
>>> -      return StmtError(Diag(OutputExpr->getLocStart(),
>>> -                  diag::err_asm_invalid_lvalue_in_output)
>>> -        << OutputExpr->getSourceRange());
>>> -    }
>>> -
>>> -    OutputConstraintInfos.push_back(Info);
>>> -  }
>>> -
>>> -  SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;
>>> -
>>> -  for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
>>> -    StringLiteral *Literal = Constraints[i];
>>> -    if (!Literal->isAscii())
>>> -      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
>>> -        << Literal->getSourceRange());
>>> -
>>> -    StringRef InputName;
>>> -    if (Names[i])
>>> -      InputName = Names[i]->getName();
>>> -
>>> -    TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
>>> -    if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(),
>>> -                                                NumOutputs, Info)) {
>>> -      return StmtError(Diag(Literal->getLocStart(),
>>> -                            diag::err_asm_invalid_input_constraint)
>>> -                       << Info.getConstraintStr());
>>> -    }
>>> -
>>> -    Expr *InputExpr = Exprs[i];
>>> -
>>> -    // Only allow void types for memory constraints.
>>> -    if (Info.allowsMemory() && !Info.allowsRegister()) {
>>> -      if (CheckAsmLValue(InputExpr, *this))
>>> -        return StmtError(Diag(InputExpr->getLocStart(),
>>> -                              diag::err_asm_invalid_lvalue_in_input)
>>> -                         << Info.getConstraintStr()
>>> -                         << InputExpr->getSourceRange());
>>> -    }
>>> -
>>> -    if (Info.allowsRegister()) {
>>> -      if (InputExpr->getType()->isVoidType()) {
>>> -        return StmtError(Diag(InputExpr->getLocStart(),
>>> -                              diag::err_asm_invalid_type_in_input)
>>> -          << InputExpr->getType() << Info.getConstraintStr()
>>> -          << InputExpr->getSourceRange());
>>> -      }
>>> -    }
>>> -
>>> -    ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
>>> -    if (Result.isInvalid())
>>> -      return StmtError();
>>> -
>>> -    Exprs[i] = Result.take();
>>> -    InputConstraintInfos.push_back(Info);
>>> -  }
>>> -
>>> -  // Check that the clobbers are valid.
>>> -  for (unsigned i = 0; i != NumClobbers; i++) {
>>> -    StringLiteral *Literal = Clobbers[i];
>>> -    if (!Literal->isAscii())
>>> -      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
>>> -        << Literal->getSourceRange());
>>> -
>>> -    StringRef Clobber = Literal->getString();
>>> -
>>> -    if (!Context.getTargetInfo().isValidClobber(Clobber))
>>> -      return StmtError(Diag(Literal->getLocStart(),
>>> -                  diag::err_asm_unknown_register_name) << Clobber);
>>> -  }
>>> -
>>> -  AsmStmt *NS =
>>> -    new (Context) AsmStmt(Context, AsmLoc, IsSimple, IsVolatile, MSAsm,
>>> -                          NumOutputs, NumInputs, Names, Constraints, Exprs,
>>> -                          AsmString, NumClobbers, Clobbers, RParenLoc);
>>> -  // Validate the asm string, ensuring it makes sense given the operands we
>>> -  // have.
>>> -  SmallVector<AsmStmt::AsmStringPiece, 8> Pieces;
>>> -  unsigned DiagOffs;
>>> -  if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) {
>>> -    Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
>>> -           << AsmString->getSourceRange();
>>> -    return StmtError();
>>> -  }
>>> -
>>> -  // Validate tied input operands for type mismatches.
>>> -  for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
>>> -    TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
>>> -
>>> -    // If this is a tied constraint, verify that the output and input have
>>> -    // either exactly the same type, or that they are int/ptr operands with the
>>> -    // same size (int/long, int*/long, are ok etc).
>>> -    if (!Info.hasTiedOperand()) continue;
>>> -
>>> -    unsigned TiedTo = Info.getTiedOperand();
>>> -    unsigned InputOpNo = i+NumOutputs;
>>> -    Expr *OutputExpr = Exprs[TiedTo];
>>> -    Expr *InputExpr = Exprs[InputOpNo];
>>> -
>>> -    if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent())
>>> -      continue;
>>> -
>>> -    QualType InTy = InputExpr->getType();
>>> -    QualType OutTy = OutputExpr->getType();
>>> -    if (Context.hasSameType(InTy, OutTy))
>>> -      continue;  // All types can be tied to themselves.
>>> -
>>> -    // 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->isRealFloatingType())
>>> -      InputDomain = AD_FP;
>>> -    else
>>> -      InputDomain = AD_Other;
>>> -
>>> -    if (OutTy->isIntegerType() || OutTy->isPointerType())
>>> -      OutputDomain = AD_Int;
>>> -    else if (OutTy->isRealFloatingType())
>>> -      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 the smaller one to a larger input and the asm string
>>> -    // won't notice.
>>> -    bool SmallerValueMentioned = false;
>>> -
>>> -    // 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(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".
>>> -      SmallerValueMentioned |= InSize < OutSize;
>>> -    }
>>> -    if (isOperandMentioned(TiedTo, Pieces)) {
>>> -      // If this is a reference to the output, and if the output is the larger
>>> -      // value, then it's ok because we'll promote the input to the larger type.
>>> -      SmallerValueMentioned |= OutSize < InSize;
>>> -    }
>>> -
>>> -    // 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;
>>> -
>>> -    // 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)) {
>>> -      CastKind castKind =
>>> -        (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast);
>>> -      InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take();
>>> -      Exprs[InputOpNo] = InputExpr;
>>> -      NS->setInputExpr(i, InputExpr);
>>> -      continue;
>>> -    }
>>> -
>>> -    Diag(InputExpr->getLocStart(),
>>> -         diag::err_asm_tying_incompatible_types)
>>> -      << InTy << OutTy << OutputExpr->getSourceRange()
>>> -      << InputExpr->getSourceRange();
>>> -    return StmtError();
>>> -  }
>>> -
>>> -  return Owned(NS);
>>> -}
>>> -
>>> -// isMSAsmKeyword - Return true if this is an MS-style inline asm keyword. These
>>> -// require special handling.
>>> -static bool isMSAsmKeyword(StringRef Name) {
>>> -  bool Ret = llvm::StringSwitch<bool>(Name)
>>> -    .Cases("EVEN", "ALIGN", true) // Alignment directives.
>>> -    .Cases("LENGTH", "SIZE", "TYPE", true) // Type and variable sizes.
>>> -    .Case("_emit", true) // _emit Pseudoinstruction.
>>> -    .Default(false);
>>> -  return Ret;
>>> -}
>>> -
>>> -static StringRef getSpelling(Sema &SemaRef, Token AsmTok) {
>>> -  StringRef Asm;
>>> -  SmallString<512> TokenBuf;
>>> -  TokenBuf.resize(512);
>>> -  bool StringInvalid = false;
>>> -  Asm = SemaRef.PP.getSpelling(AsmTok, TokenBuf, &StringInvalid);
>>> -  assert (!StringInvalid && "Expected valid string!");
>>> -  return Asm;
>>> -}
>>> -
>>> -static void patchMSAsmStrings(Sema &SemaRef, bool &IsSimple,
>>> -                              SourceLocation AsmLoc,
>>> -                              ArrayRef<Token> AsmToks,
>>> -                              const TargetInfo &TI,
>>> -                              std::vector<llvm::BitVector> &AsmRegs,
>>> -                              std::vector<llvm::BitVector> &AsmNames,
>>> -                              std::vector<std::string> &AsmStrings) {
>>> -  assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!");
>>> -
>>> -  // Assume simple asm stmt until we parse a non-register identifer (or we just
>>> -  // need to bail gracefully).
>>> -  IsSimple = true;
>>> -
>>> -  SmallString<512> Asm;
>>> -  unsigned NumAsmStrings = 0;
>>> -  for (unsigned i = 0, e = AsmToks.size(); i != e; ++i) {
>>> -
>>> -    // Determine if this should be considered a new asm.
>>> -    bool isNewAsm = i == 0 || AsmToks[i].isAtStartOfLine() ||
>>> -      AsmToks[i].is(tok::kw_asm);
>>> -
>>> -    // Emit the previous asm string.
>>> -    if (i && isNewAsm) {
>>> -      AsmStrings[NumAsmStrings++] = Asm.c_str();
>>> -      if (AsmToks[i].is(tok::kw_asm)) {
>>> -        ++i; // Skip __asm
>>> -        assert (i != e && "Expected another token.");
>>> -      }
>>> -    }
>>> -
>>> -    // Start a new asm string with the opcode.
>>> -    if (isNewAsm) {
>>> -      AsmRegs[NumAsmStrings].resize(AsmToks.size());
>>> -      AsmNames[NumAsmStrings].resize(AsmToks.size());
>>> -
>>> -      StringRef Piece = AsmToks[i].getIdentifierInfo()->getName();
>>> -      // MS-style inline asm keywords require special handling.
>>> -      if (isMSAsmKeyword(Piece))
>>> -        IsSimple = false;
>>> -
>>> -      // TODO: Verify this is a valid opcode.
>>> -      Asm = Piece;
>>> -      continue;
>>> -    }
>>> -
>>> -    if (i && AsmToks[i].hasLeadingSpace())
>>> -      Asm += ' ';
>>> -
>>> -    // Check the operand(s).
>>> -    switch (AsmToks[i].getKind()) {
>>> -    default:
>>> -      IsSimple = false;
>>> -      Asm += getSpelling(SemaRef, AsmToks[i]);
>>> -      break;
>>> -    case tok::comma: Asm += ","; break;
>>> -    case tok::colon: Asm += ":"; break;
>>> -    case tok::l_square: Asm += "["; break;
>>> -    case tok::r_square: Asm += "]"; break;
>>> -    case tok::l_brace: Asm += "{"; break;
>>> -    case tok::r_brace: Asm += "}"; break;
>>> -    case tok::numeric_constant:
>>> -      Asm += getSpelling(SemaRef, AsmToks[i]);
>>> -      break;
>>> -    case tok::identifier: {
>>> -      IdentifierInfo *II = AsmToks[i].getIdentifierInfo();
>>> -      StringRef Name = II->getName();
>>> -
>>> -      // Valid register?
>>> -      if (TI.isValidGCCRegisterName(Name)) {
>>> -        AsmRegs[NumAsmStrings].set(i);
>>> -        Asm += Name;
>>> -        break;
>>> -      }
>>> -
>>> -      IsSimple = false;
>>> -
>>> -      // MS-style inline asm keywords require special handling.
>>> -      if (isMSAsmKeyword(Name)) {
>>> -        IsSimple = false;
>>> -        Asm += Name;
>>> -        break;
>>> -      }
>>> -
>>> -      // FIXME: Why are we missing this segment register?
>>> -      if (Name == "fs") {
>>> -        Asm += Name;
>>> -        break;
>>> -      }
>>> -
>>> -      // Lookup the identifier.
>>> -      // TODO: Someone with more experience with clang should verify this the
>>> -      // proper way of doing a symbol lookup.
>>> -      DeclarationName DeclName(II);
>>> -      Scope *CurScope = SemaRef.getCurScope();
>>> -      LookupResult R(SemaRef, DeclName, AsmLoc, Sema::LookupOrdinaryName);
>>> -      if (!SemaRef.LookupName(R, CurScope, false/*AllowBuiltinCreation*/))
>>> -        break;
>>> -
>>> -      assert (R.isSingleResult() && "Expected a single result?!");
>>> -      NamedDecl *Decl = R.getFoundDecl();
>>> -      switch (Decl->getKind()) {
>>> -      default:
>>> -        assert(0 && "Unknown decl kind.");
>>> -        break;
>>> -      case Decl::Var: {
>>> -      case Decl::ParmVar:
>>> -        AsmNames[NumAsmStrings].set(i);
>>> -
>>> -        VarDecl *Var = cast<VarDecl>(Decl);
>>> -        QualType Ty = Var->getType();
>>> -        (void)Ty; // Avoid warning.
>>> -        // TODO: Patch identifier with valid operand.  One potential idea is to
>>> -        // probe the backend with type information to guess the possible
>>> -        // operand.
>>> -        break;
>>> -      }
>>> -      }
>>> -      break;
>>> -    }
>>> -    }
>>> -  }
>>> -
>>> -  // Emit the final (and possibly only) asm string.
>>> -  AsmStrings[NumAsmStrings] = Asm.c_str();
>>> -}
>>> -
>>> -// Build the unmodified MSAsmString.
>>> -static std::string buildMSAsmString(Sema &SemaRef,
>>> -                                    ArrayRef<Token> AsmToks,
>>> -                                    unsigned &NumAsmStrings) {
>>> -  assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!");
>>> -  NumAsmStrings = 0;
>>> -
>>> -  SmallString<512> Asm;
>>> -  for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) {
>>> -    bool isNewAsm = i == 0 || AsmToks[i].isAtStartOfLine() ||
>>> -      AsmToks[i].is(tok::kw_asm);
>>> -
>>> -    if (isNewAsm) {
>>> -      ++NumAsmStrings;
>>> -      if (i)
>>> -        Asm += '\n';
>>> -      if (AsmToks[i].is(tok::kw_asm)) {
>>> -        i++; // Skip __asm
>>> -        assert (i != e && "Expected another token");
>>> -      }
>>> -    }
>>> -
>>> -    if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm)
>>> -      Asm += ' ';
>>> -
>>> -    Asm += getSpelling(SemaRef, AsmToks[i]);
>>> -  }
>>> -  return Asm.c_str();
>>> -}
>>> -
>>> -StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc,
>>> -                                SourceLocation LBraceLoc,
>>> -                                ArrayRef<Token> AsmToks,
>>> -                                SourceLocation EndLoc) {
>>> -  // MS-style inline assembly is not fully supported, so emit a warning.
>>> -  Diag(AsmLoc, diag::warn_unsupported_msasm);
>>> -  SmallVector<StringRef,4> Clobbers;
>>> -  std::set<std::string> ClobberRegs;
>>> -  SmallVector<IdentifierInfo*, 4> Inputs;
>>> -  SmallVector<IdentifierInfo*, 4> Outputs;
>>> -
>>> -  // Empty asm statements don't need to instantiate the AsmParser, etc.
>>> -  if (AsmToks.empty()) {
>>> -    StringRef AsmString;
>>> -    MSAsmStmt *NS =
>>> -      new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true,
>>> -                              /*IsVolatile*/ true, AsmToks, Inputs, Outputs,
>>> -                              AsmString, Clobbers, EndLoc);
>>> -    return Owned(NS);
>>> -  }
>>> -
>>> -  unsigned NumAsmStrings;
>>> -  std::string AsmString = buildMSAsmString(*this, AsmToks, NumAsmStrings);
>>> -
>>> -  bool IsSimple;
>>> -  std::vector<llvm::BitVector> Regs;
>>> -  std::vector<llvm::BitVector> Names;
>>> -  std::vector<std::string> PatchedAsmStrings;
>>> -
>>> -  Regs.resize(NumAsmStrings);
>>> -  Names.resize(NumAsmStrings);
>>> -  PatchedAsmStrings.resize(NumAsmStrings);
>>> -
>>> -  // Rewrite operands to appease the AsmParser.
>>> -  patchMSAsmStrings(*this, IsSimple, AsmLoc, AsmToks,
>>> -                    Context.getTargetInfo(), Regs, Names, PatchedAsmStrings);
>>> -
>>> -  // patchMSAsmStrings doesn't correctly patch non-simple asm statements.
>>> -  if (!IsSimple) {
>>> -    MSAsmStmt *NS =
>>> -      new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true,
>>> -                              /*IsVolatile*/ true, AsmToks, Inputs, Outputs,
>>> -                              AsmString, Clobbers, EndLoc);
>>> -    return Owned(NS);
>>> -  }
>>> -
>>> -  // Initialize targets and assembly printers/parsers.
>>> -  llvm::InitializeAllTargetInfos();
>>> -  llvm::InitializeAllTargetMCs();
>>> -  llvm::InitializeAllAsmParsers();
>>> -
>>> -  // Get the target specific parser.
>>> -  std::string Error;
>>> -  const std::string &TT = Context.getTargetInfo().getTriple().getTriple();
>>> -  const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error));
>>> -
>>> -  OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT));
>>> -  OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
>>> -  OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
>>> -  OwningPtr<llvm::MCSubtargetInfo>
>>> -    STI(TheTarget->createMCSubtargetInfo(TT, "", ""));
>>> -
>>> -  for (unsigned i = 0, e = PatchedAsmStrings.size(); i != e; ++i) {
>>> -    llvm::SourceMgr SrcMgr;
>>> -    llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr);
>>> -    llvm::MemoryBuffer *Buffer =
>>> -      llvm::MemoryBuffer::getMemBuffer(PatchedAsmStrings[i], "<inline asm>");
>>> -
>>> -    // Tell SrcMgr about this buffer, which is what the parser will pick up.
>>> -    SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc());
>>> -
>>> -    OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
>>> -    OwningPtr<llvm::MCAsmParser>
>>> -      Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));
>>> -    OwningPtr<llvm::MCTargetAsmParser>
>>> -      TargetParser(TheTarget->createMCAsmParser(*STI, *Parser));
>>> -    // Change to the Intel dialect.
>>> -    Parser->setAssemblerDialect(1);
>>> -    Parser->setTargetParser(*TargetParser.get());
>>> -
>>> -    // Prime the lexer.
>>> -    Parser->Lex();
>>> -
>>> -    // Parse the opcode.
>>> -    StringRef IDVal;
>>> -    Parser->ParseIdentifier(IDVal);
>>> -
>>> -    // Canonicalize the opcode to lower case.
>>> -    SmallString<128> Opcode;
>>> -    for (unsigned i = 0, e = IDVal.size(); i != e; ++i)
>>> -      Opcode.push_back(tolower(IDVal[i]));
>>> -
>>> -    // Parse the operands.
>>> -    llvm::SMLoc IDLoc;
>>> -    SmallVector<llvm::MCParsedAsmOperand*, 8> Operands;
>>> -    bool HadError = TargetParser->ParseInstruction(Opcode.str(), IDLoc,
>>> -                                                   Operands);
>>> -    assert (!HadError && "Unexpected error parsing instruction");
>>> -
>>> -    // Match the MCInstr.
>>> -    SmallVector<llvm::MCInst, 2> Instrs;
>>> -    HadError = TargetParser->MatchInstruction(IDLoc, Operands, Instrs);
>>> -    assert (!HadError && "Unexpected error matching instruction");
>>> -    assert ((Instrs.size() == 1) && "Expected only a single instruction.");
>>> -
>>> -    // Get the instruction descriptor.
>>> -    llvm::MCInst Inst = Instrs[0];
>>> -    const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo();
>>> -    const llvm::MCInstrDesc &Desc = MII->get(Inst.getOpcode());
>>> -    llvm::MCInstPrinter *IP =
>>> -      TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI);
>>> -
>>> -    // Build the list of clobbers.
>>> -    for (unsigned i = 0, e = Desc.getNumDefs(); i != e; ++i) {
>>> -      const llvm::MCOperand &Op = Inst.getOperand(i);
>>> -      if (!Op.isReg())
>>> -        continue;
>>> -
>>> -      std::string Reg;
>>> -      llvm::raw_string_ostream OS(Reg);
>>> -      IP->printRegName(OS, Op.getReg());
>>> -
>>> -      StringRef Clobber(OS.str());
>>> -      if (!Context.getTargetInfo().isValidClobber(Clobber))
>>> -        return StmtError(Diag(AsmLoc, diag::err_asm_unknown_register_name) <<
>>> -                         Clobber);
>>> -      ClobberRegs.insert(Reg);
>>> -    }
>>> -  }
>>> -  for (std::set<std::string>::iterator I = ClobberRegs.begin(),
>>> -         E = ClobberRegs.end(); I != E; ++I)
>>> -    Clobbers.push_back(*I);
>>> -
>>> -  MSAsmStmt *NS =
>>> -    new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
>>> -                            /*IsVolatile*/ true, AsmToks, Inputs, Outputs,
>>> -                            AsmString, Clobbers, EndLoc);
>>> -  return Owned(NS);
>>> -}
>>> -
>>> StmtResult
>>> Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc,
>>>                            SourceLocation RParen, Decl *Parm,
>>> 
>>> Added: cfe/trunk/lib/Sema/SemaStmtAsm.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmtAsm.cpp?rev=162132&view=auto
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/SemaStmtAsm.cpp (added)
>>> +++ cfe/trunk/lib/Sema/SemaStmtAsm.cpp Fri Aug 17 16:19:40 2012
>>> @@ -0,0 +1,635 @@
>>> +//===--- SemaStmtAsm.cpp - Semantic Analysis for Statements ---------------===//
>>> +//
>>> +//                     The LLVM Compiler Infrastructure
>>> +//
>>> +// This file is distributed under the University of Illinois Open Source
>>> +// License. See LICENSE.TXT for details.
>>> +//
>>> +//===----------------------------------------------------------------------===//
>>> +//
>>> +//  This file implements semantic analysis for inline asm statements.
>>> +//
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +#include "clang/Sema/SemaInternal.h"
>>> +#include "clang/Sema/Scope.h"
>>> +#include "clang/Sema/ScopeInfo.h"
>>> +#include "clang/Sema/Initialization.h"
>>> +#include "clang/Sema/Lookup.h"
>>> +#include "clang/AST/TypeLoc.h"
>>> +#include "clang/Lex/Preprocessor.h"
>>> +#include "clang/Basic/TargetInfo.h"
>>> +#include "llvm/ADT/ArrayRef.h"
>>> +#include "llvm/ADT/BitVector.h"
>>> +#include "llvm/ADT/SmallString.h"
>>> +#include "llvm/MC/MCAsmInfo.h"
>>> +#include "llvm/MC/MCContext.h"
>>> +#include "llvm/MC/MCInst.h"
>>> +#include "llvm/MC/MCInstPrinter.h"
>>> +#include "llvm/MC/MCInstrInfo.h"
>>> +#include "llvm/MC/MCObjectFileInfo.h"
>>> +#include "llvm/MC/MCRegisterInfo.h"
>>> +#include "llvm/MC/MCStreamer.h"
>>> +#include "llvm/MC/MCSubtargetInfo.h"
>>> +#include "llvm/MC/MCTargetAsmParser.h"
>>> +#include "llvm/MC/MCParser/MCAsmLexer.h"
>>> +#include "llvm/MC/MCParser/MCAsmParser.h"
>>> +#include "llvm/Support/SourceMgr.h"
>>> +#include "llvm/Support/TargetRegistry.h"
>>> +#include "llvm/Support/TargetSelect.h"
>>> +using namespace clang;
>>> +using namespace sema;
>>> +
>>> +/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently
>>> +/// ignore "noop" casts in places where an lvalue is required by an inline asm.
>>> +/// We emulate this behavior when -fheinous-gnu-extensions is specified, but
>>> +/// provide a strong guidance to not use it.
>>> +///
>>> +/// This method checks to see if the argument is an acceptable l-value and
>>> +/// returns false if it is a case we can handle.
>>> +static bool CheckAsmLValue(const Expr *E, Sema &S) {
>>> +  // Type dependent expressions will be checked during instantiation.
>>> +  if (E->isTypeDependent())
>>> +    return false;
>>> +
>>> +  if (E->isLValue())
>>> +    return false;  // Cool, this is an lvalue.
>>> +
>>> +  // Okay, this is not an lvalue, but perhaps it is the result of a cast that we
>>> +  // are supposed to allow.
>>> +  const Expr *E2 = E->IgnoreParenNoopCasts(S.Context);
>>> +  if (E != E2 && E2->isLValue()) {
>>> +    if (!S.getLangOpts().HeinousExtensions)
>>> +      S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue)
>>> +        << E->getSourceRange();
>>> +    else
>>> +      S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
>>> +        << E->getSourceRange();
>>> +    // Accept, even if we emitted an error diagnostic.
>>> +    return false;
>>> +  }
>>> +
>>> +  // None of the above, just randomly invalid non-lvalue.
>>> +  return true;
>>> +}
>>> +
>>> +/// isOperandMentioned - Return true if the specified operand # is mentioned
>>> +/// anywhere in the decomposed asm string.
>>> +static bool isOperandMentioned(unsigned OpNo,
>>> +                         ArrayRef<AsmStmt::AsmStringPiece> AsmStrPieces) {
>>> +  for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) {
>>> +    const AsmStmt::AsmStringPiece &Piece = AsmStrPieces[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() == OpNo)
>>> +      return true;
>>> +  }
>>> +  return false;
>>> +}
>>> +
>>> +StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple,
>>> +                              bool IsVolatile, unsigned NumOutputs,
>>> +                              unsigned NumInputs, IdentifierInfo **Names,
>>> +                              MultiExprArg constraints, MultiExprArg exprs,
>>> +                              Expr *asmString, MultiExprArg clobbers,
>>> +                              SourceLocation RParenLoc, bool MSAsm) {
>>> +  unsigned NumClobbers = clobbers.size();
>>> +  StringLiteral **Constraints =
>>> +    reinterpret_cast<StringLiteral**>(constraints.get());
>>> +  Expr **Exprs = exprs.get();
>>> +  StringLiteral *AsmString = cast<StringLiteral>(asmString);
>>> +  StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.get());
>>> +
>>> +  SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;
>>> +
>>> +  // The parser verifies that there is a string literal here.
>>> +  if (!AsmString->isAscii())
>>> +    return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character)
>>> +      << AsmString->getSourceRange());
>>> +
>>> +  for (unsigned i = 0; i != NumOutputs; i++) {
>>> +    StringLiteral *Literal = Constraints[i];
>>> +    if (!Literal->isAscii())
>>> +      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
>>> +        << Literal->getSourceRange());
>>> +
>>> +    StringRef OutputName;
>>> +    if (Names[i])
>>> +      OutputName = Names[i]->getName();
>>> +
>>> +    TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
>>> +    if (!Context.getTargetInfo().validateOutputConstraint(Info))
>>> +      return StmtError(Diag(Literal->getLocStart(),
>>> +                            diag::err_asm_invalid_output_constraint)
>>> +                       << Info.getConstraintStr());
>>> +
>>> +    // Check that the output exprs are valid lvalues.
>>> +    Expr *OutputExpr = Exprs[i];
>>> +    if (CheckAsmLValue(OutputExpr, *this)) {
>>> +      return StmtError(Diag(OutputExpr->getLocStart(),
>>> +                  diag::err_asm_invalid_lvalue_in_output)
>>> +        << OutputExpr->getSourceRange());
>>> +    }
>>> +
>>> +    OutputConstraintInfos.push_back(Info);
>>> +  }
>>> +
>>> +  SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;
>>> +
>>> +  for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
>>> +    StringLiteral *Literal = Constraints[i];
>>> +    if (!Literal->isAscii())
>>> +      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
>>> +        << Literal->getSourceRange());
>>> +
>>> +    StringRef InputName;
>>> +    if (Names[i])
>>> +      InputName = Names[i]->getName();
>>> +
>>> +    TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
>>> +    if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(),
>>> +                                                NumOutputs, Info)) {
>>> +      return StmtError(Diag(Literal->getLocStart(),
>>> +                            diag::err_asm_invalid_input_constraint)
>>> +                       << Info.getConstraintStr());
>>> +    }
>>> +
>>> +    Expr *InputExpr = Exprs[i];
>>> +
>>> +    // Only allow void types for memory constraints.
>>> +    if (Info.allowsMemory() && !Info.allowsRegister()) {
>>> +      if (CheckAsmLValue(InputExpr, *this))
>>> +        return StmtError(Diag(InputExpr->getLocStart(),
>>> +                              diag::err_asm_invalid_lvalue_in_input)
>>> +                         << Info.getConstraintStr()
>>> +                         << InputExpr->getSourceRange());
>>> +    }
>>> +
>>> +    if (Info.allowsRegister()) {
>>> +      if (InputExpr->getType()->isVoidType()) {
>>> +        return StmtError(Diag(InputExpr->getLocStart(),
>>> +                              diag::err_asm_invalid_type_in_input)
>>> +          << InputExpr->getType() << Info.getConstraintStr()
>>> +          << InputExpr->getSourceRange());
>>> +      }
>>> +    }
>>> +
>>> +    ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
>>> +    if (Result.isInvalid())
>>> +      return StmtError();
>>> +
>>> +    Exprs[i] = Result.take();
>>> +    InputConstraintInfos.push_back(Info);
>>> +  }
>>> +
>>> +  // Check that the clobbers are valid.
>>> +  for (unsigned i = 0; i != NumClobbers; i++) {
>>> +    StringLiteral *Literal = Clobbers[i];
>>> +    if (!Literal->isAscii())
>>> +      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
>>> +        << Literal->getSourceRange());
>>> +
>>> +    StringRef Clobber = Literal->getString();
>>> +
>>> +    if (!Context.getTargetInfo().isValidClobber(Clobber))
>>> +      return StmtError(Diag(Literal->getLocStart(),
>>> +                  diag::err_asm_unknown_register_name) << Clobber);
>>> +  }
>>> +
>>> +  AsmStmt *NS =
>>> +    new (Context) AsmStmt(Context, AsmLoc, IsSimple, IsVolatile, MSAsm,
>>> +                          NumOutputs, NumInputs, Names, Constraints, Exprs,
>>> +                          AsmString, NumClobbers, Clobbers, RParenLoc);
>>> +  // Validate the asm string, ensuring it makes sense given the operands we
>>> +  // have.
>>> +  SmallVector<AsmStmt::AsmStringPiece, 8> Pieces;
>>> +  unsigned DiagOffs;
>>> +  if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) {
>>> +    Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
>>> +           << AsmString->getSourceRange();
>>> +    return StmtError();
>>> +  }
>>> +
>>> +  // Validate tied input operands for type mismatches.
>>> +  for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
>>> +    TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
>>> +
>>> +    // If this is a tied constraint, verify that the output and input have
>>> +    // either exactly the same type, or that they are int/ptr operands with the
>>> +    // same size (int/long, int*/long, are ok etc).
>>> +    if (!Info.hasTiedOperand()) continue;
>>> +
>>> +    unsigned TiedTo = Info.getTiedOperand();
>>> +    unsigned InputOpNo = i+NumOutputs;
>>> +    Expr *OutputExpr = Exprs[TiedTo];
>>> +    Expr *InputExpr = Exprs[InputOpNo];
>>> +
>>> +    if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent())
>>> +      continue;
>>> +
>>> +    QualType InTy = InputExpr->getType();
>>> +    QualType OutTy = OutputExpr->getType();
>>> +    if (Context.hasSameType(InTy, OutTy))
>>> +      continue;  // All types can be tied to themselves.
>>> +
>>> +    // 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->isRealFloatingType())
>>> +      InputDomain = AD_FP;
>>> +    else
>>> +      InputDomain = AD_Other;
>>> +
>>> +    if (OutTy->isIntegerType() || OutTy->isPointerType())
>>> +      OutputDomain = AD_Int;
>>> +    else if (OutTy->isRealFloatingType())
>>> +      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 the smaller one to a larger input and the asm string
>>> +    // won't notice.
>>> +    bool SmallerValueMentioned = false;
>>> +
>>> +    // 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(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".
>>> +      SmallerValueMentioned |= InSize < OutSize;
>>> +    }
>>> +    if (isOperandMentioned(TiedTo, Pieces)) {
>>> +      // If this is a reference to the output, and if the output is the larger
>>> +      // value, then it's ok because we'll promote the input to the larger type.
>>> +      SmallerValueMentioned |= OutSize < InSize;
>>> +    }
>>> +
>>> +    // 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;
>>> +
>>> +    // 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)) {
>>> +      CastKind castKind =
>>> +        (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast);
>>> +      InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take();
>>> +      Exprs[InputOpNo] = InputExpr;
>>> +      NS->setInputExpr(i, InputExpr);
>>> +      continue;
>>> +    }
>>> +
>>> +    Diag(InputExpr->getLocStart(),
>>> +         diag::err_asm_tying_incompatible_types)
>>> +      << InTy << OutTy << OutputExpr->getSourceRange()
>>> +      << InputExpr->getSourceRange();
>>> +    return StmtError();
>>> +  }
>>> +
>>> +  return Owned(NS);
>>> +}
>>> +
>>> +// isMSAsmKeyword - Return true if this is an MS-style inline asm keyword. These
>>> +// require special handling.
>>> +static bool isMSAsmKeyword(StringRef Name) {
>>> +  bool Ret = llvm::StringSwitch<bool>(Name)
>>> +    .Cases("EVEN", "ALIGN", true) // Alignment directives.
>>> +    .Cases("LENGTH", "SIZE", "TYPE", true) // Type and variable sizes.
>>> +    .Case("_emit", true) // _emit Pseudoinstruction.
>>> +    .Default(false);
>>> +  return Ret;
>>> +}
>>> +
>>> +static StringRef getSpelling(Sema &SemaRef, Token AsmTok) {
>>> +  StringRef Asm;
>>> +  SmallString<512> TokenBuf;
>>> +  TokenBuf.resize(512);
>>> +  bool StringInvalid = false;
>>> +  Asm = SemaRef.PP.getSpelling(AsmTok, TokenBuf, &StringInvalid);
>>> +  assert (!StringInvalid && "Expected valid string!");
>>> +  return Asm;
>>> +}
>>> +
>>> +static void patchMSAsmStrings(Sema &SemaRef, bool &IsSimple,
>>> +                              SourceLocation AsmLoc,
>>> +                              ArrayRef<Token> AsmToks,
>>> +                              const TargetInfo &TI,
>>> +                              std::vector<llvm::BitVector> &AsmRegs,
>>> +                              std::vector<llvm::BitVector> &AsmNames,
>>> +                              std::vector<std::string> &AsmStrings) {
>>> +  assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!");
>>> +
>>> +  // Assume simple asm stmt until we parse a non-register identifer (or we just
>>> +  // need to bail gracefully).
>>> +  IsSimple = true;
>>> +
>>> +  SmallString<512> Asm;
>>> +  unsigned NumAsmStrings = 0;
>>> +  for (unsigned i = 0, e = AsmToks.size(); i != e; ++i) {
>>> +
>>> +    // Determine if this should be considered a new asm.
>>> +    bool isNewAsm = i == 0 || AsmToks[i].isAtStartOfLine() ||
>>> +      AsmToks[i].is(tok::kw_asm);
>>> +
>>> +    // Emit the previous asm string.
>>> +    if (i && isNewAsm) {
>>> +      AsmStrings[NumAsmStrings++] = Asm.c_str();
>>> +      if (AsmToks[i].is(tok::kw_asm)) {
>>> +        ++i; // Skip __asm
>>> +        assert (i != e && "Expected another token.");
>>> +      }
>>> +    }
>>> +
>>> +    // Start a new asm string with the opcode.
>>> +    if (isNewAsm) {
>>> +      AsmRegs[NumAsmStrings].resize(AsmToks.size());
>>> +      AsmNames[NumAsmStrings].resize(AsmToks.size());
>>> +
>>> +      StringRef Piece = AsmToks[i].getIdentifierInfo()->getName();
>>> +      // MS-style inline asm keywords require special handling.
>>> +      if (isMSAsmKeyword(Piece))
>>> +        IsSimple = false;
>>> +
>>> +      // TODO: Verify this is a valid opcode.
>>> +      Asm = Piece;
>>> +      continue;
>>> +    }
>>> +
>>> +    if (i && AsmToks[i].hasLeadingSpace())
>>> +      Asm += ' ';
>>> +
>>> +    // Check the operand(s).
>>> +    switch (AsmToks[i].getKind()) {
>>> +    default:
>>> +      IsSimple = false;
>>> +      Asm += getSpelling(SemaRef, AsmToks[i]);
>>> +      break;
>>> +    case tok::comma: Asm += ","; break;
>>> +    case tok::colon: Asm += ":"; break;
>>> +    case tok::l_square: Asm += "["; break;
>>> +    case tok::r_square: Asm += "]"; break;
>>> +    case tok::l_brace: Asm += "{"; break;
>>> +    case tok::r_brace: Asm += "}"; break;
>>> +    case tok::numeric_constant:
>>> +      Asm += getSpelling(SemaRef, AsmToks[i]);
>>> +      break;
>>> +    case tok::identifier: {
>>> +      IdentifierInfo *II = AsmToks[i].getIdentifierInfo();
>>> +      StringRef Name = II->getName();
>>> +
>>> +      // Valid register?
>>> +      if (TI.isValidGCCRegisterName(Name)) {
>>> +        AsmRegs[NumAsmStrings].set(i);
>>> +        Asm += Name;
>>> +        break;
>>> +      }
>>> +
>>> +      IsSimple = false;
>>> +
>>> +      // MS-style inline asm keywords require special handling.
>>> +      if (isMSAsmKeyword(Name)) {
>>> +        IsSimple = false;
>>> +        Asm += Name;
>>> +        break;
>>> +      }
>>> +
>>> +      // FIXME: Why are we missing this segment register?
>>> +      if (Name == "fs") {
>>> +        Asm += Name;
>>> +        break;
>>> +      }
>>> +
>>> +      // Lookup the identifier.
>>> +      // TODO: Someone with more experience with clang should verify this the
>>> +      // proper way of doing a symbol lookup.
>>> +      DeclarationName DeclName(II);
>>> +      Scope *CurScope = SemaRef.getCurScope();
>>> +      LookupResult R(SemaRef, DeclName, AsmLoc, Sema::LookupOrdinaryName);
>>> +      if (!SemaRef.LookupName(R, CurScope, false/*AllowBuiltinCreation*/))
>>> +        break;
>>> +
>>> +      assert (R.isSingleResult() && "Expected a single result?!");
>>> +      NamedDecl *Decl = R.getFoundDecl();
>>> +      switch (Decl->getKind()) {
>>> +      default:
>>> +        assert(0 && "Unknown decl kind.");
>>> +        break;
>>> +      case Decl::Var: {
>>> +      case Decl::ParmVar:
>>> +        AsmNames[NumAsmStrings].set(i);
>>> +
>>> +        VarDecl *Var = cast<VarDecl>(Decl);
>>> +        QualType Ty = Var->getType();
>>> +        (void)Ty; // Avoid warning.
>>> +        // TODO: Patch identifier with valid operand.  One potential idea is to
>>> +        // probe the backend with type information to guess the possible
>>> +        // operand.
>>> +        break;
>>> +      }
>>> +      }
>>> +      break;
>>> +    }
>>> +    }
>>> +  }
>>> +
>>> +  // Emit the final (and possibly only) asm string.
>>> +  AsmStrings[NumAsmStrings] = Asm.c_str();
>>> +}
>>> +
>>> +// Build the unmodified MSAsmString.
>>> +static std::string buildMSAsmString(Sema &SemaRef,
>>> +                                    ArrayRef<Token> AsmToks,
>>> +                                    unsigned &NumAsmStrings) {
>>> +  assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!");
>>> +  NumAsmStrings = 0;
>>> +
>>> +  SmallString<512> Asm;
>>> +  for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) {
>>> +    bool isNewAsm = i == 0 || AsmToks[i].isAtStartOfLine() ||
>>> +      AsmToks[i].is(tok::kw_asm);
>>> +
>>> +    if (isNewAsm) {
>>> +      ++NumAsmStrings;
>>> +      if (i)
>>> +        Asm += '\n';
>>> +      if (AsmToks[i].is(tok::kw_asm)) {
>>> +        i++; // Skip __asm
>>> +        assert (i != e && "Expected another token");
>>> +      }
>>> +    }
>>> +
>>> +    if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm)
>>> +      Asm += ' ';
>>> +
>>> +    Asm += getSpelling(SemaRef, AsmToks[i]);
>>> +  }
>>> +  return Asm.c_str();
>>> +}
>>> +
>>> +StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc,
>>> +                                SourceLocation LBraceLoc,
>>> +                                ArrayRef<Token> AsmToks,
>>> +                                SourceLocation EndLoc) {
>>> +  // MS-style inline assembly is not fully supported, so emit a warning.
>>> +  Diag(AsmLoc, diag::warn_unsupported_msasm);
>>> +  SmallVector<StringRef,4> Clobbers;
>>> +  std::set<std::string> ClobberRegs;
>>> +  SmallVector<IdentifierInfo*, 4> Inputs;
>>> +  SmallVector<IdentifierInfo*, 4> Outputs;
>>> +
>>> +  // Empty asm statements don't need to instantiate the AsmParser, etc.
>>> +  if (AsmToks.empty()) {
>>> +    StringRef AsmString;
>>> +    MSAsmStmt *NS =
>>> +      new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true,
>>> +                              /*IsVolatile*/ true, AsmToks, Inputs, Outputs,
>>> +                              AsmString, Clobbers, EndLoc);
>>> +    return Owned(NS);
>>> +  }
>>> +
>>> +  unsigned NumAsmStrings;
>>> +  std::string AsmString = buildMSAsmString(*this, AsmToks, NumAsmStrings);
>>> +
>>> +  bool IsSimple;
>>> +  std::vector<llvm::BitVector> Regs;
>>> +  std::vector<llvm::BitVector> Names;
>>> +  std::vector<std::string> PatchedAsmStrings;
>>> +
>>> +  Regs.resize(NumAsmStrings);
>>> +  Names.resize(NumAsmStrings);
>>> +  PatchedAsmStrings.resize(NumAsmStrings);
>>> +
>>> +  // Rewrite operands to appease the AsmParser.
>>> +  patchMSAsmStrings(*this, IsSimple, AsmLoc, AsmToks,
>>> +                    Context.getTargetInfo(), Regs, Names, PatchedAsmStrings);
>>> +
>>> +  // patchMSAsmStrings doesn't correctly patch non-simple asm statements.
>>> +  if (!IsSimple) {
>>> +    MSAsmStmt *NS =
>>> +      new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true,
>>> +                              /*IsVolatile*/ true, AsmToks, Inputs, Outputs,
>>> +                              AsmString, Clobbers, EndLoc);
>>> +    return Owned(NS);
>>> +  }
>>> +
>>> +  // Initialize targets and assembly printers/parsers.
>>> +  llvm::InitializeAllTargetInfos();
>>> +  llvm::InitializeAllTargetMCs();
>>> +  llvm::InitializeAllAsmParsers();
>>> +
>>> +  // Get the target specific parser.
>>> +  std::string Error;
>>> +  const std::string &TT = Context.getTargetInfo().getTriple().getTriple();
>>> +  const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error));
>>> +
>>> +  OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT));
>>> +  OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
>>> +  OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
>>> +  OwningPtr<llvm::MCSubtargetInfo>
>>> +    STI(TheTarget->createMCSubtargetInfo(TT, "", ""));
>>> +
>>> +  for (unsigned i = 0, e = PatchedAsmStrings.size(); i != e; ++i) {
>>> +    llvm::SourceMgr SrcMgr;
>>> +    llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr);
>>> +    llvm::MemoryBuffer *Buffer =
>>> +      llvm::MemoryBuffer::getMemBuffer(PatchedAsmStrings[i], "<inline asm>");
>>> +
>>> +    // Tell SrcMgr about this buffer, which is what the parser will pick up.
>>> +    SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc());
>>> +
>>> +    OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
>>> +    OwningPtr<llvm::MCAsmParser>
>>> +      Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));
>>> +    OwningPtr<llvm::MCTargetAsmParser>
>>> +      TargetParser(TheTarget->createMCAsmParser(*STI, *Parser));
>>> +    // Change to the Intel dialect.
>>> +    Parser->setAssemblerDialect(1);
>>> +    Parser->setTargetParser(*TargetParser.get());
>>> +
>>> +    // Prime the lexer.
>>> +    Parser->Lex();
>>> +
>>> +    // Parse the opcode.
>>> +    StringRef IDVal;
>>> +    Parser->ParseIdentifier(IDVal);
>>> +
>>> +    // Canonicalize the opcode to lower case.
>>> +    SmallString<128> Opcode;
>>> +    for (unsigned i = 0, e = IDVal.size(); i != e; ++i)
>>> +      Opcode.push_back(tolower(IDVal[i]));
>>> +
>>> +    // Parse the operands.
>>> +    llvm::SMLoc IDLoc;
>>> +    SmallVector<llvm::MCParsedAsmOperand*, 8> Operands;
>>> +    bool HadError = TargetParser->ParseInstruction(Opcode.str(), IDLoc,
>>> +                                                   Operands);
>>> +    assert (!HadError && "Unexpected error parsing instruction");
>>> +
>>> +    // Match the MCInstr.
>>> +    SmallVector<llvm::MCInst, 2> Instrs;
>>> +    HadError = TargetParser->MatchInstruction(IDLoc, Operands, Instrs);
>>> +    assert (!HadError && "Unexpected error matching instruction");
>>> +    assert ((Instrs.size() == 1) && "Expected only a single instruction.");
>>> +
>>> +    // Get the instruction descriptor.
>>> +    llvm::MCInst Inst = Instrs[0];
>>> +    const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo();
>>> +    const llvm::MCInstrDesc &Desc = MII->get(Inst.getOpcode());
>>> +    llvm::MCInstPrinter *IP =
>>> +      TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI);
>>> +
>>> +    // Build the list of clobbers.
>>> +    for (unsigned i = 0, e = Desc.getNumDefs(); i != e; ++i) {
>>> +      const llvm::MCOperand &Op = Inst.getOperand(i);
>>> +      if (!Op.isReg())
>>> +        continue;
>>> +
>>> +      std::string Reg;
>>> +      llvm::raw_string_ostream OS(Reg);
>>> +      IP->printRegName(OS, Op.getReg());
>>> +
>>> +      StringRef Clobber(OS.str());
>>> +      if (!Context.getTargetInfo().isValidClobber(Clobber))
>>> +        return StmtError(Diag(AsmLoc, diag::err_asm_unknown_register_name) <<
>>> +                         Clobber);
>>> +      ClobberRegs.insert(Reg);
>>> +    }
>>> +  }
>>> +  for (std::set<std::string>::iterator I = ClobberRegs.begin(),
>>> +         E = ClobberRegs.end(); I != E; ++I)
>>> +    Clobbers.push_back(*I);
>>> +
>>> +  MSAsmStmt *NS =
>>> +    new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
>>> +                            /*IsVolatile*/ true, AsmToks, Inputs, Outputs,
>>> +                            AsmString, Clobbers, EndLoc);
>>> +  return Owned(NS);
>>> +}
>>> 
>>> 
>>> _______________________________________________
>>> cfe-commits mailing list
>>> cfe-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>> 
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits





More information about the cfe-commits mailing list