blob: 172cfe55beae77c7be1d097de0b3938962ca2d91 [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
Chad Rosier7fd00b12012-10-18 15:49:40 +0000363class MCAsmParserSemaCallbackImpl : public llvm::MCAsmParserSemaCallback {
364 Sema *SemaRef;
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000365
366public:
Chad Rosier7fd00b12012-10-18 15:49:40 +0000367 MCAsmParserSemaCallbackImpl(class Sema *Ref) { SemaRef = Ref; }
368 ~MCAsmParserSemaCallbackImpl() {}
369
Chad Rosierc337d142012-10-18 20:27:06 +0000370 void *LookupInlineAsmIdentifier(StringRef Name, void *SrcLoc, unsigned &Size){
Chad Rosier7fd00b12012-10-18 15:49:40 +0000371 SourceLocation Loc = SourceLocation::getFromPtrEncoding(SrcLoc);
Chad Rosierc337d142012-10-18 20:27:06 +0000372 NamedDecl *OpDecl = SemaRef->LookupInlineAsmIdentifier(Name, Loc, Size);
Chad Rosierd052ebf2012-10-18 19:39:37 +0000373 return static_cast<void *>(OpDecl);
Chad Rosier7fd00b12012-10-18 15:49:40 +0000374 }
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000375};
376
Chad Rosierc337d142012-10-18 20:27:06 +0000377NamedDecl *Sema::LookupInlineAsmIdentifier(StringRef Name, SourceLocation Loc,
378 unsigned &Size) {
379 Size = 0;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000380 LookupResult Result(*this, &Context.Idents.get(Name), Loc,
381 Sema::LookupOrdinaryName);
382
383 if (!LookupName(Result, getCurScope())) {
384 // If we don't find anything, return null; the AsmParser will assume
385 // it is a label of some sort.
386 return 0;
387 }
388
389 if (!Result.isSingleResult()) {
390 // FIXME: Diagnose result.
391 return 0;
392 }
393
394 NamedDecl *ND = Result.getFoundDecl();
395 if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) {
Chad Rosierc337d142012-10-18 20:27:06 +0000396 if (VarDecl *Var = dyn_cast<VarDecl>(ND))
397 Size = Context.getTypeInfo(Var->getType()).first;
398
Chad Rosier7fd00b12012-10-18 15:49:40 +0000399 return ND;
400 }
401
402 // FIXME: Handle other kinds of results? (FieldDecl, etc.)
403 // FIXME: Diagnose if we find something we can't handle, like a typedef.
404 return 0;
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000405}
Chad Rosier2735df22012-08-22 19:18:30 +0000406
Chad Rosierb55e6022012-09-13 00:06:55 +0000407StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
408 ArrayRef<Token> AsmToks,SourceLocation EndLoc) {
Chad Rosiere54cba12012-10-16 21:55:39 +0000409 SmallVector<IdentifierInfo*, 4> Names;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000410 SmallVector<StringRef, 4> ConstraintRefs;
Chad Rosiere54cba12012-10-16 21:55:39 +0000411 SmallVector<Expr*, 4> Exprs;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000412 SmallVector<StringRef, 4> ClobberRefs;
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000413
414 // Empty asm statements don't need to instantiate the AsmParser, etc.
Chad Rosier7fd00b12012-10-18 15:49:40 +0000415 if (AsmToks.empty()) {
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000416 StringRef EmptyAsmStr;
417 MSAsmStmt *NS =
418 new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true,
Chad Rosiere54cba12012-10-16 21:55:39 +0000419 /*IsVolatile*/ true, AsmToks, /*NumOutputs*/ 0,
Chad Rosier7fd00b12012-10-18 15:49:40 +0000420 /*NumInputs*/ 0, Names, ConstraintRefs, Exprs,
421 EmptyAsmStr, ClobberRefs, EndLoc);
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000422 return Owned(NS);
423 }
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000424
Chad Rosier7fd00b12012-10-18 15:49:40 +0000425 std::string AsmString;
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000426 if (buildMSAsmString(*this, AsmLoc, AsmToks, AsmString))
Bob Wilsonb0f6b9c2012-09-24 19:57:59 +0000427 return StmtError();
Chad Rosier38c71d32012-08-21 21:56:39 +0000428
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000429 // Get the target specific parser.
430 std::string Error;
431 const std::string &TT = Context.getTargetInfo().getTriple().getTriple();
432 const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error));
433
434 OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT));
435 OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
436 OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
437 OwningPtr<llvm::MCSubtargetInfo>
438 STI(TheTarget->createMCSubtargetInfo(TT, "", ""));
439
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000440 llvm::SourceMgr SrcMgr;
441 llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr);
442 llvm::MemoryBuffer *Buffer =
443 llvm::MemoryBuffer::getMemBuffer(AsmString, "<inline asm>");
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000444
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000445 // Tell SrcMgr about this buffer, which is what the parser will pick up.
446 SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc());
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000447
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000448 OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
449 OwningPtr<llvm::MCAsmParser>
450 Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));
451 OwningPtr<llvm::MCTargetAsmParser>
452 TargetParser(TheTarget->createMCAsmParser(*STI, *Parser));
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000453
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000454 // Get the instruction descriptor.
455 const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo();
456 llvm::MCInstPrinter *IP =
457 TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI);
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000458
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000459 // Change to the Intel dialect.
460 Parser->setAssemblerDialect(1);
461 Parser->setTargetParser(*TargetParser.get());
462 Parser->setParsingInlineAsm(true);
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000463
Chad Rosier7fd00b12012-10-18 15:49:40 +0000464 unsigned NumOutputs;
465 unsigned NumInputs;
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000466 std::string AsmStringIR;
Chad Rosierd052ebf2012-10-18 19:39:37 +0000467 SmallVector<void *, 4> OpDecls;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000468 SmallVector<std::string, 4> Constraints;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000469 SmallVector<std::string, 4> Clobbers;
470 MCAsmParserSemaCallbackImpl MCAPSI(this);
471 if (Parser->ParseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR,
Chad Rosierd052ebf2012-10-18 19:39:37 +0000472 NumOutputs, NumInputs, OpDecls, Constraints,
473 Clobbers, MII, IP, MCAPSI))
Chad Rosier7fd00b12012-10-18 15:49:40 +0000474 return StmtError();
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000475
Chad Rosier7fd00b12012-10-18 15:49:40 +0000476 // Build the vector of clobber StringRefs.
477 unsigned NumClobbers = Clobbers.size();
478 ClobberRefs.resize(NumClobbers);
479 for (unsigned i = 0; i != NumClobbers; ++i)
480 ClobberRefs[i] = StringRef(Clobbers[i]);
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000481
Chad Rosier7fd00b12012-10-18 15:49:40 +0000482 // Recast the void pointers and build the vector of constraint StringRefs.
483 unsigned NumExprs = NumOutputs + NumInputs;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000484 Names.resize(NumExprs);
485 ConstraintRefs.resize(NumExprs);
486 Exprs.resize(NumExprs);
487 for (unsigned i = 0, e = NumExprs; i != e; ++i) {
Chad Rosierd052ebf2012-10-18 19:39:37 +0000488 NamedDecl *OpDecl = static_cast<NamedDecl *>(OpDecls[i]);
489 if (!OpDecl)
490 return StmtError();
491
492 DeclarationNameInfo NameInfo(OpDecl->getDeclName(), AsmLoc);
493 ExprResult OpExpr = BuildDeclarationNameExpr(CXXScopeSpec(), NameInfo,
494 OpDecl);
495 if (OpExpr.isInvalid())
496 return StmtError();
497
498 Names[i] = OpDecl->getIdentifier();
Chad Rosier7fd00b12012-10-18 15:49:40 +0000499 ConstraintRefs[i] = StringRef(Constraints[i]);
Chad Rosierd052ebf2012-10-18 19:39:37 +0000500 Exprs[i] = OpExpr.take();
Chad Rosieracc22b62012-09-06 19:35:00 +0000501 }
Chad Rosierb55e6022012-09-13 00:06:55 +0000502
Chad Rosier7fd00b12012-10-18 15:49:40 +0000503 bool IsSimple = NumExprs > 0;
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000504 MSAsmStmt *NS =
Chad Rosier7fd00b12012-10-18 15:49:40 +0000505 new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
506 /*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs,
507 Names, ConstraintRefs, Exprs, AsmStringIR,
508 ClobberRefs, EndLoc);
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000509 return Owned(NS);
510}