SemaStmtAsm.cpp revision e54cba1ec0b0e498ee67d200289035797932e714
13d45a7739bae1e9c53c94ebb38c4339bd8ec0ca6Chad Rosier//===--- SemaStmtAsm.cpp - Semantic Analysis for Asm Statements -----------===//
24b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier//
34b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier//                     The LLVM Compiler Infrastructure
44b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier//
54b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier// This file is distributed under the University of Illinois Open Source
64b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier// License. See LICENSE.TXT for details.
74b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier//
84b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier//===----------------------------------------------------------------------===//
94b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier//
104b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier//  This file implements semantic analysis for inline asm statements.
114b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier//
124b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier//===----------------------------------------------------------------------===//
134b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
144b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "clang/Sema/SemaInternal.h"
154b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "clang/Sema/Scope.h"
164b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "clang/Sema/ScopeInfo.h"
174b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "clang/Sema/Initialization.h"
184b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "clang/Sema/Lookup.h"
194b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "clang/AST/TypeLoc.h"
204b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "clang/Lex/Preprocessor.h"
214b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "clang/Basic/TargetInfo.h"
224b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/ADT/ArrayRef.h"
234b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/ADT/BitVector.h"
244b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/ADT/SmallString.h"
254b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCAsmInfo.h"
264b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCContext.h"
276e97be719edb4e3b9ac15353e79c60406b3dc429Chad Rosier#include "llvm/MC/MCExpr.h"
284b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCInst.h"
294b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCInstPrinter.h"
304b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCInstrInfo.h"
314b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCObjectFileInfo.h"
324b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCRegisterInfo.h"
334b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCStreamer.h"
344b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCSubtargetInfo.h"
356e97be719edb4e3b9ac15353e79c60406b3dc429Chad Rosier#include "llvm/MC/MCSymbol.h"
364b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCTargetAsmParser.h"
374b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCParser/MCAsmLexer.h"
384b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCParser/MCAsmParser.h"
39fb700265b6e452a3cfd3abc73102fef11d103d4aChad Rosier#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
404b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/Support/SourceMgr.h"
414b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/Support/TargetRegistry.h"
424b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/Support/TargetSelect.h"
434b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosierusing namespace clang;
444b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosierusing namespace sema;
454b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
464b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently
474b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier/// ignore "noop" casts in places where an lvalue is required by an inline asm.
484b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier/// We emulate this behavior when -fheinous-gnu-extensions is specified, but
494b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier/// provide a strong guidance to not use it.
504b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier///
514b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier/// This method checks to see if the argument is an acceptable l-value and
524b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier/// returns false if it is a case we can handle.
534b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosierstatic bool CheckAsmLValue(const Expr *E, Sema &S) {
544b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  // Type dependent expressions will be checked during instantiation.
554b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  if (E->isTypeDependent())
564b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    return false;
574b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
584b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  if (E->isLValue())
594b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    return false;  // Cool, this is an lvalue.
604b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
614b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  // Okay, this is not an lvalue, but perhaps it is the result of a cast that we
624b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  // are supposed to allow.
634b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  const Expr *E2 = E->IgnoreParenNoopCasts(S.Context);
644b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  if (E != E2 && E2->isLValue()) {
654b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (!S.getLangOpts().HeinousExtensions)
664b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue)
674b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier        << E->getSourceRange();
684b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    else
694b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
704b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier        << E->getSourceRange();
714b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // Accept, even if we emitted an error diagnostic.
724b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    return false;
734b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  }
744b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
754b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  // None of the above, just randomly invalid non-lvalue.
764b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  return true;
774b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier}
784b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
794b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier/// isOperandMentioned - Return true if the specified operand # is mentioned
804b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier/// anywhere in the decomposed asm string.
814b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosierstatic bool isOperandMentioned(unsigned OpNo,
82df5faf5e7ae6823d0af0b801c4ac26d47f2cee97Chad Rosier                         ArrayRef<GCCAsmStmt::AsmStringPiece> AsmStrPieces) {
834b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) {
84df5faf5e7ae6823d0af0b801c4ac26d47f2cee97Chad Rosier    const GCCAsmStmt::AsmStringPiece &Piece = AsmStrPieces[p];
854b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (!Piece.isOperand()) continue;
864b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
874b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // If this is a reference to the input and if the input was the smaller
884b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // one, then we have to reject this asm.
894b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (Piece.getOperandNo() == OpNo)
904b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      return true;
914b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  }
924b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  return false;
934b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier}
944b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
95df5faf5e7ae6823d0af0b801c4ac26d47f2cee97Chad RosierStmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
96df5faf5e7ae6823d0af0b801c4ac26d47f2cee97Chad Rosier                                 bool IsVolatile, unsigned NumOutputs,
97df5faf5e7ae6823d0af0b801c4ac26d47f2cee97Chad Rosier                                 unsigned NumInputs, IdentifierInfo **Names,
98df5faf5e7ae6823d0af0b801c4ac26d47f2cee97Chad Rosier                                 MultiExprArg constraints, MultiExprArg exprs,
99df5faf5e7ae6823d0af0b801c4ac26d47f2cee97Chad Rosier                                 Expr *asmString, MultiExprArg clobbers,
100df5faf5e7ae6823d0af0b801c4ac26d47f2cee97Chad Rosier                                 SourceLocation RParenLoc) {
1014b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  unsigned NumClobbers = clobbers.size();
1024b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  StringLiteral **Constraints =
1035354e77e60e82828c7c2361f5c688c2667ab59ccBenjamin Kramer    reinterpret_cast<StringLiteral**>(constraints.data());
1045354e77e60e82828c7c2361f5c688c2667ab59ccBenjamin Kramer  Expr **Exprs = exprs.data();
1054b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  StringLiteral *AsmString = cast<StringLiteral>(asmString);
1065354e77e60e82828c7c2361f5c688c2667ab59ccBenjamin Kramer  StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.data());
1074b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
1084b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;
1094b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
1104b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  // The parser verifies that there is a string literal here.
1114b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  if (!AsmString->isAscii())
1124b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character)
1134b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      << AsmString->getSourceRange());
1144b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
1154b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  for (unsigned i = 0; i != NumOutputs; i++) {
1164b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    StringLiteral *Literal = Constraints[i];
1174b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (!Literal->isAscii())
1184b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
1194b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier        << Literal->getSourceRange());
1204b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
1214b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    StringRef OutputName;
1224b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (Names[i])
1234b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      OutputName = Names[i]->getName();
1244b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
1254b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
1264b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (!Context.getTargetInfo().validateOutputConstraint(Info))
1274b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      return StmtError(Diag(Literal->getLocStart(),
1284b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier                            diag::err_asm_invalid_output_constraint)
1294b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier                       << Info.getConstraintStr());
1304b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
1314b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // Check that the output exprs are valid lvalues.
1324b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    Expr *OutputExpr = Exprs[i];
1334b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (CheckAsmLValue(OutputExpr, *this)) {
1344b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      return StmtError(Diag(OutputExpr->getLocStart(),
1354b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier                  diag::err_asm_invalid_lvalue_in_output)
1364b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier        << OutputExpr->getSourceRange());
1374b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    }
1384b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
1394b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    OutputConstraintInfos.push_back(Info);
1404b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  }
1414b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
1424b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;
1434b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
1444b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
1454b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    StringLiteral *Literal = Constraints[i];
1464b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (!Literal->isAscii())
1474b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
1484b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier        << Literal->getSourceRange());
1494b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
1504b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    StringRef InputName;
1514b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (Names[i])
1524b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      InputName = Names[i]->getName();
1534b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
1544b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
1554b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(),
1564b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier                                                NumOutputs, Info)) {
1574b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      return StmtError(Diag(Literal->getLocStart(),
1584b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier                            diag::err_asm_invalid_input_constraint)
1594b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier                       << Info.getConstraintStr());
1604b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    }
1614b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
1624b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    Expr *InputExpr = Exprs[i];
1634b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
1644b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // Only allow void types for memory constraints.
1654b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (Info.allowsMemory() && !Info.allowsRegister()) {
1664b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      if (CheckAsmLValue(InputExpr, *this))
1674b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier        return StmtError(Diag(InputExpr->getLocStart(),
1684b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier                              diag::err_asm_invalid_lvalue_in_input)
1694b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier                         << Info.getConstraintStr()
1704b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier                         << InputExpr->getSourceRange());
1714b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    }
1724b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
1734b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (Info.allowsRegister()) {
1744b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      if (InputExpr->getType()->isVoidType()) {
1754b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier        return StmtError(Diag(InputExpr->getLocStart(),
1764b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier                              diag::err_asm_invalid_type_in_input)
1774b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier          << InputExpr->getType() << Info.getConstraintStr()
1784b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier          << InputExpr->getSourceRange());
1794b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      }
1804b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    }
1814b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
1824b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
1834b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (Result.isInvalid())
1844b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      return StmtError();
1854b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
1864b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    Exprs[i] = Result.take();
1874b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    InputConstraintInfos.push_back(Info);
1884b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  }
1894b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
1904b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  // Check that the clobbers are valid.
1914b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  for (unsigned i = 0; i != NumClobbers; i++) {
1924b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    StringLiteral *Literal = Clobbers[i];
1934b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (!Literal->isAscii())
1944b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
1954b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier        << Literal->getSourceRange());
1964b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
1974b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    StringRef Clobber = Literal->getString();
1984b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
1994b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (!Context.getTargetInfo().isValidClobber(Clobber))
2004b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      return StmtError(Diag(Literal->getLocStart(),
2014b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier                  diag::err_asm_unknown_register_name) << Clobber);
2024b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  }
2034b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
204df5faf5e7ae6823d0af0b801c4ac26d47f2cee97Chad Rosier  GCCAsmStmt *NS =
205df5faf5e7ae6823d0af0b801c4ac26d47f2cee97Chad Rosier    new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
206df5faf5e7ae6823d0af0b801c4ac26d47f2cee97Chad Rosier                             NumInputs, Names, Constraints, Exprs, AsmString,
207df5faf5e7ae6823d0af0b801c4ac26d47f2cee97Chad Rosier                             NumClobbers, Clobbers, RParenLoc);
2084b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  // Validate the asm string, ensuring it makes sense given the operands we
2094b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  // have.
210df5faf5e7ae6823d0af0b801c4ac26d47f2cee97Chad Rosier  SmallVector<GCCAsmStmt::AsmStringPiece, 8> Pieces;
2114b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  unsigned DiagOffs;
2124b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) {
2134b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
2144b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier           << AsmString->getSourceRange();
2154b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    return StmtError();
2164b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  }
2174b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
2184b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  // Validate tied input operands for type mismatches.
2194b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
2204b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
2214b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
2224b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // If this is a tied constraint, verify that the output and input have
2234b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // either exactly the same type, or that they are int/ptr operands with the
2244b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // same size (int/long, int*/long, are ok etc).
2254b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (!Info.hasTiedOperand()) continue;
2264b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
2274b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    unsigned TiedTo = Info.getTiedOperand();
2284b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    unsigned InputOpNo = i+NumOutputs;
2294b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    Expr *OutputExpr = Exprs[TiedTo];
2304b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    Expr *InputExpr = Exprs[InputOpNo];
2314b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
2324b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent())
2334b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      continue;
2344b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
2354b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    QualType InTy = InputExpr->getType();
2364b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    QualType OutTy = OutputExpr->getType();
2374b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (Context.hasSameType(InTy, OutTy))
2384b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      continue;  // All types can be tied to themselves.
2394b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
2404b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // Decide if the input and output are in the same domain (integer/ptr or
2414b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // floating point.
2424b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    enum AsmDomain {
2434b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      AD_Int, AD_FP, AD_Other
2444b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    } InputDomain, OutputDomain;
2454b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
2464b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (InTy->isIntegerType() || InTy->isPointerType())
2474b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      InputDomain = AD_Int;
2484b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    else if (InTy->isRealFloatingType())
2494b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      InputDomain = AD_FP;
2504b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    else
2514b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      InputDomain = AD_Other;
2524b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
2534b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (OutTy->isIntegerType() || OutTy->isPointerType())
2544b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      OutputDomain = AD_Int;
2554b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    else if (OutTy->isRealFloatingType())
2564b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      OutputDomain = AD_FP;
2574b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    else
2584b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      OutputDomain = AD_Other;
2594b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
2604b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // They are ok if they are the same size and in the same domain.  This
2614b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // allows tying things like:
2624b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    //   void* to int*
2634b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    //   void* to int            if they are the same size.
2644b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    //   double to long double   if they are the same size.
2654b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    //
2664b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    uint64_t OutSize = Context.getTypeSize(OutTy);
2674b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    uint64_t InSize = Context.getTypeSize(InTy);
2684b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (OutSize == InSize && InputDomain == OutputDomain &&
2694b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier        InputDomain != AD_Other)
2704b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      continue;
2714b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
2724b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // If the smaller input/output operand is not mentioned in the asm string,
2734b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // then we can promote the smaller one to a larger input and the asm string
2744b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // won't notice.
2754b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    bool SmallerValueMentioned = false;
2764b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
2774b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // If this is a reference to the input and if the input was the smaller
2784b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // one, then we have to reject this asm.
2794b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (isOperandMentioned(InputOpNo, Pieces)) {
2804b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      // This is a use in the asm string of the smaller operand.  Since we
2814b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      // codegen this by promoting to a wider value, the asm will get printed
2824b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      // "wrong".
2834b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      SmallerValueMentioned |= InSize < OutSize;
2844b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    }
2854b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (isOperandMentioned(TiedTo, Pieces)) {
2864b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      // If this is a reference to the output, and if the output is the larger
2874b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      // value, then it's ok because we'll promote the input to the larger type.
2884b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      SmallerValueMentioned |= OutSize < InSize;
2894b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    }
2904b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
2914b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // If the smaller value wasn't mentioned in the asm string, and if the
2924b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // output was a register, just extend the shorter one to the size of the
2934b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // larger one.
2944b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (!SmallerValueMentioned && InputDomain != AD_Other &&
2954b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier        OutputConstraintInfos[TiedTo].allowsRegister())
2964b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      continue;
2974b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
2984b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // Either both of the operands were mentioned or the smaller one was
2994b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // mentioned.  One more special case that we'll allow: if the tied input is
3004b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // integer, unmentioned, and is a constant, then we'll allow truncating it
3014b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    // down to the size of the destination.
3024b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (InputDomain == AD_Int && OutputDomain == AD_Int &&
3034b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier        !isOperandMentioned(InputOpNo, Pieces) &&
3044b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier        InputExpr->isEvaluatable(Context)) {
3054b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      CastKind castKind =
3064b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier        (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast);
3074b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take();
3084b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      Exprs[InputOpNo] = InputExpr;
3094b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      NS->setInputExpr(i, InputExpr);
3104b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      continue;
3114b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    }
3124b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
3134b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    Diag(InputExpr->getLocStart(),
3144b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier         diag::err_asm_tying_incompatible_types)
3154b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      << InTy << OutTy << OutputExpr->getSourceRange()
3164b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      << InputExpr->getSourceRange();
3174b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    return StmtError();
3184b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  }
3194b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
3204b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  return Owned(NS);
3214b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier}
3224b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
323358ab765f36f70d0744ede7dc35ce74c0911e77dChad Rosier// getSpelling - Get the spelling of the AsmTok token.
3244b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosierstatic StringRef getSpelling(Sema &SemaRef, Token AsmTok) {
3254b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  StringRef Asm;
3264b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  SmallString<512> TokenBuf;
3274b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  TokenBuf.resize(512);
3284b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  bool StringInvalid = false;
3294b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  Asm = SemaRef.PP.getSpelling(AsmTok, TokenBuf, &StringInvalid);
3304b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  assert (!StringInvalid && "Expected valid string!");
3314b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  return Asm;
3324b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier}
3334b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
334d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier// Build the inline assembly string.  Returns true on error.
335d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosierstatic bool buildMSAsmString(Sema &SemaRef,
336d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier                             SourceLocation AsmLoc,
337d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier                             ArrayRef<Token> AsmToks,
338d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier                             std::string &AsmString) {
3394b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!");
3404b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
3414b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  SmallString<512> Asm;
3424b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) {
34340d39e39e46eb36635c9735381ca5c4f916d30cdBob Wilson    bool isNewAsm = ((i == 0) ||
34440d39e39e46eb36635c9735381ca5c4f916d30cdBob Wilson                     AsmToks[i].isAtStartOfLine() ||
34540d39e39e46eb36635c9735381ca5c4f916d30cdBob Wilson                     AsmToks[i].is(tok::kw_asm));
3464b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    if (isNewAsm) {
347d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier      if (i != 0)
348d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier        Asm += "\n\t";
349d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier
3504b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      if (AsmToks[i].is(tok::kw_asm)) {
3514b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier        i++; // Skip __asm
352b0f6b9c94077446ceb29167add2e87fb99733a55Bob Wilson        if (i == e) {
353b0f6b9c94077446ceb29167add2e87fb99733a55Bob Wilson          SemaRef.Diag(AsmLoc, diag::err_asm_empty);
354b0f6b9c94077446ceb29167add2e87fb99733a55Bob Wilson          return true;
355b0f6b9c94077446ceb29167add2e87fb99733a55Bob Wilson        }
356d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier
3574b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      }
3584b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    }
3594b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
360b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier    if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm)
3614b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier      Asm += ' ';
3624b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
3634de971651ba09009d4a7cc6d2fbc978dd7092263Chad Rosier    StringRef Spelling = getSpelling(SemaRef, AsmToks[i]);
3644de971651ba09009d4a7cc6d2fbc978dd7092263Chad Rosier    Asm += Spelling;
3654b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  }
366d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  AsmString = Asm.str();
367b0f6b9c94077446ceb29167add2e87fb99733a55Bob Wilson  return false;
3684b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier}
3694b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
370d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosiernamespace {
371d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosierenum AsmOpRewriteKind {
372d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier   AOK_Imm,
373d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier   AOK_Input,
374d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier   AOK_Output
375d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier};
376d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier
377d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosierstruct AsmOpRewrite {
378d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  AsmOpRewriteKind Kind;
379d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  llvm::SMLoc Loc;
380d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  unsigned Len;
381d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier
382d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosierpublic:
383d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  AsmOpRewrite(AsmOpRewriteKind kind, llvm::SMLoc loc, unsigned len)
384d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    : Kind(kind), Loc(loc), Len(len) { }
385d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier};
386d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier
387d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier}
3882735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier
389b55e602e1dc7952edc7545fab7bb7b15047378f3Chad RosierStmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
390b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier                                ArrayRef<Token> AsmToks,SourceLocation EndLoc) {
3914b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  SmallVector<IdentifierInfo*, 4> Inputs;
3924b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  SmallVector<IdentifierInfo*, 4> Outputs;
393e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier  SmallVector<IdentifierInfo*, 4> Names;
394d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  SmallVector<std::string, 4> InputConstraints;
395d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  SmallVector<std::string, 4> OutputConstraints;
396e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier  SmallVector<StringRef, 4> Constraints;
397e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier  unsigned NumOutputs;
398e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier  unsigned NumInputs;
399e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier  SmallVector<Expr*, 4> InputExprs;
400e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier  SmallVector<Expr*, 4> OutputExprs;
401e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier  SmallVector<Expr*, 4> Exprs;
402d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  SmallVector<StringRef, 4> Clobbers;
403d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  std::set<std::string> ClobberRegs;
404d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier
405d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  SmallVector<struct AsmOpRewrite, 4> AsmStrRewrites;
4064b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
4074b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  // Empty asm statements don't need to instantiate the AsmParser, etc.
408d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  if (AsmToks.empty()) {
409d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    StringRef EmptyAsmStr;
410d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    MSAsmStmt *NS =
411d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier      new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true,
412e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier                              /*IsVolatile*/ true, AsmToks, /*NumOutputs*/ 0,
413e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier                              /*NumInputs*/ 0, Names, Constraints, Exprs, EmptyAsmStr,
414d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier                              Clobbers, EndLoc);
415d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    return Owned(NS);
416d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  }
4174b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
418d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  std::string AsmString;
419d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  if (buildMSAsmString(*this, AsmLoc, AsmToks, AsmString))
420b0f6b9c94077446ceb29167add2e87fb99733a55Bob Wilson    return StmtError();
42138c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier
4224b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  // Get the target specific parser.
4234b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  std::string Error;
4244b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  const std::string &TT = Context.getTargetInfo().getTriple().getTriple();
4254b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error));
4264b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
4274b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT));
4284b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
4294b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
4304b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  OwningPtr<llvm::MCSubtargetInfo>
4314b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    STI(TheTarget->createMCSubtargetInfo(TT, "", ""));
4324b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
433d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  llvm::SourceMgr SrcMgr;
434d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr);
435d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  llvm::MemoryBuffer *Buffer =
436d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    llvm::MemoryBuffer::getMemBuffer(AsmString, "<inline asm>");
437d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier
438d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  // Tell SrcMgr about this buffer, which is what the parser will pick up.
439d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc());
440d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier
441d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
442d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  OwningPtr<llvm::MCAsmParser>
443d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));
444d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  OwningPtr<llvm::MCTargetAsmParser>
445d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    TargetParser(TheTarget->createMCAsmParser(*STI, *Parser));
44667bd78f1d52da57f9f44092816174ccc1d599c87Chad Rosier    Parser->setParsingInlineAsm(true);
4474b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
448d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  // Get the instruction descriptor.
449d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo();
450d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  llvm::MCInstPrinter *IP =
451d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI);
452d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier
453d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  // Change to the Intel dialect.
454d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  Parser->setAssemblerDialect(1);
455d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  Parser->setTargetParser(*TargetParser.get());
456d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  Parser->setParsingInlineAsm(true);
457d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier
458d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  // Prime the lexer.
459d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  Parser->Lex();
460d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier
461d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  // While we have input, parse each statement.
462d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  unsigned InputIdx = 0;
463d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  unsigned OutputIdx = 0;
464d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  while (Parser->getLexer().isNot(llvm::AsmToken::Eof)) {
465d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    if (Parser->ParseStatement()) {
466d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier      // FIXME: The AsmParser should report errors, but we could potentially be
467d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier      // more verbose here.
468d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier      break;
469d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    }
470d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier
471d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    if (Parser->isInstruction()) {
472d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier      const llvm::MCInstrDesc &Desc = MII->get(Parser->getOpcode());
473d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier
474d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier      // Build the list of clobbers, outputs and inputs.
475d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier      for (unsigned i = 1, e = Parser->getNumParsedOperands(); i != e; ++i) {
476d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier        llvm::MCParsedAsmOperand &Operand = Parser->getParsedOperand(i);
477d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier
478d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier        // Immediate.
479d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier        if (Operand.isImm()) {
480d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier          AsmStrRewrites.push_back(AsmOpRewrite(AOK_Imm,
481d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier                                                Operand.getStartLoc(),
482d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier                                                Operand.getNameLen()));
483d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier          continue;
4847f9678b513f926dae27234858ed2586a6eb03b7bChad Rosier        }
4853034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier
486d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier
487d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier        // Register operand.
488d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier        if (Operand.isReg()) {
489d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier          unsigned NumDefs = Desc.getNumDefs();
490d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier          // Clobber.
491d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier          if (NumDefs && Operand.getMCOperandNum() < NumDefs) {
492d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier            std::string Reg;
493d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier            llvm::raw_string_ostream OS(Reg);
494d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier            IP->printRegName(OS, Operand.getReg());
495d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier            StringRef Clobber(OS.str());
496d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier            if (!Context.getTargetInfo().isValidClobber(Clobber))
497d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier              return StmtError(
498d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier                Diag(AsmLoc, diag::err_asm_unknown_register_name) << Clobber);
499d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier            ClobberRegs.insert(Reg);
500d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier          }
501d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier          continue;
502d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier        }
503d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier
504d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier
505d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier        // Expr/Input or Output.
506d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier        StringRef Name = Operand.getName();
507d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier        if (IdentifierInfo *II = &Context.Idents.get(Name)) {
508d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier          CXXScopeSpec SS;
509d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier          UnqualifiedId Id;
510d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier          SourceLocation Loc;
511d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier          Id.setIdentifier(II, AsmLoc);
512d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier          ExprResult Result = ActOnIdExpression(getCurScope(), SS, Loc, Id,
513d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier                                                false, false);
514d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier          if (!Result.isInvalid()) {
515d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier            bool isOutput = (i == 1) && Desc.mayStore();
516d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier            if (isOutput) {
517d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier              std::string Constraint = "=";
518d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier              ++InputIdx;
519d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier              Outputs.push_back(II);
520d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier              OutputExprs.push_back(Result.take());
521d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier              Constraint += Operand.getConstraint().str();
522d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier              OutputConstraints.push_back(Constraint);
523d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier              AsmStrRewrites.push_back(AsmOpRewrite(AOK_Output,
524d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier                                                    Operand.getStartLoc(),
525d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier                                                    Operand.getNameLen()));
526d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier            } else {
527d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier              Inputs.push_back(II);
528d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier              InputExprs.push_back(Result.take());
529d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier              InputConstraints.push_back(Operand.getConstraint().str());
530d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier              AsmStrRewrites.push_back(AsmOpRewrite(AOK_Input,
531d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier                                                    Operand.getStartLoc(),
532d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier                                                    Operand.getNameLen()));
533d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier            }
534633abb0ea01d37ab9c8e4ce1ee9e48894a12dfcaChad Rosier          }
5356e97be719edb4e3b9ac15353e79c60406b3dc429Chad Rosier        }
536fd5e56e35404cb44130b17546b6b5c1b33709d23Chad Rosier      }
537d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier      Parser->freeParsedOperands();
5384b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    }
5394b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  }
540e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier
541e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier  // Set the number of Outputs and Inputs.
542e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier  NumOutputs = Outputs.size();
543e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier  NumInputs = Inputs.size();
544e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier
545e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier  // Set the unique clobbers.
5464b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  for (std::set<std::string>::iterator I = ClobberRegs.begin(),
5474b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier         E = ClobberRegs.end(); I != E; ++I)
5484b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier    Clobbers.push_back(*I);
5494b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier
550e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier  // Merge the various outputs and inputs.  Output are expected first.
551e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier  Names.resize(NumOutputs + NumInputs);
552e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier  Constraints.resize(NumOutputs + NumInputs);
553e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier  Exprs.resize(NumOutputs + NumInputs);
554e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier  for (unsigned i = 0; i < NumOutputs; ++i) {
555e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier    Names[i] = Outputs[i];
556e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier    Constraints[i] = OutputConstraints[i];
557e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier    Exprs[i] = OutputExprs[i];
558e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier  }
559e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier  for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
560e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier    Names[j] = Inputs[i];
561e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier    Constraints[j] = InputConstraints[i];
562e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier    Exprs[j] = InputExprs[i];
563e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier  }
56489fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier
565d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  // Build the IR assembly string.
566d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  std::string AsmStringIR;
567d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  llvm::raw_string_ostream OS(AsmStringIR);
568d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  const char *Start = AsmString.c_str();
569d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  for (SmallVectorImpl<struct AsmOpRewrite>::iterator I = AsmStrRewrites.begin(),
570d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier         E = AsmStrRewrites.end(); I != E; ++I) {
571d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    const char *Loc = (*I).Loc.getPointer();
572d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier
573d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    // Emit everything up to the immediate/expression.
574d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    OS << StringRef(Start, Loc - Start);
575d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier
576d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    // Rewrite expressions in $N notation.
577d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    switch ((*I).Kind) {
578d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    case AOK_Imm:
579d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier      OS << Twine("$$") + StringRef(Loc, (*I).Len);
580d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier      break;
581d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    case AOK_Input:
582d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier      OS << '$';
583d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier      OS << InputIdx++;
584d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier      break;
585d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    case AOK_Output:
586d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier      OS << '$';
587d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier      OS << OutputIdx++;
588d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier      break;
589b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier    }
590b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier
591d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    // Skip the original expression.
592d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    Start = Loc + (*I).Len;
593acc22b6b5a8ba501f896fb0d00afdff5c5a3f090Chad Rosier  }
594d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  // Emit the remainder of the asm string.
595d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  const char *AsmEnd = AsmString.c_str() + AsmString.size();
596d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  if (Start != AsmEnd)
597d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier    OS << StringRef(Start, AsmEnd - Start);
598acc22b6b5a8ba501f896fb0d00afdff5c5a3f090Chad Rosier
599d9b56edcf42232c5331f9ad79aae83ba31e852dfChad Rosier  AsmString = OS.str();
6004b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  MSAsmStmt *NS =
601e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier    new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true,
602e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier                            /*IsVolatile*/ true, AsmToks, NumOutputs,
603e54cba1ec0b0e498ee67d200289035797932e714Chad Rosier                            NumInputs, Names, Constraints, Exprs, AsmString,
60489fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier                            Clobbers, EndLoc);
6054b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier  return Owned(NS);
6064b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier}
607