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