• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
CheckAsmLValue(const Expr * E,Sema & S)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.
isOperandMentioned(unsigned OpNo,ArrayRef<GCCAsmStmt::AsmStringPiece> AsmStrPieces)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 
ActOnGCCAsmStmt(SourceLocation AsmLoc,bool IsSimple,bool IsVolatile,unsigned NumOutputs,unsigned NumInputs,IdentifierInfo ** Names,MultiExprArg constraints,MultiExprArg exprs,Expr * asmString,MultiExprArg clobbers,SourceLocation RParenLoc)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 
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.
getSpelling(Sema & SemaRef,Token AsmTok)377 static 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.
buildMSAsmString(Sema & SemaRef,SourceLocation AsmLoc,ArrayRef<Token> AsmToks,SmallVectorImpl<unsigned> & TokOffsets,std::string & AsmString)388 static 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 
425 namespace {
426 
427 class MCAsmParserSemaCallbackImpl : public llvm::MCAsmParserSemaCallback {
428   Sema &SemaRef;
429   SourceLocation AsmLoc;
430   ArrayRef<Token> AsmToks;
431   ArrayRef<unsigned> TokOffsets;
432 
433 public:
MCAsmParserSemaCallbackImpl(Sema & Ref,SourceLocation Loc,ArrayRef<Token> Toks,ArrayRef<unsigned> Offsets)434   MCAsmParserSemaCallbackImpl(Sema &Ref, SourceLocation Loc,
435                               ArrayRef<Token> Toks,
436                               ArrayRef<unsigned> Offsets)
437     : SemaRef(Ref), AsmLoc(Loc), AsmToks(Toks), TokOffsets(Offsets) { }
~MCAsmParserSemaCallbackImpl()438   ~MCAsmParserSemaCallbackImpl() {}
439 
LookupInlineAsmIdentifier(StringRef Name,void * SrcLoc,unsigned & Length,unsigned & Size,unsigned & Type,bool & IsVarDecl)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 
LookupInlineAsmField(StringRef Base,StringRef Member,unsigned & Offset)451   bool LookupInlineAsmField(StringRef Base, StringRef Member,
452                             unsigned &Offset) {
453     return SemaRef.LookupInlineAsmField(Base, Member, Offset, AsmLoc);
454   }
455 
MSAsmDiagHandlerCallback(const llvm::SMDiagnostic & D,void * Context)456   static void MSAsmDiagHandlerCallback(const llvm::SMDiagnostic &D,
457                                        void *Context) {
458     ((MCAsmParserSemaCallbackImpl*)Context)->MSAsmDiagHandler(D);
459   }
MSAsmDiagHandler(const llvm::SMDiagnostic & D)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 
LookupInlineAsmIdentifier(StringRef Name,SourceLocation Loc,unsigned & Length,unsigned & Size,unsigned & Type,bool & IsVarDecl)489 NamedDecl *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 
LookupInlineAsmField(StringRef Base,StringRef Member,unsigned & Offset,SourceLocation AsmLoc)532 bool 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 
ActOnMSAsmStmt(SourceLocation AsmLoc,SourceLocation LBraceLoc,ArrayRef<Token> AsmToks,SourceLocation EndLoc)576 StmtResult 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