blob: 616dcfcd83aa780f2846e207fda004fb2dcc3daf [file] [log] [blame]
Chad Rosier3d45a772012-08-17 21:27:25 +00001//===--- SemaStmtAsm.cpp - Semantic Analysis for Asm Statements -----------===//
Chad Rosier4b5e48d2012-08-17 21:19:40 +00002//
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/Sema/Scope.h"
16#include "clang/Sema/ScopeInfo.h"
17#include "clang/Sema/Initialization.h"
18#include "clang/Sema/Lookup.h"
19#include "clang/AST/TypeLoc.h"
20#include "clang/Lex/Preprocessor.h"
21#include "clang/Basic/TargetInfo.h"
22#include "llvm/ADT/ArrayRef.h"
23#include "llvm/ADT/BitVector.h"
24#include "llvm/ADT/SmallString.h"
25#include "llvm/MC/MCAsmInfo.h"
26#include "llvm/MC/MCContext.h"
Chad Rosier4b5e48d2012-08-17 21:19:40 +000027#include "llvm/MC/MCObjectFileInfo.h"
28#include "llvm/MC/MCRegisterInfo.h"
29#include "llvm/MC/MCStreamer.h"
30#include "llvm/MC/MCSubtargetInfo.h"
31#include "llvm/MC/MCTargetAsmParser.h"
Chad Rosier4b5e48d2012-08-17 21:19:40 +000032#include "llvm/MC/MCParser/MCAsmParser.h"
33#include "llvm/Support/SourceMgr.h"
34#include "llvm/Support/TargetRegistry.h"
35#include "llvm/Support/TargetSelect.h"
36using namespace clang;
37using namespace sema;
38
39/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently
40/// ignore "noop" casts in places where an lvalue is required by an inline asm.
41/// We emulate this behavior when -fheinous-gnu-extensions is specified, but
42/// provide a strong guidance to not use it.
43///
44/// This method checks to see if the argument is an acceptable l-value and
45/// returns false if it is a case we can handle.
46static bool CheckAsmLValue(const Expr *E, Sema &S) {
47 // Type dependent expressions will be checked during instantiation.
48 if (E->isTypeDependent())
49 return false;
50
51 if (E->isLValue())
52 return false; // Cool, this is an lvalue.
53
54 // Okay, this is not an lvalue, but perhaps it is the result of a cast that we
55 // are supposed to allow.
56 const Expr *E2 = E->IgnoreParenNoopCasts(S.Context);
57 if (E != E2 && E2->isLValue()) {
58 if (!S.getLangOpts().HeinousExtensions)
59 S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue)
60 << E->getSourceRange();
61 else
62 S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
63 << E->getSourceRange();
64 // Accept, even if we emitted an error diagnostic.
65 return false;
66 }
67
68 // None of the above, just randomly invalid non-lvalue.
69 return true;
70}
71
72/// isOperandMentioned - Return true if the specified operand # is mentioned
73/// anywhere in the decomposed asm string.
74static bool isOperandMentioned(unsigned OpNo,
Chad Rosierdf5faf52012-08-25 00:11:56 +000075 ArrayRef<GCCAsmStmt::AsmStringPiece> AsmStrPieces) {
Chad Rosier4b5e48d2012-08-17 21:19:40 +000076 for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) {
Chad Rosierdf5faf52012-08-25 00:11:56 +000077 const GCCAsmStmt::AsmStringPiece &Piece = AsmStrPieces[p];
Chad Rosier4b5e48d2012-08-17 21:19:40 +000078 if (!Piece.isOperand()) continue;
79
80 // If this is a reference to the input and if the input was the smaller
81 // one, then we have to reject this asm.
82 if (Piece.getOperandNo() == OpNo)
83 return true;
84 }
85 return false;
86}
87
Chad Rosierdf5faf52012-08-25 00:11:56 +000088StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
89 bool IsVolatile, unsigned NumOutputs,
90 unsigned NumInputs, IdentifierInfo **Names,
91 MultiExprArg constraints, MultiExprArg exprs,
92 Expr *asmString, MultiExprArg clobbers,
93 SourceLocation RParenLoc) {
Chad Rosier4b5e48d2012-08-17 21:19:40 +000094 unsigned NumClobbers = clobbers.size();
95 StringLiteral **Constraints =
Benjamin Kramer5354e772012-08-23 23:38:35 +000096 reinterpret_cast<StringLiteral**>(constraints.data());
97 Expr **Exprs = exprs.data();
Chad Rosier4b5e48d2012-08-17 21:19:40 +000098 StringLiteral *AsmString = cast<StringLiteral>(asmString);
Benjamin Kramer5354e772012-08-23 23:38:35 +000099 StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.data());
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000100
101 SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;
102
103 // The parser verifies that there is a string literal here.
104 if (!AsmString->isAscii())
105 return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character)
106 << AsmString->getSourceRange());
107
108 for (unsigned i = 0; i != NumOutputs; i++) {
109 StringLiteral *Literal = Constraints[i];
110 if (!Literal->isAscii())
111 return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
112 << Literal->getSourceRange());
113
114 StringRef OutputName;
115 if (Names[i])
116 OutputName = Names[i]->getName();
117
118 TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
119 if (!Context.getTargetInfo().validateOutputConstraint(Info))
120 return StmtError(Diag(Literal->getLocStart(),
121 diag::err_asm_invalid_output_constraint)
122 << Info.getConstraintStr());
123
124 // Check that the output exprs are valid lvalues.
125 Expr *OutputExpr = Exprs[i];
126 if (CheckAsmLValue(OutputExpr, *this)) {
127 return StmtError(Diag(OutputExpr->getLocStart(),
128 diag::err_asm_invalid_lvalue_in_output)
129 << OutputExpr->getSourceRange());
130 }
131
132 OutputConstraintInfos.push_back(Info);
133 }
134
135 SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;
136
137 for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
138 StringLiteral *Literal = Constraints[i];
139 if (!Literal->isAscii())
140 return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
141 << Literal->getSourceRange());
142
143 StringRef InputName;
144 if (Names[i])
145 InputName = Names[i]->getName();
146
147 TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
148 if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(),
149 NumOutputs, Info)) {
150 return StmtError(Diag(Literal->getLocStart(),
151 diag::err_asm_invalid_input_constraint)
152 << Info.getConstraintStr());
153 }
154
155 Expr *InputExpr = Exprs[i];
156
157 // Only allow void types for memory constraints.
158 if (Info.allowsMemory() && !Info.allowsRegister()) {
159 if (CheckAsmLValue(InputExpr, *this))
160 return StmtError(Diag(InputExpr->getLocStart(),
161 diag::err_asm_invalid_lvalue_in_input)
162 << Info.getConstraintStr()
163 << InputExpr->getSourceRange());
164 }
165
166 if (Info.allowsRegister()) {
167 if (InputExpr->getType()->isVoidType()) {
168 return StmtError(Diag(InputExpr->getLocStart(),
169 diag::err_asm_invalid_type_in_input)
170 << InputExpr->getType() << Info.getConstraintStr()
171 << InputExpr->getSourceRange());
172 }
173 }
174
175 ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
176 if (Result.isInvalid())
177 return StmtError();
178
179 Exprs[i] = Result.take();
180 InputConstraintInfos.push_back(Info);
181 }
182
183 // Check that the clobbers are valid.
184 for (unsigned i = 0; i != NumClobbers; i++) {
185 StringLiteral *Literal = Clobbers[i];
186 if (!Literal->isAscii())
187 return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
188 << Literal->getSourceRange());
189
190 StringRef Clobber = Literal->getString();
191
192 if (!Context.getTargetInfo().isValidClobber(Clobber))
193 return StmtError(Diag(Literal->getLocStart(),
194 diag::err_asm_unknown_register_name) << Clobber);
195 }
196
Chad Rosierdf5faf52012-08-25 00:11:56 +0000197 GCCAsmStmt *NS =
198 new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
199 NumInputs, Names, Constraints, Exprs, AsmString,
200 NumClobbers, Clobbers, RParenLoc);
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000201 // Validate the asm string, ensuring it makes sense given the operands we
202 // have.
Chad Rosierdf5faf52012-08-25 00:11:56 +0000203 SmallVector<GCCAsmStmt::AsmStringPiece, 8> Pieces;
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000204 unsigned DiagOffs;
205 if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) {
206 Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
207 << AsmString->getSourceRange();
208 return StmtError();
209 }
210
211 // Validate tied input operands for type mismatches.
212 for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
213 TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
214
215 // If this is a tied constraint, verify that the output and input have
216 // either exactly the same type, or that they are int/ptr operands with the
217 // same size (int/long, int*/long, are ok etc).
218 if (!Info.hasTiedOperand()) continue;
219
220 unsigned TiedTo = Info.getTiedOperand();
221 unsigned InputOpNo = i+NumOutputs;
222 Expr *OutputExpr = Exprs[TiedTo];
223 Expr *InputExpr = Exprs[InputOpNo];
224
225 if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent())
226 continue;
227
228 QualType InTy = InputExpr->getType();
229 QualType OutTy = OutputExpr->getType();
230 if (Context.hasSameType(InTy, OutTy))
231 continue; // All types can be tied to themselves.
232
233 // Decide if the input and output are in the same domain (integer/ptr or
234 // floating point.
235 enum AsmDomain {
236 AD_Int, AD_FP, AD_Other
237 } InputDomain, OutputDomain;
238
239 if (InTy->isIntegerType() || InTy->isPointerType())
240 InputDomain = AD_Int;
241 else if (InTy->isRealFloatingType())
242 InputDomain = AD_FP;
243 else
244 InputDomain = AD_Other;
245
246 if (OutTy->isIntegerType() || OutTy->isPointerType())
247 OutputDomain = AD_Int;
248 else if (OutTy->isRealFloatingType())
249 OutputDomain = AD_FP;
250 else
251 OutputDomain = AD_Other;
252
253 // They are ok if they are the same size and in the same domain. This
254 // allows tying things like:
255 // void* to int*
256 // void* to int if they are the same size.
257 // double to long double if they are the same size.
258 //
259 uint64_t OutSize = Context.getTypeSize(OutTy);
260 uint64_t InSize = Context.getTypeSize(InTy);
261 if (OutSize == InSize && InputDomain == OutputDomain &&
262 InputDomain != AD_Other)
263 continue;
264
265 // If the smaller input/output operand is not mentioned in the asm string,
266 // then we can promote the smaller one to a larger input and the asm string
267 // won't notice.
268 bool SmallerValueMentioned = false;
269
270 // If this is a reference to the input and if the input was the smaller
271 // one, then we have to reject this asm.
272 if (isOperandMentioned(InputOpNo, Pieces)) {
273 // This is a use in the asm string of the smaller operand. Since we
274 // codegen this by promoting to a wider value, the asm will get printed
275 // "wrong".
276 SmallerValueMentioned |= InSize < OutSize;
277 }
278 if (isOperandMentioned(TiedTo, Pieces)) {
279 // If this is a reference to the output, and if the output is the larger
280 // value, then it's ok because we'll promote the input to the larger type.
281 SmallerValueMentioned |= OutSize < InSize;
282 }
283
284 // If the smaller value wasn't mentioned in the asm string, and if the
285 // output was a register, just extend the shorter one to the size of the
286 // larger one.
287 if (!SmallerValueMentioned && InputDomain != AD_Other &&
288 OutputConstraintInfos[TiedTo].allowsRegister())
289 continue;
290
291 // Either both of the operands were mentioned or the smaller one was
292 // mentioned. One more special case that we'll allow: if the tied input is
293 // integer, unmentioned, and is a constant, then we'll allow truncating it
294 // down to the size of the destination.
295 if (InputDomain == AD_Int && OutputDomain == AD_Int &&
296 !isOperandMentioned(InputOpNo, Pieces) &&
297 InputExpr->isEvaluatable(Context)) {
298 CastKind castKind =
299 (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast);
300 InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take();
301 Exprs[InputOpNo] = InputExpr;
302 NS->setInputExpr(i, InputExpr);
303 continue;
304 }
305
306 Diag(InputExpr->getLocStart(),
307 diag::err_asm_tying_incompatible_types)
308 << InTy << OutTy << OutputExpr->getSourceRange()
309 << InputExpr->getSourceRange();
310 return StmtError();
311 }
312
313 return Owned(NS);
314}
315
Chad Rosier358ab762012-08-22 21:08:06 +0000316// getSpelling - Get the spelling of the AsmTok token.
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000317static StringRef getSpelling(Sema &SemaRef, Token AsmTok) {
318 StringRef Asm;
319 SmallString<512> TokenBuf;
320 TokenBuf.resize(512);
321 bool StringInvalid = false;
322 Asm = SemaRef.PP.getSpelling(AsmTok, TokenBuf, &StringInvalid);
323 assert (!StringInvalid && "Expected valid string!");
324 return Asm;
325}
326
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000327// Build the inline assembly string. Returns true on error.
328static bool buildMSAsmString(Sema &SemaRef,
329 SourceLocation AsmLoc,
330 ArrayRef<Token> AsmToks,
331 std::string &AsmString) {
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000332 assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!");
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000333
334 SmallString<512> Asm;
335 for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) {
Bob Wilson40d39e32012-09-24 19:57:55 +0000336 bool isNewAsm = ((i == 0) ||
337 AsmToks[i].isAtStartOfLine() ||
338 AsmToks[i].is(tok::kw_asm));
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000339 if (isNewAsm) {
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000340 if (i != 0)
341 Asm += "\n\t";
342
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000343 if (AsmToks[i].is(tok::kw_asm)) {
344 i++; // Skip __asm
Bob Wilsonb0f6b9c2012-09-24 19:57:59 +0000345 if (i == e) {
346 SemaRef.Diag(AsmLoc, diag::err_asm_empty);
347 return true;
348 }
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000349
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000350 }
351 }
352
Chad Rosierb55e6022012-09-13 00:06:55 +0000353 if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm)
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000354 Asm += ' ';
Chad Rosier4de97162012-09-11 00:51:28 +0000355
356 StringRef Spelling = getSpelling(SemaRef, AsmToks[i]);
357 Asm += Spelling;
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000358 }
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000359 AsmString = Asm.str();
Bob Wilsonb0f6b9c2012-09-24 19:57:59 +0000360 return false;
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000361}
362
Benjamin Kramerc6f84cf2012-10-20 13:02:06 +0000363namespace {
364
Chad Rosier7fd00b12012-10-18 15:49:40 +0000365class MCAsmParserSemaCallbackImpl : public llvm::MCAsmParserSemaCallback {
366 Sema *SemaRef;
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000367
368public:
Chad Rosier7fd00b12012-10-18 15:49:40 +0000369 MCAsmParserSemaCallbackImpl(class Sema *Ref) { SemaRef = Ref; }
370 ~MCAsmParserSemaCallbackImpl() {}
371
Chad Rosierc337d142012-10-18 20:27:06 +0000372 void *LookupInlineAsmIdentifier(StringRef Name, void *SrcLoc, unsigned &Size){
Chad Rosier7fd00b12012-10-18 15:49:40 +0000373 SourceLocation Loc = SourceLocation::getFromPtrEncoding(SrcLoc);
Chad Rosierc337d142012-10-18 20:27:06 +0000374 NamedDecl *OpDecl = SemaRef->LookupInlineAsmIdentifier(Name, Loc, Size);
Chad Rosierd052ebf2012-10-18 19:39:37 +0000375 return static_cast<void *>(OpDecl);
Chad Rosier7fd00b12012-10-18 15:49:40 +0000376 }
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000377};
378
Benjamin Kramerc6f84cf2012-10-20 13:02:06 +0000379}
380
Chad Rosierc337d142012-10-18 20:27:06 +0000381NamedDecl *Sema::LookupInlineAsmIdentifier(StringRef Name, SourceLocation Loc,
382 unsigned &Size) {
383 Size = 0;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000384 LookupResult Result(*this, &Context.Idents.get(Name), Loc,
385 Sema::LookupOrdinaryName);
386
387 if (!LookupName(Result, getCurScope())) {
388 // If we don't find anything, return null; the AsmParser will assume
389 // it is a label of some sort.
390 return 0;
391 }
392
393 if (!Result.isSingleResult()) {
394 // FIXME: Diagnose result.
395 return 0;
396 }
397
398 NamedDecl *ND = Result.getFoundDecl();
399 if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) {
Chad Rosierc337d142012-10-18 20:27:06 +0000400 if (VarDecl *Var = dyn_cast<VarDecl>(ND))
401 Size = Context.getTypeInfo(Var->getType()).first;
402
Chad Rosier7fd00b12012-10-18 15:49:40 +0000403 return ND;
404 }
405
406 // FIXME: Handle other kinds of results? (FieldDecl, etc.)
407 // FIXME: Diagnose if we find something we can't handle, like a typedef.
408 return 0;
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000409}
Chad Rosier2735df22012-08-22 19:18:30 +0000410
Chad Rosierb55e6022012-09-13 00:06:55 +0000411StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
412 ArrayRef<Token> AsmToks,SourceLocation EndLoc) {
Chad Rosiere54cba12012-10-16 21:55:39 +0000413 SmallVector<IdentifierInfo*, 4> Names;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000414 SmallVector<StringRef, 4> ConstraintRefs;
Chad Rosiere54cba12012-10-16 21:55:39 +0000415 SmallVector<Expr*, 4> Exprs;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000416 SmallVector<StringRef, 4> ClobberRefs;
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000417
418 // Empty asm statements don't need to instantiate the AsmParser, etc.
Chad Rosier7fd00b12012-10-18 15:49:40 +0000419 if (AsmToks.empty()) {
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000420 StringRef EmptyAsmStr;
421 MSAsmStmt *NS =
422 new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true,
Chad Rosiere54cba12012-10-16 21:55:39 +0000423 /*IsVolatile*/ true, AsmToks, /*NumOutputs*/ 0,
Chad Rosier7fd00b12012-10-18 15:49:40 +0000424 /*NumInputs*/ 0, Names, ConstraintRefs, Exprs,
425 EmptyAsmStr, ClobberRefs, EndLoc);
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000426 return Owned(NS);
427 }
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000428
Chad Rosier7fd00b12012-10-18 15:49:40 +0000429 std::string AsmString;
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000430 if (buildMSAsmString(*this, AsmLoc, AsmToks, AsmString))
Bob Wilsonb0f6b9c2012-09-24 19:57:59 +0000431 return StmtError();
Chad Rosier38c71d32012-08-21 21:56:39 +0000432
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000433 // Get the target specific parser.
434 std::string Error;
435 const std::string &TT = Context.getTargetInfo().getTriple().getTriple();
436 const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error));
437
438 OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT));
439 OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
440 OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
441 OwningPtr<llvm::MCSubtargetInfo>
442 STI(TheTarget->createMCSubtargetInfo(TT, "", ""));
443
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000444 llvm::SourceMgr SrcMgr;
445 llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr);
446 llvm::MemoryBuffer *Buffer =
447 llvm::MemoryBuffer::getMemBuffer(AsmString, "<inline asm>");
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000448
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000449 // Tell SrcMgr about this buffer, which is what the parser will pick up.
450 SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc());
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000451
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000452 OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
453 OwningPtr<llvm::MCAsmParser>
454 Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));
455 OwningPtr<llvm::MCTargetAsmParser>
456 TargetParser(TheTarget->createMCAsmParser(*STI, *Parser));
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000457
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000458 // Get the instruction descriptor.
459 const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo();
460 llvm::MCInstPrinter *IP =
461 TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI);
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000462
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000463 // Change to the Intel dialect.
464 Parser->setAssemblerDialect(1);
465 Parser->setTargetParser(*TargetParser.get());
466 Parser->setParsingInlineAsm(true);
Chad Rosiercf81cd22012-10-19 17:58:45 +0000467 TargetParser->setParsingInlineAsm(true);
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000468
Chad Rosier793c4052012-10-19 20:36:37 +0000469 MCAsmParserSemaCallbackImpl MCAPSI(this);
470 TargetParser->setSemaCallback(&MCAPSI);
471
Chad Rosier7fd00b12012-10-18 15:49:40 +0000472 unsigned NumOutputs;
473 unsigned NumInputs;
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000474 std::string AsmStringIR;
Chad Rosierd052ebf2012-10-18 19:39:37 +0000475 SmallVector<void *, 4> OpDecls;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000476 SmallVector<std::string, 4> Constraints;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000477 SmallVector<std::string, 4> Clobbers;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000478 if (Parser->ParseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR,
Chad Rosierd052ebf2012-10-18 19:39:37 +0000479 NumOutputs, NumInputs, OpDecls, Constraints,
480 Clobbers, MII, IP, MCAPSI))
Chad Rosier7fd00b12012-10-18 15:49:40 +0000481 return StmtError();
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000482
Chad Rosier7fd00b12012-10-18 15:49:40 +0000483 // Build the vector of clobber StringRefs.
484 unsigned NumClobbers = Clobbers.size();
485 ClobberRefs.resize(NumClobbers);
486 for (unsigned i = 0; i != NumClobbers; ++i)
487 ClobberRefs[i] = StringRef(Clobbers[i]);
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000488
Chad Rosier7fd00b12012-10-18 15:49:40 +0000489 // Recast the void pointers and build the vector of constraint StringRefs.
490 unsigned NumExprs = NumOutputs + NumInputs;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000491 Names.resize(NumExprs);
492 ConstraintRefs.resize(NumExprs);
493 Exprs.resize(NumExprs);
494 for (unsigned i = 0, e = NumExprs; i != e; ++i) {
Chad Rosierd052ebf2012-10-18 19:39:37 +0000495 NamedDecl *OpDecl = static_cast<NamedDecl *>(OpDecls[i]);
496 if (!OpDecl)
497 return StmtError();
498
499 DeclarationNameInfo NameInfo(OpDecl->getDeclName(), AsmLoc);
500 ExprResult OpExpr = BuildDeclarationNameExpr(CXXScopeSpec(), NameInfo,
501 OpDecl);
502 if (OpExpr.isInvalid())
503 return StmtError();
504
505 Names[i] = OpDecl->getIdentifier();
Chad Rosier7fd00b12012-10-18 15:49:40 +0000506 ConstraintRefs[i] = StringRef(Constraints[i]);
Chad Rosierd052ebf2012-10-18 19:39:37 +0000507 Exprs[i] = OpExpr.take();
Chad Rosieracc22b62012-09-06 19:35:00 +0000508 }
Chad Rosierb55e6022012-09-13 00:06:55 +0000509
Chad Rosier7fd00b12012-10-18 15:49:40 +0000510 bool IsSimple = NumExprs > 0;
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000511 MSAsmStmt *NS =
Chad Rosier7fd00b12012-10-18 15:49:40 +0000512 new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
513 /*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs,
514 Names, ConstraintRefs, Exprs, AsmStringIR,
515 ClobberRefs, EndLoc);
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000516 return Owned(NS);
517}