SemaStmtAsm.cpp revision 3034d88fd128ddf164f39d4f460ae3c3d70b40ae
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 3234b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier// isMSAsmKeyword - Return true if this is an MS-style inline asm keyword. These 3244b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier// require special handling. 3254b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosierstatic bool isMSAsmKeyword(StringRef Name) { 3264b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier bool Ret = llvm::StringSwitch<bool>(Name) 3274b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier .Cases("EVEN", "ALIGN", true) // Alignment directives. 3284b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier .Cases("LENGTH", "SIZE", "TYPE", true) // Type and variable sizes. 3294b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier .Case("_emit", true) // _emit Pseudoinstruction. 3304b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier .Default(false); 3314b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return Ret; 3324b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier} 3334b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 3346e97be719edb4e3b9ac15353e79c60406b3dc429Chad Rosier// getIdentifierInfo - Given a Name and a range of tokens, find the associated 3356e97be719edb4e3b9ac15353e79c60406b3dc429Chad Rosier// IdentifierInfo*. 3366e97be719edb4e3b9ac15353e79c60406b3dc429Chad Rosierstatic IdentifierInfo *getIdentifierInfo(StringRef Name, 3376e97be719edb4e3b9ac15353e79c60406b3dc429Chad Rosier ArrayRef<Token> AsmToks, 3386e97be719edb4e3b9ac15353e79c60406b3dc429Chad Rosier unsigned Begin, unsigned End) { 3396e97be719edb4e3b9ac15353e79c60406b3dc429Chad Rosier for (unsigned i = Begin; i <= End; ++i) { 3406e97be719edb4e3b9ac15353e79c60406b3dc429Chad Rosier IdentifierInfo *II = AsmToks[i].getIdentifierInfo(); 3416e97be719edb4e3b9ac15353e79c60406b3dc429Chad Rosier if (II && II->getName() == Name) 3426e97be719edb4e3b9ac15353e79c60406b3dc429Chad Rosier return II; 3436e97be719edb4e3b9ac15353e79c60406b3dc429Chad Rosier } 3446e97be719edb4e3b9ac15353e79c60406b3dc429Chad Rosier return 0; 3456e97be719edb4e3b9ac15353e79c60406b3dc429Chad Rosier} 3466e97be719edb4e3b9ac15353e79c60406b3dc429Chad Rosier 347358ab765f36f70d0744ede7dc35ce74c0911e77dChad Rosier// getSpelling - Get the spelling of the AsmTok token. 3484b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosierstatic StringRef getSpelling(Sema &SemaRef, Token AsmTok) { 3494b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier StringRef Asm; 3504b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SmallString<512> TokenBuf; 3514b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier TokenBuf.resize(512); 3524b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier bool StringInvalid = false; 3534b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Asm = SemaRef.PP.getSpelling(AsmTok, TokenBuf, &StringInvalid); 3544b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier assert (!StringInvalid && "Expected valid string!"); 3554b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return Asm; 3564b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier} 3574b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 358358ab765f36f70d0744ede7dc35ce74c0911e77dChad Rosier// Determine if we should bail on this MSAsm instruction. 3592735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosierstatic bool bailOnMSAsm(std::vector<StringRef> Piece) { 3602735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier for (unsigned i = 0, e = Piece.size(); i != e; ++i) 3612735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier if (isMSAsmKeyword(Piece[i])) 3622735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier return true; 3632735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier return false; 3642735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier} 3652735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier 366358ab765f36f70d0744ede7dc35ce74c0911e77dChad Rosier// Determine if we should bail on this MSAsm block. 3672735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosierstatic bool bailOnMSAsm(std::vector<std::vector<StringRef> > Pieces) { 3682735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier for (unsigned i = 0, e = Pieces.size(); i != e; ++i) 3692735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier if (bailOnMSAsm(Pieces[i])) 3702735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier return true; 3712735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier return false; 3722735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier} 3732735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier 374358ab765f36f70d0744ede7dc35ce74c0911e77dChad Rosier// Determine if this is a simple MSAsm instruction. 37598ac608c79fb46e73715121018f0659fb3bbe3e8Chad Rosierstatic bool isSimpleMSAsm(std::vector<StringRef> &Pieces, 37698ac608c79fb46e73715121018f0659fb3bbe3e8Chad Rosier const TargetInfo &TI) { 37798ac608c79fb46e73715121018f0659fb3bbe3e8Chad Rosier if (isMSAsmKeyword(Pieces[0])) 37898ac608c79fb46e73715121018f0659fb3bbe3e8Chad Rosier return false; 3794b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 38098ac608c79fb46e73715121018f0659fb3bbe3e8Chad Rosier for (unsigned i = 1, e = Pieces.size(); i != e; ++i) 38198ac608c79fb46e73715121018f0659fb3bbe3e8Chad Rosier if (!TI.isValidGCCRegisterName(Pieces[i])) 38298ac608c79fb46e73715121018f0659fb3bbe3e8Chad Rosier return false; 383153f8ecb5169347e41a0734ee1698498d88b96c5Chad Rosier return true; 384153f8ecb5169347e41a0734ee1698498d88b96c5Chad Rosier} 3854b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 386358ab765f36f70d0744ede7dc35ce74c0911e77dChad Rosier// Determine if this is a simple MSAsm block. 387153f8ecb5169347e41a0734ee1698498d88b96c5Chad Rosierstatic bool isSimpleMSAsm(std::vector<std::vector<StringRef> > Pieces, 388153f8ecb5169347e41a0734ee1698498d88b96c5Chad Rosier const TargetInfo &TI) { 389153f8ecb5169347e41a0734ee1698498d88b96c5Chad Rosier for (unsigned i = 0, e = Pieces.size(); i != e; ++i) 390153f8ecb5169347e41a0734ee1698498d88b96c5Chad Rosier if (!isSimpleMSAsm(Pieces[i], TI)) 391153f8ecb5169347e41a0734ee1698498d88b96c5Chad Rosier return false; 39298ac608c79fb46e73715121018f0659fb3bbe3e8Chad Rosier return true; 3934b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier} 3944b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 39540d39e39e46eb36635c9735381ca5c4f916d30cdBob Wilson// Break the AsmString into pieces (i.e., mnemonic and operands). 39638c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosierstatic void buildMSAsmPieces(StringRef Asm, std::vector<StringRef> &Pieces) { 39738c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier std::pair<StringRef,StringRef> Split = Asm.split(' '); 39838c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier 39938c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier // Mnemonic 40038c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier Pieces.push_back(Split.first); 40138c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier Asm = Split.second; 40238c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier 40338c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier // Operands 40438c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier while (!Asm.empty()) { 40538c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier Split = Asm.split(", "); 40638c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier Pieces.push_back(Split.first); 40738c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier Asm = Split.second; 40838c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier } 40938c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier} 41038c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier 411f0fbd776df77bc4b8b3e6ff3542b2e9117b2b905Chad Rosierstatic void buildMSAsmPieces(std::vector<std::string> &AsmStrings, 412f0fbd776df77bc4b8b3e6ff3542b2e9117b2b905Chad Rosier std::vector<std::vector<StringRef> > &Pieces) { 413f0fbd776df77bc4b8b3e6ff3542b2e9117b2b905Chad Rosier for (unsigned i = 0, e = AsmStrings.size(); i != e; ++i) 414f0fbd776df77bc4b8b3e6ff3542b2e9117b2b905Chad Rosier buildMSAsmPieces(AsmStrings[i], Pieces[i]); 415f0fbd776df77bc4b8b3e6ff3542b2e9117b2b905Chad Rosier} 416f0fbd776df77bc4b8b3e6ff3542b2e9117b2b905Chad Rosier 417b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier// Build the individual assembly instruction(s) and place them in the AsmStrings 418b0f6b9c94077446ceb29167add2e87fb99733a55Bob Wilson// vector. These strings are fed to the AsmParser. Returns true on error. 419b0f6b9c94077446ceb29167add2e87fb99733a55Bob Wilsonstatic bool buildMSAsmStrings(Sema &SemaRef, 420b0f6b9c94077446ceb29167add2e87fb99733a55Bob Wilson SourceLocation AsmLoc, 421b0f6b9c94077446ceb29167add2e87fb99733a55Bob Wilson ArrayRef<Token> AsmToks, 422b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier std::vector<std::string> &AsmStrings, 4239072a026a111726022b4f1c7f0a925d642ae8991Chad Rosier std::vector<std::pair<unsigned,unsigned> > &AsmTokRanges) { 4244b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); 4254b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 4264b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SmallString<512> Asm; 4279072a026a111726022b4f1c7f0a925d642ae8991Chad Rosier unsigned startTok = 0; 4284b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) { 42940d39e39e46eb36635c9735381ca5c4f916d30cdBob Wilson bool isNewAsm = ((i == 0) || 43040d39e39e46eb36635c9735381ca5c4f916d30cdBob Wilson AsmToks[i].isAtStartOfLine() || 43140d39e39e46eb36635c9735381ca5c4f916d30cdBob Wilson AsmToks[i].is(tok::kw_asm)); 4324b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 4334b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (isNewAsm) { 43438c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier if (i) { 43532f3acc0103055b1ef171fa94d1ee6d1deb0223eBenjamin Kramer AsmStrings.push_back(Asm.str()); 4369072a026a111726022b4f1c7f0a925d642ae8991Chad Rosier AsmTokRanges.push_back(std::make_pair(startTok, i-1)); 4379072a026a111726022b4f1c7f0a925d642ae8991Chad Rosier startTok = i; 43838c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier Asm.clear(); 43938c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier } 4404b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (AsmToks[i].is(tok::kw_asm)) { 4414b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier i++; // Skip __asm 442b0f6b9c94077446ceb29167add2e87fb99733a55Bob Wilson if (i == e) { 443b0f6b9c94077446ceb29167add2e87fb99733a55Bob Wilson SemaRef.Diag(AsmLoc, diag::err_asm_empty); 444b0f6b9c94077446ceb29167add2e87fb99733a55Bob Wilson return true; 445b0f6b9c94077446ceb29167add2e87fb99733a55Bob Wilson } 4464b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 4474b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 4484b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 449b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm) 4504b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Asm += ' '; 4514b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 4524de971651ba09009d4a7cc6d2fbc978dd7092263Chad Rosier StringRef Spelling = getSpelling(SemaRef, AsmToks[i]); 4534de971651ba09009d4a7cc6d2fbc978dd7092263Chad Rosier Asm += Spelling; 4544b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 45532f3acc0103055b1ef171fa94d1ee6d1deb0223eBenjamin Kramer AsmStrings.push_back(Asm.str()); 4569072a026a111726022b4f1c7f0a925d642ae8991Chad Rosier AsmTokRanges.push_back(std::make_pair(startTok, AsmToks.size()-1)); 457b0f6b9c94077446ceb29167add2e87fb99733a55Bob Wilson 458b0f6b9c94077446ceb29167add2e87fb99733a55Bob Wilson return false; 4594b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier} 4604b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 4613034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier// Check to see if the expression is a substring of the asm operand. 4623034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosierstatic StringRef getMSInlineAsmExprName(StringRef Name) { 4633034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier // Strip off the size directives. 4643034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier // E.g., DWORD PTR [V] -> V 4653034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier if (Name.startswith("BYTE") || Name.startswith("byte") || 4663034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier Name.startswith("WORD") || Name.startswith("word") || 4673034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier Name.startswith("DWORD") || Name.startswith("dword") || 4683034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier Name.startswith("QWORD") || Name.startswith("qword") || 4693034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier Name.startswith("XWORD") || Name.startswith("xword") || 4703034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier Name.startswith("XMMWORD") || Name.startswith("xmmword") || 4713034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier Name.startswith("YMMWORD") || Name.startswith("ymmword")) { 4723034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier std::pair< StringRef, StringRef > SplitName = Name.split(' '); 4733034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier assert((SplitName.second.startswith("PTR") || 4743034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier SplitName.second.startswith("ptr")) && 4753034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier "Expected PTR/ptr!"); 4763034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier SplitName = SplitName.second.split('['); 4773034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier SplitName = SplitName.second.split(']'); 4783034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier return SplitName.first; 4793034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier } 4803034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier return Name; 4813034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier} 4823034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier 483c69164917460ff717fd0b02649a3d7b0c5096088Chad Rosier#define DEF_SIMPLE_MSASM(STR) \ 48489fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier MSAsmStmt *NS = \ 48589fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, \ 48689fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier /*IsVolatile*/ true, AsmToks, Inputs, Outputs, \ 487c69164917460ff717fd0b02649a3d7b0c5096088Chad Rosier InputExprs, OutputExprs, STR, Constraints, \ 48889fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier Clobbers, EndLoc); 4892735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier 490b55e602e1dc7952edc7545fab7bb7b15047378f3Chad RosierStmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, 491b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier ArrayRef<Token> AsmToks,SourceLocation EndLoc) { 49289fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier SmallVector<StringRef, 4> Constraints; 49389fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier std::vector<std::string> InputConstraints; 49489fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier std::vector<std::string> OutputConstraints; 4954112a4c001c0ffe83962e5c6755c8b3e0d74b74cChad Rosier SmallVector<StringRef, 4> Clobbers; 4964b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier std::set<std::string> ClobberRegs; 497b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier 498b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier // FIXME: Use a struct to hold the various expression information. 4994b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SmallVector<IdentifierInfo*, 4> Inputs; 5004b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SmallVector<IdentifierInfo*, 4> Outputs; 501633abb0ea01d37ab9c8e4ce1ee9e48894a12dfcaChad Rosier SmallVector<Expr*, 4> InputExprs; 502633abb0ea01d37ab9c8e4ce1ee9e48894a12dfcaChad Rosier SmallVector<Expr*, 4> OutputExprs; 503acc22b6b5a8ba501f896fb0d00afdff5c5a3f090Chad Rosier SmallVector<std::string, 4> InputExprNames; 504acc22b6b5a8ba501f896fb0d00afdff5c5a3f090Chad Rosier SmallVector<std::string, 4> OutputExprNames; 505b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier SmallVector<unsigned, 4> InputExprStrIdx; 506b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier SmallVector<unsigned, 4> OutputExprStrIdx; 5074b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5084b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Empty asm statements don't need to instantiate the AsmParser, etc. 509c69164917460ff717fd0b02649a3d7b0c5096088Chad Rosier StringRef EmptyAsmStr; 510c69164917460ff717fd0b02649a3d7b0c5096088Chad Rosier if (AsmToks.empty()) { DEF_SIMPLE_MSASM(EmptyAsmStr); return Owned(NS); } 5114b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 51238c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier std::vector<std::string> AsmStrings; 5139072a026a111726022b4f1c7f0a925d642ae8991Chad Rosier std::vector<std::pair<unsigned,unsigned> > AsmTokRanges; 514b0f6b9c94077446ceb29167add2e87fb99733a55Bob Wilson if (buildMSAsmStrings(*this, AsmLoc, AsmToks, AsmStrings, AsmTokRanges)) 515b0f6b9c94077446ceb29167add2e87fb99733a55Bob Wilson return StmtError(); 51638c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier 517e78460f4335766b55c3da6a43fcd072671076458Chad Rosier std::vector<std::vector<StringRef> > Pieces(AsmStrings.size()); 518f0fbd776df77bc4b8b3e6ff3542b2e9117b2b905Chad Rosier buildMSAsmPieces(AsmStrings, Pieces); 519153f8ecb5169347e41a0734ee1698498d88b96c5Chad Rosier 520153f8ecb5169347e41a0734ee1698498d88b96c5Chad Rosier bool IsSimple = isSimpleMSAsm(Pieces, Context.getTargetInfo()); 5214b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5222735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier // AsmParser doesn't fully support these asm statements. 523c69164917460ff717fd0b02649a3d7b0c5096088Chad Rosier if (bailOnMSAsm(Pieces)) { DEF_SIMPLE_MSASM(EmptyAsmStr); return Owned(NS); } 5244b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5254b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Initialize targets and assembly printers/parsers. 5264b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier llvm::InitializeAllTargetInfos(); 5274b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier llvm::InitializeAllTargetMCs(); 5284b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier llvm::InitializeAllAsmParsers(); 5294b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5304b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Get the target specific parser. 5314b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier std::string Error; 5324b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier const std::string &TT = Context.getTargetInfo().getTriple().getTriple(); 5334b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error)); 5344b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5354b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT)); 5364b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); 5374b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo()); 5384b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OwningPtr<llvm::MCSubtargetInfo> 5394b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier STI(TheTarget->createMCSubtargetInfo(TT, "", "")); 5404b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 54125bd2986db1c7b8ced84fe835f5465007de47892Chad Rosier for (unsigned StrIdx = 0, e = AsmStrings.size(); StrIdx != e; ++StrIdx) { 5424b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier llvm::SourceMgr SrcMgr; 5434b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); 5444b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier llvm::MemoryBuffer *Buffer = 54525bd2986db1c7b8ced84fe835f5465007de47892Chad Rosier llvm::MemoryBuffer::getMemBuffer(AsmStrings[StrIdx], "<inline asm>"); 5464b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5474b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Tell SrcMgr about this buffer, which is what the parser will pick up. 5484b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc()); 5494b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5504b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx)); 5514b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OwningPtr<llvm::MCAsmParser> 5524b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI)); 5534b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OwningPtr<llvm::MCTargetAsmParser> 5544b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier TargetParser(TheTarget->createMCAsmParser(*STI, *Parser)); 5554b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Change to the Intel dialect. 5564b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Parser->setAssemblerDialect(1); 5574b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Parser->setTargetParser(*TargetParser.get()); 5584b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5594b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Prime the lexer. 5604b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Parser->Lex(); 5614b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5624b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Parse the opcode. 5634b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier StringRef IDVal; 5644b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Parser->ParseIdentifier(IDVal); 5654b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5664b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Canonicalize the opcode to lower case. 567be5c3fbec3a430bab2524e9315f58f64815bfeafChad Rosier SmallString<128> OpcodeStr; 568b706d9027cd8bbbaffa8b359a501cba52ace4c09Chad Rosier for (unsigned i = 0, e = IDVal.size(); i != e; ++i) 569be5c3fbec3a430bab2524e9315f58f64815bfeafChad Rosier OpcodeStr.push_back(tolower(IDVal[i])); 5703d442196134d18ed8ee17576638b758362b60742Chad Rosier // FIXME: Convert to a StmtError. 5713d442196134d18ed8ee17576638b758362b60742Chad Rosier assert(TargetParser->mnemonicIsValid(OpcodeStr) && "Invalid mnemonic!"); 5724b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5734b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Parse the operands. 5744b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier llvm::SMLoc IDLoc; 5754b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SmallVector<llvm::MCParsedAsmOperand*, 8> Operands; 576be5c3fbec3a430bab2524e9315f58f64815bfeafChad Rosier bool HadError = TargetParser->ParseInstruction(OpcodeStr.str(), IDLoc, 5774b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Operands); 5782735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier // If we had an error parsing the operands, fail gracefully. 579c69164917460ff717fd0b02649a3d7b0c5096088Chad Rosier if (HadError) { DEF_SIMPLE_MSASM(EmptyAsmStr); return Owned(NS); } 5804b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5814b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Match the MCInstr. 582be5c3fbec3a430bab2524e9315f58f64815bfeafChad Rosier unsigned Kind; 5833034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier unsigned Opcode; 58483591b6d3f20ee84f4abe1c2574e90736aa84b11Chad Rosier unsigned ErrorInfo; 5853034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier SmallVector<std::pair< unsigned, std::string >, 4> MapAndConstraints; 5863034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier HadError = TargetParser->MatchInstruction(IDLoc, Operands, *Str.get(), Kind, 5873034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier Opcode, MapAndConstraints, 5887065c52fc53ec3106a97b7c8d373df431f3bd4f3Chad Rosier ErrorInfo, 58951a6b3f58b0dbbc51a77b8f4a509720954406cebChad Rosier /*matchingInlineAsm*/ true); 5902735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier // If we had an error parsing the operands, fail gracefully. 591c69164917460ff717fd0b02649a3d7b0c5096088Chad Rosier if (HadError) { DEF_SIMPLE_MSASM(EmptyAsmStr); return Owned(NS); } 5924b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5934b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Get the instruction descriptor. 5944b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo(); 5953034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier const llvm::MCInstrDesc &Desc = MII->get(Opcode); 5964b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier llvm::MCInstPrinter *IP = 5974b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI); 5984b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5996e97be719edb4e3b9ac15353e79c60406b3dc429Chad Rosier // Build the list of clobbers, outputs and inputs. 600fd5e56e35404cb44130b17546b6b5c1b33709d23Chad Rosier unsigned NumDefs = Desc.getNumDefs(); 6011b497f26ab7861b22383b22f35cf799c0b312c9bChad Rosier for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 6023034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier // Skip immediates. 6033034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier if (Operands[i]->isImm()) 604fb700265b6e452a3cfd3abc73102fef11d103d4aChad Rosier continue; 605fb700265b6e452a3cfd3abc73102fef11d103d4aChad Rosier 6063034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier // Register. 6073034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier if (Operands[i]->isReg()) { 6083034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier // Clobber. 6093034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier if (NumDefs && (MapAndConstraints[i-1].first < NumDefs)) { 6107f9678b513f926dae27234858ed2586a6eb03b7bChad Rosier std::string Reg; 6117f9678b513f926dae27234858ed2586a6eb03b7bChad Rosier llvm::raw_string_ostream OS(Reg); 6123034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier IP->printRegName(OS, Operands[i]->getReg()); 6137f9678b513f926dae27234858ed2586a6eb03b7bChad Rosier StringRef Clobber(OS.str()); 6147f9678b513f926dae27234858ed2586a6eb03b7bChad Rosier if (!Context.getTargetInfo().isValidClobber(Clobber)) 6157f9678b513f926dae27234858ed2586a6eb03b7bChad Rosier return StmtError( 6167f9678b513f926dae27234858ed2586a6eb03b7bChad Rosier Diag(AsmLoc, diag::err_asm_unknown_register_name) << Clobber); 6177f9678b513f926dae27234858ed2586a6eb03b7bChad Rosier ClobberRegs.insert(Reg); 6187f9678b513f926dae27234858ed2586a6eb03b7bChad Rosier } 6193034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier continue; 6203034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier } 6213034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier 6223034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier // Expr/Input or Output. 6233034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier StringRef Name = getMSInlineAsmExprName(Pieces[StrIdx][i]); 6243034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier 6253034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier // The expr may be a register. 6263034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier // E.g., DWORD PTR [eax] 6273034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier if (Context.getTargetInfo().isValidGCCRegisterName(Name)) 6283034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier continue; 6293034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier 6303034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier IdentifierInfo *II = getIdentifierInfo(Name, AsmToks, 6313034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier AsmTokRanges[StrIdx].first, 6323034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier AsmTokRanges[StrIdx].second); 6333034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier if (II) { 6343034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier CXXScopeSpec SS; 6353034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier UnqualifiedId Id; 6363034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier SourceLocation Loc; 6373034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier Id.setIdentifier(II, AsmLoc); 6383034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier ExprResult Result = ActOnIdExpression(getCurScope(), SS, Loc, Id, 6393034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier false, false); 6403034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier if (!Result.isInvalid()) { 6413034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier // FIXME: Determine the proper constraints. 6423034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier bool isMemDef = (i == 1) && Desc.mayStore(); 6433034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier if (isMemDef) { 6443034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier Outputs.push_back(II); 6453034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier OutputExprs.push_back(Result.take()); 6463034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier OutputExprNames.push_back(Name.str()); 6473034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier OutputExprStrIdx.push_back(StrIdx); 6483034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier 6493034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier std::string Constraint = "=" + MapAndConstraints[i-1].second; 6503034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier OutputConstraints.push_back(Constraint); 6513034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier } else { 6523034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier Inputs.push_back(II); 6533034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier InputExprs.push_back(Result.take()); 6543034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier InputExprNames.push_back(Name.str()); 6553034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier InputExprStrIdx.push_back(StrIdx); 6563034d88fd128ddf164f39d4f460ae3c3d70b40aeChad Rosier InputConstraints.push_back(MapAndConstraints[i-1].second); 657633abb0ea01d37ab9c8e4ce1ee9e48894a12dfcaChad Rosier } 6586e97be719edb4e3b9ac15353e79c60406b3dc429Chad Rosier } 659fd5e56e35404cb44130b17546b6b5c1b33709d23Chad Rosier } 6604b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 6614b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 6624b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier for (std::set<std::string>::iterator I = ClobberRegs.begin(), 6634b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier E = ClobberRegs.end(); I != E; ++I) 6644b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Clobbers.push_back(*I); 6654b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 66689fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier // Merge the output and input constraints. Output constraints are expected 66789fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier // first. 66889fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier for (std::vector<std::string>::iterator I = OutputConstraints.begin(), 66989fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier E = OutputConstraints.end(); I != E; ++I) 67089fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier Constraints.push_back(*I); 67189fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier 67289fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier for (std::vector<std::string>::iterator I = InputConstraints.begin(), 67389fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier E = InputConstraints.end(); I != E; ++I) 67489fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier Constraints.push_back(*I); 67589fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier 676acc22b6b5a8ba501f896fb0d00afdff5c5a3f090Chad Rosier // Enumerate the AsmString expressions. 677acc22b6b5a8ba501f896fb0d00afdff5c5a3f090Chad Rosier unsigned OpNum = 0; 678acc22b6b5a8ba501f896fb0d00afdff5c5a3f090Chad Rosier for (unsigned i = 0, e = OutputExprNames.size(); i != e; ++i, ++OpNum) { 679b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier unsigned StrIdx = OutputExprStrIdx[i]; 680b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier // Iterate over the assembly instruction pieces, skipping the mnemonic. 681b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier for (unsigned j = 1, f = Pieces[StrIdx].size(); j != f; ++j) { 682b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier // If the operand and the expression name match, then rewrite the operand. 683b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier if (OutputExprNames[i] == Pieces[StrIdx][j]) { 684b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier SmallString<32> Res; 685b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier llvm::raw_svector_ostream OS(Res); 686b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier OS << '$' << OpNum; 687b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier OutputExprNames[i] = OS.str(); 688b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier Pieces[StrIdx][j] = OutputExprNames[i]; 689b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier break; 690b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier } 691b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier // Check to see if the expression is a substring of the asm piece. 692b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier std::pair< StringRef, StringRef > Split = Pieces[StrIdx][j].split(' '); 693b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier bool isKeyword = llvm::StringSwitch<bool>(Split.first) 694b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier .Cases("BYTE", "byte", "WORD", "word", "DWORD", true) 695b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier .Cases("dword", "QWORD", "qword", "XWORD", "xword", true) 696b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier .Cases("XMMWORD", "xmmword", "YMMWORD", "ymmword", true) 697b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier .Default(false); 698b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier if (isKeyword && 699b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier Split.second.find_first_of(OutputExprNames[i]) != StringRef::npos) { 700b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier // Is is a substring, do the replacement. 701b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier SmallString<32> Res; 702b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier llvm::raw_svector_ostream OS(Res); 703b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier OS << '$' << OpNum; 704b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier std::string piece = Pieces[StrIdx][j].str(); 705b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier size_t found = piece.find(InputExprNames[i]); 706b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier piece.replace(found, InputExprNames[i].size(), OS.str()); 707b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier OutputExprNames[i] = piece; 708b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier Pieces[StrIdx][j] = OutputExprNames[i]; 709b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier break; 710b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier } 711b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier } 712acc22b6b5a8ba501f896fb0d00afdff5c5a3f090Chad Rosier } 713acc22b6b5a8ba501f896fb0d00afdff5c5a3f090Chad Rosier for (unsigned i = 0, e = InputExprNames.size(); i != e; ++i, ++OpNum) { 714b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier unsigned StrIdx = InputExprStrIdx[i]; 715b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier // Iterate over the assembly instruction pieces, skipping the mnemonic. 716b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier for (unsigned j = 1, f = Pieces[StrIdx].size(); j != f; ++j) { 717b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier // If the operand and the expression name match, then rewrite the operand. 718b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier if (InputExprNames[i] == Pieces[StrIdx][j]) { 719b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier SmallString<32> Res; 720b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier llvm::raw_svector_ostream OS(Res); 721b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier OS << '$' << OpNum; 722b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier InputExprNames[i] = OS.str(); 723b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier Pieces[StrIdx][j] = InputExprNames[i]; 724b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier break; 725b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier } 726b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier // Check to see if the expression is a substring of the asm piece. 727b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier std::pair< StringRef, StringRef > Split = Pieces[StrIdx][j].split(' '); 728b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier bool isKeyword = llvm::StringSwitch<bool>(Split.first) 729b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier .Cases("BYTE", "byte", "WORD", "word", "DWORD", true) 730b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier .Cases("dword", "QWORD", "qword", "XWORD", "xword", true) 731b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier .Cases("XMMWORD", "xmmword", "YMMWORD", "ymmword", true) 732b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier .Default(false); 733b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier if (isKeyword && 734b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier Split.second.find_first_of(InputExprNames[i]) != StringRef::npos) { 735b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier // It is a substring, do the replacement. 736b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier SmallString<32> Res; 737b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier llvm::raw_svector_ostream OS(Res); 738b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier OS << '$' << OpNum; 739b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier std::string piece = Pieces[StrIdx][j].str(); 740b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier size_t found = piece.find(InputExprNames[i]); 741b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier piece.replace(found, InputExprNames[i].size(), OS.str()); 742b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier InputExprNames[i] = piece; 743b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier Pieces[StrIdx][j] = InputExprNames[i]; 744b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier break; 745b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier } 746b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier } 747b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier } 748b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier 749b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier // Emit the IR assembly string. 750b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier std::string AsmString; 751b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier for (unsigned i = 0, e = Pieces.size(); i != e; ++i) { 752b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier // Skip empty asm stmts. 753b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier if (Pieces[i].empty()) continue; 754b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier 755b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier if (i > 0) 756b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier AsmString += "\n\t"; 757b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier 758b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier // Emit the mnemonic. 759b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier AsmString += Pieces[i][0]; 760b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier if (Pieces[i].size() > 1) 761b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier AsmString += ' '; 762b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier 763b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier // Emit the operands adding $$ to constants. 764b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier for (unsigned j = 1, f = Pieces[i].size(); j != f; ++j) { 765b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier if (j > 1) AsmString += ", "; 766b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier unsigned Val; 767b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier if (!Pieces[i][j].getAsInteger(0, Val)) 768b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier AsmString += "$$"; 769b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier 770b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier AsmString += Pieces[i][j]; 771b55e602e1dc7952edc7545fab7bb7b15047378f3Chad Rosier } 772acc22b6b5a8ba501f896fb0d00afdff5c5a3f090Chad Rosier } 773acc22b6b5a8ba501f896fb0d00afdff5c5a3f090Chad Rosier 7744b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier MSAsmStmt *NS = 7754b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple, 7764b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier /*IsVolatile*/ true, AsmToks, Inputs, Outputs, 77789fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier InputExprs, OutputExprs, AsmString, Constraints, 77889fb6d7eba51c7864ec544e07accd23b24057122Chad Rosier Clobbers, EndLoc); 7794b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return Owned(NS); 7804b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier} 781