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