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" 37 using namespace clang; 38 using 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. 47 static 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. 75 static 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 89 StmtResult 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 if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(), 133 diag::err_dereference_incomplete_type)) 134 return StmtError(); 135 136 OutputConstraintInfos.push_back(Info); 137 } 138 139 SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos; 140 141 for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) { 142 StringLiteral *Literal = Constraints[i]; 143 if (!Literal->isAscii()) 144 return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) 145 << Literal->getSourceRange()); 146 147 StringRef InputName; 148 if (Names[i]) 149 InputName = Names[i]->getName(); 150 151 TargetInfo::ConstraintInfo Info(Literal->getString(), InputName); 152 if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(), 153 NumOutputs, Info)) { 154 return StmtError(Diag(Literal->getLocStart(), 155 diag::err_asm_invalid_input_constraint) 156 << Info.getConstraintStr()); 157 } 158 159 Expr *InputExpr = Exprs[i]; 160 161 // Only allow void types for memory constraints. 162 if (Info.allowsMemory() && !Info.allowsRegister()) { 163 if (CheckAsmLValue(InputExpr, *this)) 164 return StmtError(Diag(InputExpr->getLocStart(), 165 diag::err_asm_invalid_lvalue_in_input) 166 << Info.getConstraintStr() 167 << InputExpr->getSourceRange()); 168 } 169 170 if (Info.allowsRegister()) { 171 if (InputExpr->getType()->isVoidType()) { 172 return StmtError(Diag(InputExpr->getLocStart(), 173 diag::err_asm_invalid_type_in_input) 174 << InputExpr->getType() << Info.getConstraintStr() 175 << InputExpr->getSourceRange()); 176 } 177 } 178 179 ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]); 180 if (Result.isInvalid()) 181 return StmtError(); 182 183 Exprs[i] = Result.take(); 184 InputConstraintInfos.push_back(Info); 185 186 const Type *Ty = Exprs[i]->getType().getTypePtr(); 187 if (Ty->isDependentType()) 188 continue; 189 190 if (!Ty->isVoidType() || !Info.allowsMemory()) 191 if (RequireCompleteType(InputExpr->getLocStart(), Exprs[i]->getType(), 192 diag::err_dereference_incomplete_type)) 193 return StmtError(); 194 195 unsigned Size = Context.getTypeSize(Ty); 196 if (!Context.getTargetInfo().validateInputSize(Literal->getString(), 197 Size)) 198 return StmtError(Diag(InputExpr->getLocStart(), 199 diag::err_asm_invalid_input_size) 200 << Info.getConstraintStr()); 201 } 202 203 // Check that the clobbers are valid. 204 for (unsigned i = 0; i != NumClobbers; i++) { 205 StringLiteral *Literal = Clobbers[i]; 206 if (!Literal->isAscii()) 207 return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) 208 << Literal->getSourceRange()); 209 210 StringRef Clobber = Literal->getString(); 211 212 if (!Context.getTargetInfo().isValidClobber(Clobber)) 213 return StmtError(Diag(Literal->getLocStart(), 214 diag::err_asm_unknown_register_name) << Clobber); 215 } 216 217 GCCAsmStmt *NS = 218 new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, 219 NumInputs, Names, Constraints, Exprs, AsmString, 220 NumClobbers, Clobbers, RParenLoc); 221 // Validate the asm string, ensuring it makes sense given the operands we 222 // have. 223 SmallVector<GCCAsmStmt::AsmStringPiece, 8> Pieces; 224 unsigned DiagOffs; 225 if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) { 226 Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID) 227 << AsmString->getSourceRange(); 228 return StmtError(); 229 } 230 231 // Validate constraints and modifiers. 232 for (unsigned i = 0, e = Pieces.size(); i != e; ++i) { 233 GCCAsmStmt::AsmStringPiece &Piece = Pieces[i]; 234 if (!Piece.isOperand()) continue; 235 236 // Look for the correct constraint index. 237 unsigned Idx = 0; 238 unsigned ConstraintIdx = 0; 239 for (unsigned i = 0, e = NS->getNumOutputs(); i != e; ++i, ++ConstraintIdx) { 240 TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i]; 241 if (Idx == Piece.getOperandNo()) 242 break; 243 ++Idx; 244 245 if (Info.isReadWrite()) { 246 if (Idx == Piece.getOperandNo()) 247 break; 248 ++Idx; 249 } 250 } 251 252 for (unsigned i = 0, e = NS->getNumInputs(); i != e; ++i, ++ConstraintIdx) { 253 TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; 254 if (Idx == Piece.getOperandNo()) 255 break; 256 ++Idx; 257 258 if (Info.isReadWrite()) { 259 if (Idx == Piece.getOperandNo()) 260 break; 261 ++Idx; 262 } 263 } 264 265 // Now that we have the right indexes go ahead and check. 266 StringLiteral *Literal = Constraints[ConstraintIdx]; 267 const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr(); 268 if (Ty->isDependentType() || Ty->isIncompleteType()) 269 continue; 270 271 unsigned Size = Context.getTypeSize(Ty); 272 if (!Context.getTargetInfo() 273 .validateConstraintModifier(Literal->getString(), Piece.getModifier(), 274 Size)) 275 Diag(Exprs[ConstraintIdx]->getLocStart(), 276 diag::warn_asm_mismatched_size_modifier); 277 } 278 279 // Validate tied input operands for type mismatches. 280 for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) { 281 TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; 282 283 // If this is a tied constraint, verify that the output and input have 284 // either exactly the same type, or that they are int/ptr operands with the 285 // same size (int/long, int*/long, are ok etc). 286 if (!Info.hasTiedOperand()) continue; 287 288 unsigned TiedTo = Info.getTiedOperand(); 289 unsigned InputOpNo = i+NumOutputs; 290 Expr *OutputExpr = Exprs[TiedTo]; 291 Expr *InputExpr = Exprs[InputOpNo]; 292 293 if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent()) 294 continue; 295 296 QualType InTy = InputExpr->getType(); 297 QualType OutTy = OutputExpr->getType(); 298 if (Context.hasSameType(InTy, OutTy)) 299 continue; // All types can be tied to themselves. 300 301 // Decide if the input and output are in the same domain (integer/ptr or 302 // floating point. 303 enum AsmDomain { 304 AD_Int, AD_FP, AD_Other 305 } InputDomain, OutputDomain; 306 307 if (InTy->isIntegerType() || InTy->isPointerType()) 308 InputDomain = AD_Int; 309 else if (InTy->isRealFloatingType()) 310 InputDomain = AD_FP; 311 else 312 InputDomain = AD_Other; 313 314 if (OutTy->isIntegerType() || OutTy->isPointerType()) 315 OutputDomain = AD_Int; 316 else if (OutTy->isRealFloatingType()) 317 OutputDomain = AD_FP; 318 else 319 OutputDomain = AD_Other; 320 321 // They are ok if they are the same size and in the same domain. This 322 // allows tying things like: 323 // void* to int* 324 // void* to int if they are the same size. 325 // double to long double if they are the same size. 326 // 327 uint64_t OutSize = Context.getTypeSize(OutTy); 328 uint64_t InSize = Context.getTypeSize(InTy); 329 if (OutSize == InSize && InputDomain == OutputDomain && 330 InputDomain != AD_Other) 331 continue; 332 333 // If the smaller input/output operand is not mentioned in the asm string, 334 // then we can promote the smaller one to a larger input and the asm string 335 // won't notice. 336 bool SmallerValueMentioned = false; 337 338 // If this is a reference to the input and if the input was the smaller 339 // one, then we have to reject this asm. 340 if (isOperandMentioned(InputOpNo, Pieces)) { 341 // This is a use in the asm string of the smaller operand. Since we 342 // codegen this by promoting to a wider value, the asm will get printed 343 // "wrong". 344 SmallerValueMentioned |= InSize < OutSize; 345 } 346 if (isOperandMentioned(TiedTo, Pieces)) { 347 // If this is a reference to the output, and if the output is the larger 348 // value, then it's ok because we'll promote the input to the larger type. 349 SmallerValueMentioned |= OutSize < InSize; 350 } 351 352 // If the smaller value wasn't mentioned in the asm string, and if the 353 // output was a register, just extend the shorter one to the size of the 354 // larger one. 355 if (!SmallerValueMentioned && InputDomain != AD_Other && 356 OutputConstraintInfos[TiedTo].allowsRegister()) 357 continue; 358 359 // Either both of the operands were mentioned or the smaller one was 360 // mentioned. One more special case that we'll allow: if the tied input is 361 // integer, unmentioned, and is a constant, then we'll allow truncating it 362 // down to the size of the destination. 363 if (InputDomain == AD_Int && OutputDomain == AD_Int && 364 !isOperandMentioned(InputOpNo, Pieces) && 365 InputExpr->isEvaluatable(Context)) { 366 CastKind castKind = 367 (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast); 368 InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take(); 369 Exprs[InputOpNo] = InputExpr; 370 NS->setInputExpr(i, InputExpr); 371 continue; 372 } 373 374 Diag(InputExpr->getLocStart(), 375 diag::err_asm_tying_incompatible_types) 376 << InTy << OutTy << OutputExpr->getSourceRange() 377 << InputExpr->getSourceRange(); 378 return StmtError(); 379 } 380 381 return Owned(NS); 382 } 383 384 // getSpelling - Get the spelling of the AsmTok token. 385 static StringRef getSpelling(Sema &SemaRef, Token AsmTok) { 386 StringRef Asm; 387 SmallString<512> TokenBuf; 388 TokenBuf.resize(512); 389 bool StringInvalid = false; 390 Asm = SemaRef.PP.getSpelling(AsmTok, TokenBuf, &StringInvalid); 391 assert (!StringInvalid && "Expected valid string!"); 392 return Asm; 393 } 394 395 // Build the inline assembly string. Returns true on error. 396 static bool buildMSAsmString(Sema &SemaRef, 397 SourceLocation AsmLoc, 398 ArrayRef<Token> AsmToks, 399 SmallVectorImpl<unsigned> &TokOffsets, 400 std::string &AsmString) { 401 assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); 402 403 SmallString<512> Asm; 404 for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) { 405 bool isNewAsm = ((i == 0) || 406 AsmToks[i].isAtStartOfLine() || 407 AsmToks[i].is(tok::kw_asm)); 408 if (isNewAsm) { 409 if (i != 0) 410 Asm += "\n\t"; 411 412 if (AsmToks[i].is(tok::kw_asm)) { 413 i++; // Skip __asm 414 if (i == e) { 415 SemaRef.Diag(AsmLoc, diag::err_asm_empty); 416 return true; 417 } 418 419 } 420 } 421 422 if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm) 423 Asm += ' '; 424 425 StringRef Spelling = getSpelling(SemaRef, AsmToks[i]); 426 Asm += Spelling; 427 TokOffsets.push_back(Asm.size()); 428 } 429 AsmString = Asm.str(); 430 return false; 431 } 432 433 namespace { 434 435 class MCAsmParserSemaCallbackImpl : public llvm::MCAsmParserSemaCallback { 436 Sema &SemaRef; 437 SourceLocation AsmLoc; 438 ArrayRef<Token> AsmToks; 439 ArrayRef<unsigned> TokOffsets; 440 441 public: 442 MCAsmParserSemaCallbackImpl(Sema &Ref, SourceLocation Loc, 443 ArrayRef<Token> Toks, 444 ArrayRef<unsigned> Offsets) 445 : SemaRef(Ref), AsmLoc(Loc), AsmToks(Toks), TokOffsets(Offsets) { } 446 ~MCAsmParserSemaCallbackImpl() {} 447 448 void *LookupInlineAsmIdentifier(StringRef Name, void *SrcLoc, 449 unsigned &Length, unsigned &Size, 450 unsigned &Type, bool &IsVarDecl){ 451 SourceLocation Loc = SourceLocation::getFromPtrEncoding(SrcLoc); 452 453 NamedDecl *OpDecl = SemaRef.LookupInlineAsmIdentifier(Name, Loc, Length, 454 Size, Type, 455 IsVarDecl); 456 return static_cast<void *>(OpDecl); 457 } 458 459 bool LookupInlineAsmField(StringRef Base, StringRef Member, 460 unsigned &Offset) { 461 return SemaRef.LookupInlineAsmField(Base, Member, Offset, AsmLoc); 462 } 463 464 static void MSAsmDiagHandlerCallback(const llvm::SMDiagnostic &D, 465 void *Context) { 466 ((MCAsmParserSemaCallbackImpl*)Context)->MSAsmDiagHandler(D); 467 } 468 void MSAsmDiagHandler(const llvm::SMDiagnostic &D) { 469 // Compute an offset into the inline asm buffer. 470 // FIXME: This isn't right if .macro is involved (but hopefully, no 471 // real-world code does that). 472 const llvm::SourceMgr &LSM = *D.getSourceMgr(); 473 const llvm::MemoryBuffer *LBuf = 474 LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); 475 unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); 476 477 // Figure out which token that offset points into. 478 const unsigned *OffsetPtr = 479 std::lower_bound(TokOffsets.begin(), TokOffsets.end(), Offset); 480 unsigned TokIndex = OffsetPtr - TokOffsets.begin(); 481 482 // If we come up with an answer which seems sane, use it; otherwise, 483 // just point at the __asm keyword. 484 // FIXME: Assert the answer is sane once we handle .macro correctly. 485 SourceLocation Loc = AsmLoc; 486 if (TokIndex < AsmToks.size()) { 487 const Token *Tok = &AsmToks[TokIndex]; 488 Loc = Tok->getLocation(); 489 Loc = Loc.getLocWithOffset(Offset - (*OffsetPtr - Tok->getLength())); 490 } 491 SemaRef.Diag(Loc, diag::err_inline_ms_asm_parsing) << D.getMessage(); 492 } 493 }; 494 495 } 496 497 // FIXME: Temporary hack until the frontend parser is hooked up to parse 498 // variables. 499 static bool isIdentifierChar(char c) { 500 return isalnum(c) || c == '_' || c == '$' || c == '.' || c == '@'; 501 } 502 503 static void lexIdentifier(const char *&CurPtr) { 504 while (isIdentifierChar(*CurPtr)) 505 ++CurPtr; 506 } 507 508 static StringRef parseIdentifier(StringRef Identifier) { 509 const char *StartPtr = Identifier.data(), *EndPtr, *CurPtr; 510 EndPtr = StartPtr + Identifier.size(); 511 CurPtr = StartPtr; 512 while(CurPtr <= EndPtr) { 513 if (isIdentifierChar(*CurPtr)) 514 lexIdentifier(CurPtr); 515 else if (CurPtr[0] == ':' && CurPtr[1] == ':') 516 CurPtr += 2; 517 else 518 break; 519 } 520 return StringRef(StartPtr, CurPtr - StartPtr); 521 } 522 523 NamedDecl *Sema::LookupInlineAsmIdentifier(StringRef Name, SourceLocation Loc, 524 unsigned &Length, unsigned &Size, 525 unsigned &Type, bool &IsVarDecl) { 526 // FIXME: Temporary hack until the frontend parser is hooked up to parse 527 // variables. 528 StringRef ParsedName = parseIdentifier(Name); 529 assert (ParsedName == Name && "Identifier not parsed correctly!"); 530 531 Length = 1; 532 Size = 0; 533 Type = 0; 534 IsVarDecl = false; 535 LookupResult Result(*this, &Context.Idents.get(Name), Loc, 536 Sema::LookupOrdinaryName); 537 538 if (!LookupName(Result, getCurScope())) { 539 // If we don't find anything, return null; the AsmParser will assume 540 // it is a label of some sort. 541 return 0; 542 } 543 544 if (!Result.isSingleResult()) { 545 // FIXME: Diagnose result. 546 return 0; 547 } 548 549 NamedDecl *FoundDecl = Result.getFoundDecl(); 550 if (isa<FunctionDecl>(FoundDecl)) 551 return FoundDecl; 552 if (VarDecl *Var = dyn_cast<VarDecl>(FoundDecl)) { 553 QualType Ty = Var->getType(); 554 Type = Size = Context.getTypeSizeInChars(Ty).getQuantity(); 555 if (Ty->isArrayType()) { 556 const ArrayType *ATy = Context.getAsArrayType(Ty); 557 Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity(); 558 Length = Size / Type; 559 } 560 IsVarDecl = true; 561 return FoundDecl; 562 } 563 564 // FIXME: Handle other kinds of results? (FieldDecl, etc.) 565 // FIXME: Diagnose if we find something we can't handle, like a typedef. 566 return 0; 567 } 568 569 bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member, 570 unsigned &Offset, SourceLocation AsmLoc) { 571 Offset = 0; 572 LookupResult BaseResult(*this, &Context.Idents.get(Base), SourceLocation(), 573 LookupOrdinaryName); 574 575 if (!LookupName(BaseResult, getCurScope())) 576 return true; 577 578 if (!BaseResult.isSingleResult()) 579 return true; 580 581 const RecordType *RT = 0; 582 NamedDecl *FoundDecl = BaseResult.getFoundDecl(); 583 if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl)) 584 RT = VD->getType()->getAs<RecordType>(); 585 else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(FoundDecl)) 586 RT = TD->getUnderlyingType()->getAs<RecordType>(); 587 if (!RT) 588 return true; 589 590 if (RequireCompleteType(AsmLoc, QualType(RT, 0), 0)) 591 return true; 592 593 LookupResult FieldResult(*this, &Context.Idents.get(Member), SourceLocation(), 594 LookupMemberName); 595 596 if (!LookupQualifiedName(FieldResult, RT->getDecl())) 597 return true; 598 599 // FIXME: Handle IndirectFieldDecl? 600 FieldDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl()); 601 if (!FD) 602 return true; 603 604 const ASTRecordLayout &RL = Context.getASTRecordLayout(RT->getDecl()); 605 unsigned i = FD->getFieldIndex(); 606 CharUnits Result = Context.toCharUnitsFromBits(RL.getFieldOffset(i)); 607 Offset = (unsigned)Result.getQuantity(); 608 609 return false; 610 } 611 612 StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, 613 ArrayRef<Token> AsmToks,SourceLocation EndLoc) { 614 SmallVector<IdentifierInfo*, 4> Names; 615 SmallVector<StringRef, 4> ConstraintRefs; 616 SmallVector<Expr*, 4> Exprs; 617 SmallVector<StringRef, 4> ClobberRefs; 618 619 llvm::Triple TheTriple = Context.getTargetInfo().getTriple(); 620 llvm::Triple::ArchType ArchTy = TheTriple.getArch(); 621 bool UnsupportedArch = ArchTy != llvm::Triple::x86 && 622 ArchTy != llvm::Triple::x86_64; 623 if (UnsupportedArch) 624 Diag(AsmLoc, diag::err_msasm_unsupported_arch) << TheTriple.getArchName(); 625 626 // Empty asm statements don't need to instantiate the AsmParser, etc. 627 if (UnsupportedArch || AsmToks.empty()) { 628 StringRef EmptyAsmStr; 629 MSAsmStmt *NS = 630 new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, 631 /*IsVolatile*/ true, AsmToks, /*NumOutputs*/ 0, 632 /*NumInputs*/ 0, Names, ConstraintRefs, Exprs, 633 EmptyAsmStr, ClobberRefs, EndLoc); 634 return Owned(NS); 635 } 636 637 std::string AsmString; 638 SmallVector<unsigned, 8> TokOffsets; 639 if (buildMSAsmString(*this, AsmLoc, AsmToks, TokOffsets, AsmString)) 640 return StmtError(); 641 642 // Get the target specific parser. 643 std::string Error; 644 const std::string &TT = TheTriple.getTriple(); 645 const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error)); 646 647 OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT)); 648 OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); 649 OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo()); 650 OwningPtr<llvm::MCSubtargetInfo> 651 STI(TheTarget->createMCSubtargetInfo(TT, "", "")); 652 653 llvm::SourceMgr SrcMgr; 654 llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); 655 llvm::MemoryBuffer *Buffer = 656 llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS inline asm>"); 657 658 // Tell SrcMgr about this buffer, which is what the parser will pick up. 659 SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc()); 660 661 OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx)); 662 OwningPtr<llvm::MCAsmParser> 663 Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI)); 664 OwningPtr<llvm::MCTargetAsmParser> 665 TargetParser(TheTarget->createMCAsmParser(*STI, *Parser)); 666 667 // Get the instruction descriptor. 668 const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo(); 669 llvm::MCInstPrinter *IP = 670 TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI); 671 672 // Change to the Intel dialect. 673 Parser->setAssemblerDialect(1); 674 Parser->setTargetParser(*TargetParser.get()); 675 Parser->setParsingInlineAsm(true); 676 TargetParser->setParsingInlineAsm(true); 677 678 MCAsmParserSemaCallbackImpl MCAPSI(*this, AsmLoc, AsmToks, TokOffsets); 679 TargetParser->setSemaCallback(&MCAPSI); 680 SrcMgr.setDiagHandler(MCAsmParserSemaCallbackImpl::MSAsmDiagHandlerCallback, 681 &MCAPSI); 682 683 unsigned NumOutputs; 684 unsigned NumInputs; 685 std::string AsmStringIR; 686 SmallVector<std::pair<void *, bool>, 4> OpDecls; 687 SmallVector<std::string, 4> Constraints; 688 SmallVector<std::string, 4> Clobbers; 689 if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, 690 NumOutputs, NumInputs, OpDecls, Constraints, 691 Clobbers, MII, IP, MCAPSI)) 692 return StmtError(); 693 694 // Build the vector of clobber StringRefs. 695 unsigned NumClobbers = Clobbers.size(); 696 ClobberRefs.resize(NumClobbers); 697 for (unsigned i = 0; i != NumClobbers; ++i) 698 ClobberRefs[i] = StringRef(Clobbers[i]); 699 700 // Recast the void pointers and build the vector of constraint StringRefs. 701 unsigned NumExprs = NumOutputs + NumInputs; 702 Names.resize(NumExprs); 703 ConstraintRefs.resize(NumExprs); 704 Exprs.resize(NumExprs); 705 for (unsigned i = 0, e = NumExprs; i != e; ++i) { 706 NamedDecl *OpDecl = static_cast<NamedDecl *>(OpDecls[i].first); 707 if (!OpDecl) 708 return StmtError(); 709 710 DeclarationNameInfo NameInfo(OpDecl->getDeclName(), AsmLoc); 711 ExprResult OpExpr = BuildDeclarationNameExpr(CXXScopeSpec(), NameInfo, 712 OpDecl); 713 if (OpExpr.isInvalid()) 714 return StmtError(); 715 716 // Need address of variable. 717 if (OpDecls[i].second) 718 OpExpr = BuildUnaryOp(getCurScope(), AsmLoc, clang::UO_AddrOf, 719 OpExpr.take()); 720 721 Names[i] = OpDecl->getIdentifier(); 722 ConstraintRefs[i] = StringRef(Constraints[i]); 723 Exprs[i] = OpExpr.take(); 724 } 725 726 bool IsSimple = NumExprs > 0; 727 MSAsmStmt *NS = 728 new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple, 729 /*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs, 730 Names, ConstraintRefs, Exprs, AsmStringIR, 731 ClobberRefs, EndLoc); 732 return Owned(NS); 733 } 734