SemaStmtAsm.cpp revision 682ad162f144ff8e8e5303d30bc48b6a6a41d0d6
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" 274b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCInst.h" 284b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCInstPrinter.h" 294b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCInstrInfo.h" 304b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCObjectFileInfo.h" 314b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCRegisterInfo.h" 324b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCStreamer.h" 334b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCSubtargetInfo.h" 344b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCTargetAsmParser.h" 354b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCParser/MCAsmLexer.h" 364b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/MC/MCParser/MCAsmParser.h" 374b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/Support/SourceMgr.h" 384b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/Support/TargetRegistry.h" 394b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier#include "llvm/Support/TargetSelect.h" 404b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosierusing namespace clang; 414b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosierusing namespace sema; 424b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 434b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently 444b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier/// ignore "noop" casts in places where an lvalue is required by an inline asm. 454b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier/// We emulate this behavior when -fheinous-gnu-extensions is specified, but 464b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier/// provide a strong guidance to not use it. 474b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier/// 484b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier/// This method checks to see if the argument is an acceptable l-value and 494b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier/// returns false if it is a case we can handle. 504b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosierstatic bool CheckAsmLValue(const Expr *E, Sema &S) { 514b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Type dependent expressions will be checked during instantiation. 524b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (E->isTypeDependent()) 534b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return false; 544b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 554b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (E->isLValue()) 564b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return false; // Cool, this is an lvalue. 574b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 584b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Okay, this is not an lvalue, but perhaps it is the result of a cast that we 594b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // are supposed to allow. 604b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier const Expr *E2 = E->IgnoreParenNoopCasts(S.Context); 614b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (E != E2 && E2->isLValue()) { 624b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (!S.getLangOpts().HeinousExtensions) 634b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue) 644b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier << E->getSourceRange(); 654b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier else 664b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue) 674b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier << E->getSourceRange(); 684b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Accept, even if we emitted an error diagnostic. 694b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return false; 704b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 714b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 724b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // None of the above, just randomly invalid non-lvalue. 734b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return true; 744b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier} 754b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 764b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier/// isOperandMentioned - Return true if the specified operand # is mentioned 774b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier/// anywhere in the decomposed asm string. 784b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosierstatic bool isOperandMentioned(unsigned OpNo, 794b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier ArrayRef<AsmStmt::AsmStringPiece> AsmStrPieces) { 804b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) { 814b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier const AsmStmt::AsmStringPiece &Piece = AsmStrPieces[p]; 824b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (!Piece.isOperand()) continue; 834b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 844b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // If this is a reference to the input and if the input was the smaller 854b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // one, then we have to reject this asm. 864b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (Piece.getOperandNo() == OpNo) 874b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return true; 884b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 894b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return false; 904b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier} 914b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 924b5e48d39eb94ee12f3d89df60525053d8b0275eChad RosierStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, 934b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier bool IsVolatile, unsigned NumOutputs, 944b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier unsigned NumInputs, IdentifierInfo **Names, 954b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier MultiExprArg constraints, MultiExprArg exprs, 964b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Expr *asmString, MultiExprArg clobbers, 97df4ee102aa909e2f40c294701bfeffac63e8d29bChad Rosier SourceLocation RParenLoc) { 984b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier unsigned NumClobbers = clobbers.size(); 994b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier StringLiteral **Constraints = 1004b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier reinterpret_cast<StringLiteral**>(constraints.get()); 1014b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Expr **Exprs = exprs.get(); 1024b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier StringLiteral *AsmString = cast<StringLiteral>(asmString); 1034b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.get()); 1044b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 1054b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos; 1064b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 1074b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // The parser verifies that there is a string literal here. 1084b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (!AsmString->isAscii()) 1094b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character) 1104b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier << AsmString->getSourceRange()); 1114b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 1124b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier for (unsigned i = 0; i != NumOutputs; i++) { 1134b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier StringLiteral *Literal = Constraints[i]; 1144b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (!Literal->isAscii()) 1154b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) 1164b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier << Literal->getSourceRange()); 1174b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 1184b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier StringRef OutputName; 1194b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (Names[i]) 1204b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OutputName = Names[i]->getName(); 1214b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 1224b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName); 1234b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (!Context.getTargetInfo().validateOutputConstraint(Info)) 1244b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return StmtError(Diag(Literal->getLocStart(), 1254b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier diag::err_asm_invalid_output_constraint) 1264b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier << Info.getConstraintStr()); 1274b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 1284b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Check that the output exprs are valid lvalues. 1294b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Expr *OutputExpr = Exprs[i]; 1304b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (CheckAsmLValue(OutputExpr, *this)) { 1314b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return StmtError(Diag(OutputExpr->getLocStart(), 1324b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier diag::err_asm_invalid_lvalue_in_output) 1334b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier << OutputExpr->getSourceRange()); 1344b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 1354b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 1364b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OutputConstraintInfos.push_back(Info); 1374b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 1384b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 1394b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos; 1404b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 1414b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) { 1424b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier StringLiteral *Literal = Constraints[i]; 1434b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (!Literal->isAscii()) 1444b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) 1454b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier << Literal->getSourceRange()); 1464b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 1474b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier StringRef InputName; 1484b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (Names[i]) 1494b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier InputName = Names[i]->getName(); 1504b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 1514b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier TargetInfo::ConstraintInfo Info(Literal->getString(), InputName); 1524b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(), 1534b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier NumOutputs, Info)) { 1544b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return StmtError(Diag(Literal->getLocStart(), 1554b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier diag::err_asm_invalid_input_constraint) 1564b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier << Info.getConstraintStr()); 1574b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 1584b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 1594b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Expr *InputExpr = Exprs[i]; 1604b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 1614b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Only allow void types for memory constraints. 1624b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (Info.allowsMemory() && !Info.allowsRegister()) { 1634b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (CheckAsmLValue(InputExpr, *this)) 1644b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return StmtError(Diag(InputExpr->getLocStart(), 1654b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier diag::err_asm_invalid_lvalue_in_input) 1664b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier << Info.getConstraintStr() 1674b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier << InputExpr->getSourceRange()); 1684b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 1694b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 1704b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (Info.allowsRegister()) { 1714b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (InputExpr->getType()->isVoidType()) { 1724b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return StmtError(Diag(InputExpr->getLocStart(), 1734b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier diag::err_asm_invalid_type_in_input) 1744b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier << InputExpr->getType() << Info.getConstraintStr() 1754b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier << InputExpr->getSourceRange()); 1764b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 1774b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 1784b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 1794b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]); 1804b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (Result.isInvalid()) 1814b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return StmtError(); 1824b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 1834b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Exprs[i] = Result.take(); 1844b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier InputConstraintInfos.push_back(Info); 1854b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 1864b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 1874b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Check that the clobbers are valid. 1884b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier for (unsigned i = 0; i != NumClobbers; i++) { 1894b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier StringLiteral *Literal = Clobbers[i]; 1904b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (!Literal->isAscii()) 1914b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) 1924b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier << Literal->getSourceRange()); 1934b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 1944b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier StringRef Clobber = Literal->getString(); 1954b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 1964b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (!Context.getTargetInfo().isValidClobber(Clobber)) 1974b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return StmtError(Diag(Literal->getLocStart(), 1984b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier diag::err_asm_unknown_register_name) << Clobber); 1994b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 2004b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 2014b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier AsmStmt *NS = 202df4ee102aa909e2f40c294701bfeffac63e8d29bChad Rosier new (Context) AsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, 203df4ee102aa909e2f40c294701bfeffac63e8d29bChad Rosier NumInputs, Names, Constraints, Exprs, AsmString, 204df4ee102aa909e2f40c294701bfeffac63e8d29bChad Rosier NumClobbers, Clobbers, RParenLoc); 2054b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Validate the asm string, ensuring it makes sense given the operands we 2064b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // have. 2074b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SmallVector<AsmStmt::AsmStringPiece, 8> Pieces; 2084b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier unsigned DiagOffs; 2094b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) { 2104b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID) 2114b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier << AsmString->getSourceRange(); 2124b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return StmtError(); 2134b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 2144b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 2154b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Validate tied input operands for type mismatches. 2164b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) { 2174b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; 2184b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 2194b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // If this is a tied constraint, verify that the output and input have 2204b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // either exactly the same type, or that they are int/ptr operands with the 2214b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // same size (int/long, int*/long, are ok etc). 2224b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (!Info.hasTiedOperand()) continue; 2234b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 2244b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier unsigned TiedTo = Info.getTiedOperand(); 2254b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier unsigned InputOpNo = i+NumOutputs; 2264b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Expr *OutputExpr = Exprs[TiedTo]; 2274b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Expr *InputExpr = Exprs[InputOpNo]; 2284b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 2294b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent()) 2304b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier continue; 2314b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 2324b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier QualType InTy = InputExpr->getType(); 2334b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier QualType OutTy = OutputExpr->getType(); 2344b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (Context.hasSameType(InTy, OutTy)) 2354b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier continue; // All types can be tied to themselves. 2364b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 2374b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Decide if the input and output are in the same domain (integer/ptr or 2384b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // floating point. 2394b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier enum AsmDomain { 2404b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier AD_Int, AD_FP, AD_Other 2414b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } InputDomain, OutputDomain; 2424b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 2434b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (InTy->isIntegerType() || InTy->isPointerType()) 2444b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier InputDomain = AD_Int; 2454b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier else if (InTy->isRealFloatingType()) 2464b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier InputDomain = AD_FP; 2474b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier else 2484b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier InputDomain = AD_Other; 2494b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 2504b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (OutTy->isIntegerType() || OutTy->isPointerType()) 2514b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OutputDomain = AD_Int; 2524b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier else if (OutTy->isRealFloatingType()) 2534b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OutputDomain = AD_FP; 2544b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier else 2554b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OutputDomain = AD_Other; 2564b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 2574b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // They are ok if they are the same size and in the same domain. This 2584b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // allows tying things like: 2594b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // void* to int* 2604b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // void* to int if they are the same size. 2614b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // double to long double if they are the same size. 2624b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // 2634b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier uint64_t OutSize = Context.getTypeSize(OutTy); 2644b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier uint64_t InSize = Context.getTypeSize(InTy); 2654b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (OutSize == InSize && InputDomain == OutputDomain && 2664b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier InputDomain != AD_Other) 2674b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier continue; 2684b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 2694b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // If the smaller input/output operand is not mentioned in the asm string, 2704b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // then we can promote the smaller one to a larger input and the asm string 2714b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // won't notice. 2724b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier bool SmallerValueMentioned = false; 2734b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 2744b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // If this is a reference to the input and if the input was the smaller 2754b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // one, then we have to reject this asm. 2764b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (isOperandMentioned(InputOpNo, Pieces)) { 2774b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // This is a use in the asm string of the smaller operand. Since we 2784b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // codegen this by promoting to a wider value, the asm will get printed 2794b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // "wrong". 2804b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SmallerValueMentioned |= InSize < OutSize; 2814b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 2824b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (isOperandMentioned(TiedTo, Pieces)) { 2834b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // If this is a reference to the output, and if the output is the larger 2844b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // value, then it's ok because we'll promote the input to the larger type. 2854b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SmallerValueMentioned |= OutSize < InSize; 2864b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 2874b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 2884b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // If the smaller value wasn't mentioned in the asm string, and if the 2894b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // output was a register, just extend the shorter one to the size of the 2904b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // larger one. 2914b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (!SmallerValueMentioned && InputDomain != AD_Other && 2924b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OutputConstraintInfos[TiedTo].allowsRegister()) 2934b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier continue; 2944b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 2954b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Either both of the operands were mentioned or the smaller one was 2964b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // mentioned. One more special case that we'll allow: if the tied input is 2974b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // integer, unmentioned, and is a constant, then we'll allow truncating it 2984b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // down to the size of the destination. 2994b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (InputDomain == AD_Int && OutputDomain == AD_Int && 3004b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier !isOperandMentioned(InputOpNo, Pieces) && 3014b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier InputExpr->isEvaluatable(Context)) { 3024b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier CastKind castKind = 3034b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast); 3044b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take(); 3054b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Exprs[InputOpNo] = InputExpr; 3064b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier NS->setInputExpr(i, InputExpr); 3074b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier continue; 3084b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 3094b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 3104b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Diag(InputExpr->getLocStart(), 3114b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier diag::err_asm_tying_incompatible_types) 3124b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier << InTy << OutTy << OutputExpr->getSourceRange() 3134b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier << InputExpr->getSourceRange(); 3144b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return StmtError(); 3154b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 3164b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 3174b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return Owned(NS); 3184b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier} 3194b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 3204b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier// isMSAsmKeyword - Return true if this is an MS-style inline asm keyword. These 3214b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier// require special handling. 3224b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosierstatic bool isMSAsmKeyword(StringRef Name) { 3234b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier bool Ret = llvm::StringSwitch<bool>(Name) 3244b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier .Cases("EVEN", "ALIGN", true) // Alignment directives. 3254b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier .Cases("LENGTH", "SIZE", "TYPE", true) // Type and variable sizes. 3264b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier .Case("_emit", true) // _emit Pseudoinstruction. 3274b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier .Default(false); 3284b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return Ret; 3294b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier} 3304b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 331358ab765f36f70d0744ede7dc35ce74c0911e77dChad Rosier// getSpelling - Get the spelling of the AsmTok token. 3324b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosierstatic StringRef getSpelling(Sema &SemaRef, Token AsmTok) { 3334b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier StringRef Asm; 3344b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SmallString<512> TokenBuf; 3354b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier TokenBuf.resize(512); 3364b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier bool StringInvalid = false; 3374b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Asm = SemaRef.PP.getSpelling(AsmTok, TokenBuf, &StringInvalid); 3384b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier assert (!StringInvalid && "Expected valid string!"); 3394b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return Asm; 3404b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier} 3414b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 342358ab765f36f70d0744ede7dc35ce74c0911e77dChad Rosier// Determine if we should bail on this MSAsm instruction. 3432735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosierstatic bool bailOnMSAsm(std::vector<StringRef> Piece) { 3442735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier for (unsigned i = 0, e = Piece.size(); i != e; ++i) 3452735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier if (isMSAsmKeyword(Piece[i])) 3462735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier return true; 3472735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier return false; 3482735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier} 3492735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier 350358ab765f36f70d0744ede7dc35ce74c0911e77dChad Rosier// Determine if we should bail on this MSAsm block. 3512735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosierstatic bool bailOnMSAsm(std::vector<std::vector<StringRef> > Pieces) { 3522735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier for (unsigned i = 0, e = Pieces.size(); i != e; ++i) 3532735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier if (bailOnMSAsm(Pieces[i])) 3542735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier return true; 3552735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier return false; 3562735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier} 3572735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier 358358ab765f36f70d0744ede7dc35ce74c0911e77dChad Rosier// Determine if this is a simple MSAsm instruction. 35998ac608c79fb46e73715121018f0659fb3bbe3e8Chad Rosierstatic bool isSimpleMSAsm(std::vector<StringRef> &Pieces, 36098ac608c79fb46e73715121018f0659fb3bbe3e8Chad Rosier const TargetInfo &TI) { 36198ac608c79fb46e73715121018f0659fb3bbe3e8Chad Rosier if (isMSAsmKeyword(Pieces[0])) 36298ac608c79fb46e73715121018f0659fb3bbe3e8Chad Rosier return false; 3634b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 36498ac608c79fb46e73715121018f0659fb3bbe3e8Chad Rosier for (unsigned i = 1, e = Pieces.size(); i != e; ++i) 36598ac608c79fb46e73715121018f0659fb3bbe3e8Chad Rosier if (!TI.isValidGCCRegisterName(Pieces[i])) 36698ac608c79fb46e73715121018f0659fb3bbe3e8Chad Rosier return false; 367153f8ecb5169347e41a0734ee1698498d88b96c5Chad Rosier return true; 368153f8ecb5169347e41a0734ee1698498d88b96c5Chad Rosier} 3694b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 370358ab765f36f70d0744ede7dc35ce74c0911e77dChad Rosier// Determine if this is a simple MSAsm block. 371153f8ecb5169347e41a0734ee1698498d88b96c5Chad Rosierstatic bool isSimpleMSAsm(std::vector<std::vector<StringRef> > Pieces, 372153f8ecb5169347e41a0734ee1698498d88b96c5Chad Rosier const TargetInfo &TI) { 373153f8ecb5169347e41a0734ee1698498d88b96c5Chad Rosier for (unsigned i = 0, e = Pieces.size(); i != e; ++i) 374153f8ecb5169347e41a0734ee1698498d88b96c5Chad Rosier if (!isSimpleMSAsm(Pieces[i], TI)) 375153f8ecb5169347e41a0734ee1698498d88b96c5Chad Rosier return false; 37698ac608c79fb46e73715121018f0659fb3bbe3e8Chad Rosier return true; 3774b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier} 3784b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 379358ab765f36f70d0744ede7dc35ce74c0911e77dChad Rosier// Break the AsmSting into pieces (i.e., mnemonic and operands). 38038c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosierstatic void buildMSAsmPieces(StringRef Asm, std::vector<StringRef> &Pieces) { 38138c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier std::pair<StringRef,StringRef> Split = Asm.split(' '); 38238c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier 38338c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier // Mnemonic 38438c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier Pieces.push_back(Split.first); 38538c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier Asm = Split.second; 38638c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier 38738c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier // Operands 38838c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier while (!Asm.empty()) { 38938c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier Split = Asm.split(", "); 39038c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier Pieces.push_back(Split.first); 39138c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier Asm = Split.second; 39238c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier } 39338c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier} 39438c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier 395f0fbd776df77bc4b8b3e6ff3542b2e9117b2b905Chad Rosierstatic void buildMSAsmPieces(std::vector<std::string> &AsmStrings, 396f0fbd776df77bc4b8b3e6ff3542b2e9117b2b905Chad Rosier std::vector<std::vector<StringRef> > &Pieces) { 397f0fbd776df77bc4b8b3e6ff3542b2e9117b2b905Chad Rosier for (unsigned i = 0, e = AsmStrings.size(); i != e; ++i) 398f0fbd776df77bc4b8b3e6ff3542b2e9117b2b905Chad Rosier buildMSAsmPieces(AsmStrings[i], Pieces[i]); 399f0fbd776df77bc4b8b3e6ff3542b2e9117b2b905Chad Rosier} 400f0fbd776df77bc4b8b3e6ff3542b2e9117b2b905Chad Rosier 401682ad162f144ff8e8e5303d30bc48b6a6a41d0d6Chad Rosier// Build the unmodified AsmString used by the IR. Also build the individual 402682ad162f144ff8e8e5303d30bc48b6a6a41d0d6Chad Rosier// asm instruction(s) and place them in the AsmStrings vector; these are fed 403682ad162f144ff8e8e5303d30bc48b6a6a41d0d6Chad Rosier// to the AsmParser. 4049072a026a111726022b4f1c7f0a925d642ae8991Chad Rosierstatic std::string buildMSAsmString(Sema &SemaRef, ArrayRef<Token> AsmToks, 4059072a026a111726022b4f1c7f0a925d642ae8991Chad Rosier std::vector<std::string> &AsmStrings, 4069072a026a111726022b4f1c7f0a925d642ae8991Chad Rosier std::vector<std::pair<unsigned,unsigned> > &AsmTokRanges) { 4074b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); 4084b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 40938c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier SmallString<512> Res; 4104b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SmallString<512> Asm; 4119072a026a111726022b4f1c7f0a925d642ae8991Chad Rosier unsigned startTok = 0; 4124b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) { 4134b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier bool isNewAsm = i == 0 || AsmToks[i].isAtStartOfLine() || 4144b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier AsmToks[i].is(tok::kw_asm); 4154b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 4164b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (isNewAsm) { 41738c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier if (i) { 41838c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier AsmStrings.push_back(Asm.c_str()); 4199072a026a111726022b4f1c7f0a925d642ae8991Chad Rosier AsmTokRanges.push_back(std::make_pair(startTok, i-1)); 4209072a026a111726022b4f1c7f0a925d642ae8991Chad Rosier startTok = i; 42138c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier Res += Asm; 42238c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier Asm.clear(); 42338c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier Res += '\n'; 42438c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier } 4254b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (AsmToks[i].is(tok::kw_asm)) { 4264b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier i++; // Skip __asm 4274b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier assert (i != e && "Expected another token"); 4284b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 4294b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 4304b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 4314b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm) 4324b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Asm += ' '; 4334b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 4344b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Asm += getSpelling(SemaRef, AsmToks[i]); 4354b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 43638c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier AsmStrings.push_back(Asm.c_str()); 4379072a026a111726022b4f1c7f0a925d642ae8991Chad Rosier AsmTokRanges.push_back(std::make_pair(startTok, AsmToks.size()-1)); 43838c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier Res += Asm; 43938c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier return Res.c_str(); 4404b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier} 4414b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 4422735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier#define DEF_SIMPLE_MSASM \ 4432735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier MSAsmStmt *NS = \ 4442735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, \ 4452735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier /*IsVolatile*/ true, AsmToks, Inputs, Outputs, \ 4462735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier AsmString, Clobbers, EndLoc); 4472735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier 4484b5e48d39eb94ee12f3d89df60525053d8b0275eChad RosierStmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, 4494b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SourceLocation LBraceLoc, 4504b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier ArrayRef<Token> AsmToks, 4514b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SourceLocation EndLoc) { 4524b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // MS-style inline assembly is not fully supported, so emit a warning. 4534b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Diag(AsmLoc, diag::warn_unsupported_msasm); 4544b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SmallVector<StringRef,4> Clobbers; 4554b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier std::set<std::string> ClobberRegs; 4564b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SmallVector<IdentifierInfo*, 4> Inputs; 4574b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SmallVector<IdentifierInfo*, 4> Outputs; 4584b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 4594b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Empty asm statements don't need to instantiate the AsmParser, etc. 4604b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (AsmToks.empty()) { 4614b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier StringRef AsmString; 4622735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier DEF_SIMPLE_MSASM; 4634b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return Owned(NS); 4644b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 4654b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 46638c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier std::vector<std::string> AsmStrings; 4679072a026a111726022b4f1c7f0a925d642ae8991Chad Rosier std::vector<std::pair<unsigned,unsigned> > AsmTokRanges; 4689072a026a111726022b4f1c7f0a925d642ae8991Chad Rosier std::string AsmString = buildMSAsmString(*this, AsmToks, AsmStrings, AsmTokRanges); 46938c71d38e1b2a5f71c086b9c2efa9e8e69fa1bb5Chad Rosier 470e78460f4335766b55c3da6a43fcd072671076458Chad Rosier std::vector<std::vector<StringRef> > Pieces(AsmStrings.size()); 471f0fbd776df77bc4b8b3e6ff3542b2e9117b2b905Chad Rosier buildMSAsmPieces(AsmStrings, Pieces); 472153f8ecb5169347e41a0734ee1698498d88b96c5Chad Rosier 473153f8ecb5169347e41a0734ee1698498d88b96c5Chad Rosier bool IsSimple = isSimpleMSAsm(Pieces, Context.getTargetInfo()); 4744b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 4752735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier // AsmParser doesn't fully support these asm statements. 4762735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier if (bailOnMSAsm(Pieces)) { DEF_SIMPLE_MSASM; return Owned(NS); } 4774b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 4784b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Initialize targets and assembly printers/parsers. 4794b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier llvm::InitializeAllTargetInfos(); 4804b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier llvm::InitializeAllTargetMCs(); 4814b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier llvm::InitializeAllAsmParsers(); 4824b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 4834b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Get the target specific parser. 4844b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier std::string Error; 4854b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier const std::string &TT = Context.getTargetInfo().getTriple().getTriple(); 4864b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error)); 4874b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 4884b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT)); 4894b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); 4904b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo()); 4914b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OwningPtr<llvm::MCSubtargetInfo> 4924b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier STI(TheTarget->createMCSubtargetInfo(TT, "", "")); 4934b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 49498ac608c79fb46e73715121018f0659fb3bbe3e8Chad Rosier for (unsigned i = 0, e = AsmStrings.size(); i != e; ++i) { 4954b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier llvm::SourceMgr SrcMgr; 4964b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); 4974b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier llvm::MemoryBuffer *Buffer = 49898ac608c79fb46e73715121018f0659fb3bbe3e8Chad Rosier llvm::MemoryBuffer::getMemBuffer(AsmStrings[i], "<inline asm>"); 4994b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5004b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Tell SrcMgr about this buffer, which is what the parser will pick up. 5014b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc()); 5024b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5034b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx)); 5044b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OwningPtr<llvm::MCAsmParser> 5054b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI)); 5064b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier OwningPtr<llvm::MCTargetAsmParser> 5074b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier TargetParser(TheTarget->createMCAsmParser(*STI, *Parser)); 5084b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Change to the Intel dialect. 5094b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Parser->setAssemblerDialect(1); 5104b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Parser->setTargetParser(*TargetParser.get()); 5114b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5124b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Prime the lexer. 5134b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Parser->Lex(); 5144b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5154b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Parse the opcode. 5164b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier StringRef IDVal; 5174b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Parser->ParseIdentifier(IDVal); 5184b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5194b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Canonicalize the opcode to lower case. 5204b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SmallString<128> Opcode; 5214b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier for (unsigned i = 0, e = IDVal.size(); i != e; ++i) 5224b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Opcode.push_back(tolower(IDVal[i])); 5234b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5244b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Parse the operands. 5254b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier llvm::SMLoc IDLoc; 5264b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SmallVector<llvm::MCParsedAsmOperand*, 8> Operands; 5274b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier bool HadError = TargetParser->ParseInstruction(Opcode.str(), IDLoc, 5284b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Operands); 5292735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier // If we had an error parsing the operands, fail gracefully. 5302735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier if (HadError) { DEF_SIMPLE_MSASM; return Owned(NS); } 5314b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5324b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Match the MCInstr. 53383591b6d3f20ee84f4abe1c2574e90736aa84b11Chad Rosier unsigned ErrorInfo; 5344b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier SmallVector<llvm::MCInst, 2> Instrs; 53583591b6d3f20ee84f4abe1c2574e90736aa84b11Chad Rosier HadError = TargetParser->MatchInstruction(IDLoc, Operands, Instrs, 53651a6b3f58b0dbbc51a77b8f4a509720954406cebChad Rosier ErrorInfo, 53751a6b3f58b0dbbc51a77b8f4a509720954406cebChad Rosier /*matchingInlineAsm*/ true); 5382735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier // If we had an error parsing the operands, fail gracefully. 5392735df2eb16acfb92b8cd24e163e3a74a7a4d950Chad Rosier if (HadError) { DEF_SIMPLE_MSASM; return Owned(NS); } 5404b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5414b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Get the instruction descriptor. 5424b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier llvm::MCInst Inst = Instrs[0]; 5434b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo(); 5444b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier const llvm::MCInstrDesc &Desc = MII->get(Inst.getOpcode()); 5454b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier llvm::MCInstPrinter *IP = 5464b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI); 5474b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5484b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier // Build the list of clobbers. 5494b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier for (unsigned i = 0, e = Desc.getNumDefs(); i != e; ++i) { 5504b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier const llvm::MCOperand &Op = Inst.getOperand(i); 5514b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (!Op.isReg()) 5524b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier continue; 5534b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5544b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier std::string Reg; 5554b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier llvm::raw_string_ostream OS(Reg); 5564b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier IP->printRegName(OS, Op.getReg()); 5574b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5584b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier StringRef Clobber(OS.str()); 5594b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier if (!Context.getTargetInfo().isValidClobber(Clobber)) 5604b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return StmtError(Diag(AsmLoc, diag::err_asm_unknown_register_name) << 5614b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Clobber); 5624b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier ClobberRegs.insert(Reg); 5634b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 5644b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier } 5654b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier for (std::set<std::string>::iterator I = ClobberRegs.begin(), 5664b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier E = ClobberRegs.end(); I != E; ++I) 5674b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier Clobbers.push_back(*I); 5684b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier 5694b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier MSAsmStmt *NS = 5704b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple, 5714b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier /*IsVolatile*/ true, AsmToks, Inputs, Outputs, 5724b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier AsmString, Clobbers, EndLoc); 5734b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier return Owned(NS); 5744b5e48d39eb94ee12f3d89df60525053d8b0275eChad Rosier} 575