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

Sean Silva silvas at purdue.edu
Wed Aug 22 18:37:32 PDT 2012


+    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'.

--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




More information about the cfe-commits mailing list