SemaStmtAsm.cpp revision ae07378ff9bf4af9bdd97a4607437ace4c32b7e7
1//===--- SemaStmtAsm.cpp - Semantic Analysis for Asm Statements -----------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements semantic analysis for inline asm statements. 11// 12//===----------------------------------------------------------------------===// 13 14#include "clang/Sema/SemaInternal.h" 15#include "clang/AST/RecordLayout.h" 16#include "clang/AST/TypeLoc.h" 17#include "clang/Basic/TargetInfo.h" 18#include "clang/Lex/Preprocessor.h" 19#include "clang/Sema/Initialization.h" 20#include "clang/Sema/Lookup.h" 21#include "clang/Sema/Scope.h" 22#include "clang/Sema/ScopeInfo.h" 23#include "llvm/ADT/ArrayRef.h" 24#include "llvm/ADT/BitVector.h" 25#include "llvm/ADT/SmallString.h" 26#include "llvm/MC/MCAsmInfo.h" 27#include "llvm/MC/MCContext.h" 28#include "llvm/MC/MCObjectFileInfo.h" 29#include "llvm/MC/MCParser/MCAsmParser.h" 30#include "llvm/MC/MCRegisterInfo.h" 31#include "llvm/MC/MCStreamer.h" 32#include "llvm/MC/MCSubtargetInfo.h" 33#include "llvm/MC/MCTargetAsmParser.h" 34#include "llvm/Support/SourceMgr.h" 35#include "llvm/Support/TargetRegistry.h" 36#include "llvm/Support/TargetSelect.h" 37using namespace clang; 38using namespace sema; 39 40/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently 41/// ignore "noop" casts in places where an lvalue is required by an inline asm. 42/// We emulate this behavior when -fheinous-gnu-extensions is specified, but 43/// provide a strong guidance to not use it. 44/// 45/// This method checks to see if the argument is an acceptable l-value and 46/// returns false if it is a case we can handle. 47static bool CheckAsmLValue(const Expr *E, Sema &S) { 48 // Type dependent expressions will be checked during instantiation. 49 if (E->isTypeDependent()) 50 return false; 51 52 if (E->isLValue()) 53 return false; // Cool, this is an lvalue. 54 55 // Okay, this is not an lvalue, but perhaps it is the result of a cast that we 56 // are supposed to allow. 57 const Expr *E2 = E->IgnoreParenNoopCasts(S.Context); 58 if (E != E2 && E2->isLValue()) { 59 if (!S.getLangOpts().HeinousExtensions) 60 S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue) 61 << E->getSourceRange(); 62 else 63 S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue) 64 << E->getSourceRange(); 65 // Accept, even if we emitted an error diagnostic. 66 return false; 67 } 68 69 // None of the above, just randomly invalid non-lvalue. 70 return true; 71} 72 73/// isOperandMentioned - Return true if the specified operand # is mentioned 74/// anywhere in the decomposed asm string. 75static bool isOperandMentioned(unsigned OpNo, 76 ArrayRef<GCCAsmStmt::AsmStringPiece> AsmStrPieces) { 77 for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) { 78 const GCCAsmStmt::AsmStringPiece &Piece = AsmStrPieces[p]; 79 if (!Piece.isOperand()) continue; 80 81 // If this is a reference to the input and if the input was the smaller 82 // one, then we have to reject this asm. 83 if (Piece.getOperandNo() == OpNo) 84 return true; 85 } 86 return false; 87} 88 89StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, 90 bool IsVolatile, unsigned NumOutputs, 91 unsigned NumInputs, IdentifierInfo **Names, 92 MultiExprArg constraints, MultiExprArg exprs, 93 Expr *asmString, MultiExprArg clobbers, 94 SourceLocation RParenLoc) { 95 unsigned NumClobbers = clobbers.size(); 96 StringLiteral **Constraints = 97 reinterpret_cast<StringLiteral**>(constraints.data()); 98 Expr **Exprs = exprs.data(); 99 StringLiteral *AsmString = cast<StringLiteral>(asmString); 100 StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.data()); 101 102 SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos; 103 104 // The parser verifies that there is a string literal here. 105 if (!AsmString->isAscii()) 106 return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character) 107 << AsmString->getSourceRange()); 108 109 for (unsigned i = 0; i != NumOutputs; i++) { 110 StringLiteral *Literal = Constraints[i]; 111 if (!Literal->isAscii()) 112 return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) 113 << Literal->getSourceRange()); 114 115 StringRef OutputName; 116 if (Names[i]) 117 OutputName = Names[i]->getName(); 118 119 TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName); 120 if (!Context.getTargetInfo().validateOutputConstraint(Info)) 121 return StmtError(Diag(Literal->getLocStart(), 122 diag::err_asm_invalid_output_constraint) 123 << Info.getConstraintStr()); 124 125 // Check that the output exprs are valid lvalues. 126 Expr *OutputExpr = Exprs[i]; 127 if (CheckAsmLValue(OutputExpr, *this)) { 128 return StmtError(Diag(OutputExpr->getLocStart(), 129 diag::err_asm_invalid_lvalue_in_output) 130 << OutputExpr->getSourceRange()); 131 } 132 133 OutputConstraintInfos.push_back(Info); 134 } 135 136 SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos; 137 138 for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) { 139 StringLiteral *Literal = Constraints[i]; 140 if (!Literal->isAscii()) 141 return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) 142 << Literal->getSourceRange()); 143 144 StringRef InputName; 145 if (Names[i]) 146 InputName = Names[i]->getName(); 147 148 TargetInfo::ConstraintInfo Info(Literal->getString(), InputName); 149 if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(), 150 NumOutputs, Info)) { 151 return StmtError(Diag(Literal->getLocStart(), 152 diag::err_asm_invalid_input_constraint) 153 << Info.getConstraintStr()); 154 } 155 156 Expr *InputExpr = Exprs[i]; 157 158 // Only allow void types for memory constraints. 159 if (Info.allowsMemory() && !Info.allowsRegister()) { 160 if (CheckAsmLValue(InputExpr, *this)) 161 return StmtError(Diag(InputExpr->getLocStart(), 162 diag::err_asm_invalid_lvalue_in_input) 163 << Info.getConstraintStr() 164 << InputExpr->getSourceRange()); 165 } 166 167 if (Info.allowsRegister()) { 168 if (InputExpr->getType()->isVoidType()) { 169 return StmtError(Diag(InputExpr->getLocStart(), 170 diag::err_asm_invalid_type_in_input) 171 << InputExpr->getType() << Info.getConstraintStr() 172 << InputExpr->getSourceRange()); 173 } 174 } 175 176 ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]); 177 if (Result.isInvalid()) 178 return StmtError(); 179 180 Exprs[i] = Result.take(); 181 InputConstraintInfos.push_back(Info); 182 183 const Type *Ty = Exprs[i]->getType().getTypePtr(); 184 if (Ty->isDependentType() || Ty->isIncompleteType()) 185 continue; 186 187 unsigned Size = Context.getTypeSize(Ty); 188 if (!Context.getTargetInfo().validateInputSize(Literal->getString(), 189 Size)) 190 return StmtError(Diag(InputExpr->getLocStart(), 191 diag::err_asm_invalid_input_size) 192 << Info.getConstraintStr()); 193 } 194 195 // Check that the clobbers are valid. 196 for (unsigned i = 0; i != NumClobbers; i++) { 197 StringLiteral *Literal = Clobbers[i]; 198 if (!Literal->isAscii()) 199 return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) 200 << Literal->getSourceRange()); 201 202 StringRef Clobber = Literal->getString(); 203 204 if (!Context.getTargetInfo().isValidClobber(Clobber)) 205 return StmtError(Diag(Literal->getLocStart(), 206 diag::err_asm_unknown_register_name) << Clobber); 207 } 208 209 GCCAsmStmt *NS = 210 new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, 211 NumInputs, Names, Constraints, Exprs, AsmString, 212 NumClobbers, Clobbers, RParenLoc); 213 // Validate the asm string, ensuring it makes sense given the operands we 214 // have. 215 SmallVector<GCCAsmStmt::AsmStringPiece, 8> Pieces; 216 unsigned DiagOffs; 217 if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) { 218 Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID) 219 << AsmString->getSourceRange(); 220 return StmtError(); 221 } 222 223 // Validate constraints and modifiers. 224 for (unsigned i = 0, e = Pieces.size(); i != e; ++i) { 225 GCCAsmStmt::AsmStringPiece &Piece = Pieces[i]; 226 if (!Piece.isOperand()) continue; 227 228 // Look for the correct constraint index. 229 unsigned Idx = 0; 230 unsigned ConstraintIdx = 0; 231 for (unsigned i = 0, e = NS->getNumOutputs(); i != e; ++i, ++ConstraintIdx) { 232 TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i]; 233 if (Idx == Piece.getOperandNo()) 234 break; 235 ++Idx; 236 237 if (Info.isReadWrite()) { 238 if (Idx == Piece.getOperandNo()) 239 break; 240 ++Idx; 241 } 242 } 243 244 for (unsigned i = 0, e = NS->getNumInputs(); i != e; ++i, ++ConstraintIdx) { 245 TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; 246 if (Idx == Piece.getOperandNo()) 247 break; 248 ++Idx; 249 250 if (Info.isReadWrite()) { 251 if (Idx == Piece.getOperandNo()) 252 break; 253 ++Idx; 254 } 255 } 256 257 // Now that we have the right indexes go ahead and check. 258 StringLiteral *Literal = Constraints[ConstraintIdx]; 259 const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr(); 260 if (Ty->isDependentType() || Ty->isIncompleteType()) 261 continue; 262 263 unsigned Size = Context.getTypeSize(Ty); 264 if (!Context.getTargetInfo() 265 .validateConstraintModifier(Literal->getString(), Piece.getModifier(), 266 Size)) 267 Diag(Exprs[ConstraintIdx]->getLocStart(), 268 diag::warn_asm_mismatched_size_modifier); 269 } 270 271 // Validate tied input operands for type mismatches. 272 for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) { 273 TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; 274 275 // If this is a tied constraint, verify that the output and input have 276 // either exactly the same type, or that they are int/ptr operands with the 277 // same size (int/long, int*/long, are ok etc). 278 if (!Info.hasTiedOperand()) continue; 279 280 unsigned TiedTo = Info.getTiedOperand(); 281 unsigned InputOpNo = i+NumOutputs; 282 Expr *OutputExpr = Exprs[TiedTo]; 283 Expr *InputExpr = Exprs[InputOpNo]; 284 285 if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent()) 286 continue; 287 288 QualType InTy = InputExpr->getType(); 289 QualType OutTy = OutputExpr->getType(); 290 if (Context.hasSameType(InTy, OutTy)) 291 continue; // All types can be tied to themselves. 292 293 // Decide if the input and output are in the same domain (integer/ptr or 294 // floating point. 295 enum AsmDomain { 296 AD_Int, AD_FP, AD_Other 297 } InputDomain, OutputDomain; 298 299 if (InTy->isIntegerType() || InTy->isPointerType()) 300 InputDomain = AD_Int; 301 else if (InTy->isRealFloatingType()) 302 InputDomain = AD_FP; 303 else 304 InputDomain = AD_Other; 305 306 if (OutTy->isIntegerType() || OutTy->isPointerType()) 307 OutputDomain = AD_Int; 308 else if (OutTy->isRealFloatingType()) 309 OutputDomain = AD_FP; 310 else 311 OutputDomain = AD_Other; 312 313 // They are ok if they are the same size and in the same domain. This 314 // allows tying things like: 315 // void* to int* 316 // void* to int if they are the same size. 317 // double to long double if they are the same size. 318 // 319 uint64_t OutSize = Context.getTypeSize(OutTy); 320 uint64_t InSize = Context.getTypeSize(InTy); 321 if (OutSize == InSize && InputDomain == OutputDomain && 322 InputDomain != AD_Other) 323 continue; 324 325 // If the smaller input/output operand is not mentioned in the asm string, 326 // then we can promote the smaller one to a larger input and the asm string 327 // won't notice. 328 bool SmallerValueMentioned = false; 329 330 // If this is a reference to the input and if the input was the smaller 331 // one, then we have to reject this asm. 332 if (isOperandMentioned(InputOpNo, Pieces)) { 333 // This is a use in the asm string of the smaller operand. Since we 334 // codegen this by promoting to a wider value, the asm will get printed 335 // "wrong". 336 SmallerValueMentioned |= InSize < OutSize; 337 } 338 if (isOperandMentioned(TiedTo, Pieces)) { 339 // If this is a reference to the output, and if the output is the larger 340 // value, then it's ok because we'll promote the input to the larger type. 341 SmallerValueMentioned |= OutSize < InSize; 342 } 343 344 // If the smaller value wasn't mentioned in the asm string, and if the 345 // output was a register, just extend the shorter one to the size of the 346 // larger one. 347 if (!SmallerValueMentioned && InputDomain != AD_Other && 348 OutputConstraintInfos[TiedTo].allowsRegister()) 349 continue; 350 351 // Either both of the operands were mentioned or the smaller one was 352 // mentioned. One more special case that we'll allow: if the tied input is 353 // integer, unmentioned, and is a constant, then we'll allow truncating it 354 // down to the size of the destination. 355 if (InputDomain == AD_Int && OutputDomain == AD_Int && 356 !isOperandMentioned(InputOpNo, Pieces) && 357 InputExpr->isEvaluatable(Context)) { 358 CastKind castKind = 359 (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast); 360 InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take(); 361 Exprs[InputOpNo] = InputExpr; 362 NS->setInputExpr(i, InputExpr); 363 continue; 364 } 365 366 Diag(InputExpr->getLocStart(), 367 diag::err_asm_tying_incompatible_types) 368 << InTy << OutTy << OutputExpr->getSourceRange() 369 << InputExpr->getSourceRange(); 370 return StmtError(); 371 } 372 373 return Owned(NS); 374} 375 376// getSpelling - Get the spelling of the AsmTok token. 377static StringRef getSpelling(Sema &SemaRef, Token AsmTok) { 378 StringRef Asm; 379 SmallString<512> TokenBuf; 380 TokenBuf.resize(512); 381 bool StringInvalid = false; 382 Asm = SemaRef.PP.getSpelling(AsmTok, TokenBuf, &StringInvalid); 383 assert (!StringInvalid && "Expected valid string!"); 384 return Asm; 385} 386 387// Build the inline assembly string. Returns true on error. 388static bool buildMSAsmString(Sema &SemaRef, 389 SourceLocation AsmLoc, 390 ArrayRef<Token> AsmToks, 391 SmallVectorImpl<unsigned> &TokOffsets, 392 std::string &AsmString) { 393 assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); 394 395 SmallString<512> Asm; 396 for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) { 397 bool isNewAsm = ((i == 0) || 398 AsmToks[i].isAtStartOfLine() || 399 AsmToks[i].is(tok::kw_asm)); 400 if (isNewAsm) { 401 if (i != 0) 402 Asm += "\n\t"; 403 404 if (AsmToks[i].is(tok::kw_asm)) { 405 i++; // Skip __asm 406 if (i == e) { 407 SemaRef.Diag(AsmLoc, diag::err_asm_empty); 408 return true; 409 } 410 411 } 412 } 413 414 if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm) 415 Asm += ' '; 416 417 StringRef Spelling = getSpelling(SemaRef, AsmToks[i]); 418 Asm += Spelling; 419 TokOffsets.push_back(Asm.size()); 420 } 421 AsmString = Asm.str(); 422 return false; 423} 424 425namespace { 426 427class MCAsmParserSemaCallbackImpl : public llvm::MCAsmParserSemaCallback { 428 Sema &SemaRef; 429 SourceLocation AsmLoc; 430 ArrayRef<Token> AsmToks; 431 ArrayRef<unsigned> TokOffsets; 432 433public: 434 MCAsmParserSemaCallbackImpl(Sema &Ref, SourceLocation Loc, 435 ArrayRef<Token> Toks, 436 ArrayRef<unsigned> Offsets) 437 : SemaRef(Ref), AsmLoc(Loc), AsmToks(Toks), TokOffsets(Offsets) { } 438 ~MCAsmParserSemaCallbackImpl() {} 439 440 void *LookupInlineAsmIdentifier(StringRef Name, void *SrcLoc, 441 unsigned &Length, unsigned &Size, 442 unsigned &Type, bool &IsVarDecl){ 443 SourceLocation Loc = SourceLocation::getFromPtrEncoding(SrcLoc); 444 445 NamedDecl *OpDecl = SemaRef.LookupInlineAsmIdentifier(Name, Loc, Length, 446 Size, Type, 447 IsVarDecl); 448 return static_cast<void *>(OpDecl); 449 } 450 451 bool LookupInlineAsmField(StringRef Base, StringRef Member, 452 unsigned &Offset) { 453 return SemaRef.LookupInlineAsmField(Base, Member, Offset, AsmLoc); 454 } 455 456 static void MSAsmDiagHandlerCallback(const llvm::SMDiagnostic &D, 457 void *Context) { 458 ((MCAsmParserSemaCallbackImpl*)Context)->MSAsmDiagHandler(D); 459 } 460 void MSAsmDiagHandler(const llvm::SMDiagnostic &D) { 461 // Compute an offset into the inline asm buffer. 462 // FIXME: This isn't right if .macro is involved (but hopefully, no 463 // real-world code does that). 464 const llvm::SourceMgr &LSM = *D.getSourceMgr(); 465 const llvm::MemoryBuffer *LBuf = 466 LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); 467 unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); 468 469 // Figure out which token that offset points into. 470 const unsigned *OffsetPtr = 471 std::lower_bound(TokOffsets.begin(), TokOffsets.end(), Offset); 472 unsigned TokIndex = OffsetPtr - TokOffsets.begin(); 473 474 // If we come up with an answer which seems sane, use it; otherwise, 475 // just point at the __asm keyword. 476 // FIXME: Assert the answer is sane once we handle .macro correctly. 477 SourceLocation Loc = AsmLoc; 478 if (TokIndex < AsmToks.size()) { 479 const Token *Tok = &AsmToks[TokIndex]; 480 Loc = Tok->getLocation(); 481 Loc = Loc.getLocWithOffset(Offset - (*OffsetPtr - Tok->getLength())); 482 } 483 SemaRef.Diag(Loc, diag::err_inline_ms_asm_parsing) << D.getMessage(); 484 } 485}; 486 487} 488 489NamedDecl *Sema::LookupInlineAsmIdentifier(StringRef Name, SourceLocation Loc, 490 unsigned &Length, unsigned &Size, 491 unsigned &Type, bool &IsVarDecl) { 492 Length = 1; 493 Size = 0; 494 Type = 0; 495 IsVarDecl = false; 496 LookupResult Result(*this, &Context.Idents.get(Name), Loc, 497 Sema::LookupOrdinaryName); 498 499 if (!LookupName(Result, getCurScope())) { 500 // If we don't find anything, return null; the AsmParser will assume 501 // it is a label of some sort. 502 return 0; 503 } 504 505 if (!Result.isSingleResult()) { 506 // FIXME: Diagnose result. 507 return 0; 508 } 509 510 NamedDecl *ND = Result.getFoundDecl(); 511 if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) { 512 if (VarDecl *Var = dyn_cast<VarDecl>(ND)) { 513 Type = Context.getTypeInfo(Var->getType()).first; 514 QualType Ty = Var->getType(); 515 if (Ty->isArrayType()) { 516 const ArrayType *ATy = Context.getAsArrayType(Ty); 517 Length = Type / Context.getTypeInfo(ATy->getElementType()).first; 518 Type /= Length; // Type is in terms of a single element. 519 } 520 Type /= 8; // Type is in terms of bits, but we want bytes. 521 Size = Length * Type; 522 IsVarDecl = true; 523 } 524 return ND; 525 } 526 527 // FIXME: Handle other kinds of results? (FieldDecl, etc.) 528 // FIXME: Diagnose if we find something we can't handle, like a typedef. 529 return 0; 530} 531 532bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member, 533 unsigned &Offset, SourceLocation AsmLoc) { 534 Offset = 0; 535 LookupResult BaseResult(*this, &Context.Idents.get(Base), SourceLocation(), 536 LookupOrdinaryName); 537 538 if (!LookupName(BaseResult, getCurScope())) 539 return true; 540 541 if (!BaseResult.isSingleResult()) 542 return true; 543 544 NamedDecl *FoundDecl = BaseResult.getFoundDecl(); 545 const RecordType *RT = 0; 546 if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl)) { 547 RT = VD->getType()->getAs<RecordType>(); 548 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(FoundDecl)) { 549 RT = TD->getUnderlyingType()->getAs<RecordType>(); 550 } 551 if (!RT) 552 return true; 553 554 if (RequireCompleteType(AsmLoc, QualType(RT, 0), 0)) 555 return true; 556 557 LookupResult FieldResult(*this, &Context.Idents.get(Member), SourceLocation(), 558 LookupMemberName); 559 560 if (!LookupQualifiedName(FieldResult, RT->getDecl())) 561 return true; 562 563 // FIXME: Handle IndirectFieldDecl? 564 FieldDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl()); 565 if (!FD) 566 return true; 567 568 const ASTRecordLayout &RL = Context.getASTRecordLayout(RT->getDecl()); 569 unsigned i = FD->getFieldIndex(); 570 CharUnits Result = Context.toCharUnitsFromBits(RL.getFieldOffset(i)); 571 Offset = (unsigned)Result.getQuantity(); 572 573 return false; 574} 575 576StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, 577 ArrayRef<Token> AsmToks,SourceLocation EndLoc) { 578 SmallVector<IdentifierInfo*, 4> Names; 579 SmallVector<StringRef, 4> ConstraintRefs; 580 SmallVector<Expr*, 4> Exprs; 581 SmallVector<StringRef, 4> ClobberRefs; 582 583 llvm::Triple TheTriple = Context.getTargetInfo().getTriple(); 584 llvm::Triple::ArchType ArchTy = TheTriple.getArch(); 585 bool UnsupportedArch = ArchTy != llvm::Triple::x86 && 586 ArchTy != llvm::Triple::x86_64; 587 if (UnsupportedArch) 588 Diag(AsmLoc, diag::err_msasm_unsupported_arch) << TheTriple.getArchName(); 589 590 // Empty asm statements don't need to instantiate the AsmParser, etc. 591 if (UnsupportedArch || AsmToks.empty()) { 592 StringRef EmptyAsmStr; 593 MSAsmStmt *NS = 594 new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, 595 /*IsVolatile*/ true, AsmToks, /*NumOutputs*/ 0, 596 /*NumInputs*/ 0, Names, ConstraintRefs, Exprs, 597 EmptyAsmStr, ClobberRefs, EndLoc); 598 return Owned(NS); 599 } 600 601 std::string AsmString; 602 SmallVector<unsigned, 8> TokOffsets; 603 if (buildMSAsmString(*this, AsmLoc, AsmToks, TokOffsets, AsmString)) 604 return StmtError(); 605 606 // Get the target specific parser. 607 std::string Error; 608 const std::string &TT = TheTriple.getTriple(); 609 const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error)); 610 611 OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT)); 612 OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); 613 OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo()); 614 OwningPtr<llvm::MCSubtargetInfo> 615 STI(TheTarget->createMCSubtargetInfo(TT, "", "")); 616 617 llvm::SourceMgr SrcMgr; 618 llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); 619 llvm::MemoryBuffer *Buffer = 620 llvm::MemoryBuffer::getMemBuffer(AsmString, "<inline asm>"); 621 622 // Tell SrcMgr about this buffer, which is what the parser will pick up. 623 SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc()); 624 625 OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx)); 626 OwningPtr<llvm::MCAsmParser> 627 Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI)); 628 OwningPtr<llvm::MCTargetAsmParser> 629 TargetParser(TheTarget->createMCAsmParser(*STI, *Parser)); 630 631 // Get the instruction descriptor. 632 const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo(); 633 llvm::MCInstPrinter *IP = 634 TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI); 635 636 // Change to the Intel dialect. 637 Parser->setAssemblerDialect(1); 638 Parser->setTargetParser(*TargetParser.get()); 639 Parser->setParsingInlineAsm(true); 640 TargetParser->setParsingInlineAsm(true); 641 642 MCAsmParserSemaCallbackImpl MCAPSI(*this, AsmLoc, AsmToks, TokOffsets); 643 TargetParser->setSemaCallback(&MCAPSI); 644 SrcMgr.setDiagHandler(MCAsmParserSemaCallbackImpl::MSAsmDiagHandlerCallback, 645 &MCAPSI); 646 647 unsigned NumOutputs; 648 unsigned NumInputs; 649 std::string AsmStringIR; 650 SmallVector<std::pair<void *, bool>, 4> OpDecls; 651 SmallVector<std::string, 4> Constraints; 652 SmallVector<std::string, 4> Clobbers; 653 if (Parser->ParseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, 654 NumOutputs, NumInputs, OpDecls, Constraints, 655 Clobbers, MII, IP, MCAPSI)) 656 return StmtError(); 657 658 // Build the vector of clobber StringRefs. 659 unsigned NumClobbers = Clobbers.size(); 660 ClobberRefs.resize(NumClobbers); 661 for (unsigned i = 0; i != NumClobbers; ++i) 662 ClobberRefs[i] = StringRef(Clobbers[i]); 663 664 // Recast the void pointers and build the vector of constraint StringRefs. 665 unsigned NumExprs = NumOutputs + NumInputs; 666 Names.resize(NumExprs); 667 ConstraintRefs.resize(NumExprs); 668 Exprs.resize(NumExprs); 669 for (unsigned i = 0, e = NumExprs; i != e; ++i) { 670 NamedDecl *OpDecl = static_cast<NamedDecl *>(OpDecls[i].first); 671 if (!OpDecl) 672 return StmtError(); 673 674 DeclarationNameInfo NameInfo(OpDecl->getDeclName(), AsmLoc); 675 ExprResult OpExpr = BuildDeclarationNameExpr(CXXScopeSpec(), NameInfo, 676 OpDecl); 677 if (OpExpr.isInvalid()) 678 return StmtError(); 679 680 // Need address of variable. 681 if (OpDecls[i].second) 682 OpExpr = BuildUnaryOp(getCurScope(), AsmLoc, clang::UO_AddrOf, 683 OpExpr.take()); 684 685 Names[i] = OpDecl->getIdentifier(); 686 ConstraintRefs[i] = StringRef(Constraints[i]); 687 Exprs[i] = OpExpr.take(); 688 } 689 690 bool IsSimple = NumExprs > 0; 691 MSAsmStmt *NS = 692 new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple, 693 /*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs, 694 Names, ConstraintRefs, Exprs, AsmStringIR, 695 ClobberRefs, EndLoc); 696 return Owned(NS); 697} 698