blob: f33b87cebcc47ade6851b98d888c3da0a070929a [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,
Eli Friedman5f1385b2012-10-23 02:43:30 +0000331 llvm::SmallVectorImpl<unsigned> &TokOffsets,
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000332 std::string &AsmString) {
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000333 assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!");
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000334
335 SmallString<512> Asm;
336 for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) {
Bob Wilson40d39e32012-09-24 19:57:55 +0000337 bool isNewAsm = ((i == 0) ||
338 AsmToks[i].isAtStartOfLine() ||
339 AsmToks[i].is(tok::kw_asm));
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000340 if (isNewAsm) {
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000341 if (i != 0)
342 Asm += "\n\t";
343
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000344 if (AsmToks[i].is(tok::kw_asm)) {
345 i++; // Skip __asm
Bob Wilsonb0f6b9c2012-09-24 19:57:59 +0000346 if (i == e) {
347 SemaRef.Diag(AsmLoc, diag::err_asm_empty);
348 return true;
349 }
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000350
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000351 }
352 }
353
Chad Rosierb55e6022012-09-13 00:06:55 +0000354 if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm)
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000355 Asm += ' ';
Chad Rosier4de97162012-09-11 00:51:28 +0000356
357 StringRef Spelling = getSpelling(SemaRef, AsmToks[i]);
358 Asm += Spelling;
Eli Friedman5f1385b2012-10-23 02:43:30 +0000359 TokOffsets.push_back(Asm.size());
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000360 }
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000361 AsmString = Asm.str();
Bob Wilsonb0f6b9c2012-09-24 19:57:59 +0000362 return false;
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000363}
364
Benjamin Kramerc6f84cf2012-10-20 13:02:06 +0000365namespace {
366
Chad Rosier7fd00b12012-10-18 15:49:40 +0000367class MCAsmParserSemaCallbackImpl : public llvm::MCAsmParserSemaCallback {
Eli Friedman5f1385b2012-10-23 02:43:30 +0000368 Sema &SemaRef;
369 SourceLocation AsmLoc;
370 ArrayRef<Token> AsmToks;
371 ArrayRef<unsigned> TokOffsets;
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000372
373public:
Eli Friedman5f1385b2012-10-23 02:43:30 +0000374 MCAsmParserSemaCallbackImpl(Sema &Ref, SourceLocation Loc,
375 ArrayRef<Token> Toks,
376 ArrayRef<unsigned> Offsets)
377 : SemaRef(Ref), AsmLoc(Loc), AsmToks(Toks), TokOffsets(Offsets) { }
Chad Rosier7fd00b12012-10-18 15:49:40 +0000378 ~MCAsmParserSemaCallbackImpl() {}
379
Chad Rosierc337d142012-10-18 20:27:06 +0000380 void *LookupInlineAsmIdentifier(StringRef Name, void *SrcLoc, unsigned &Size){
Chad Rosier7fd00b12012-10-18 15:49:40 +0000381 SourceLocation Loc = SourceLocation::getFromPtrEncoding(SrcLoc);
Eli Friedman5f1385b2012-10-23 02:43:30 +0000382 NamedDecl *OpDecl = SemaRef.LookupInlineAsmIdentifier(Name, Loc, Size);
Chad Rosierd052ebf2012-10-18 19:39:37 +0000383 return static_cast<void *>(OpDecl);
Chad Rosier7fd00b12012-10-18 15:49:40 +0000384 }
Eli Friedman5f1385b2012-10-23 02:43:30 +0000385
386 static void MSAsmDiagHandlerCallback(const llvm::SMDiagnostic &D,
387 void *Context) {
388 ((MCAsmParserSemaCallbackImpl*)Context)->MSAsmDiagHandler(D);
389 }
390 void MSAsmDiagHandler(const llvm::SMDiagnostic &D) {
391 // Compute an offset into the inline asm buffer.
392 // FIXME: This isn't right if .macro is involved (but hopefully, no
393 // real-world code does that).
394 const llvm::SourceMgr &LSM = *D.getSourceMgr();
395 const llvm::MemoryBuffer *LBuf =
396 LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
397 unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart();
398
399 // Figure out which token that offset points into.
400 const unsigned *OffsetPtr =
401 std::lower_bound(TokOffsets.begin(), TokOffsets.end(), Offset);
402 unsigned TokIndex = OffsetPtr - TokOffsets.begin();
403
404 // If we come up with an answer which seems sane, use it; otherwise,
405 // just point at the __asm keyword.
406 // FIXME: Assert the answer is sane once we handle .macro correctly.
407 SourceLocation Loc = AsmLoc;
408 if (TokIndex < AsmToks.size()) {
409 const Token *Tok = &AsmToks[TokIndex];
410 Loc = Tok->getLocation();
411 Loc = Loc.getLocWithOffset(Offset - (*OffsetPtr - Tok->getLength()));
412 }
413 SemaRef.Diag(Loc, diag::err_inline_ms_asm_parsing) << D.getMessage();
414 }
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000415};
416
Benjamin Kramerc6f84cf2012-10-20 13:02:06 +0000417}
418
Chad Rosierc337d142012-10-18 20:27:06 +0000419NamedDecl *Sema::LookupInlineAsmIdentifier(StringRef Name, SourceLocation Loc,
420 unsigned &Size) {
421 Size = 0;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000422 LookupResult Result(*this, &Context.Idents.get(Name), Loc,
423 Sema::LookupOrdinaryName);
424
425 if (!LookupName(Result, getCurScope())) {
426 // If we don't find anything, return null; the AsmParser will assume
427 // it is a label of some sort.
428 return 0;
429 }
430
431 if (!Result.isSingleResult()) {
432 // FIXME: Diagnose result.
433 return 0;
434 }
435
436 NamedDecl *ND = Result.getFoundDecl();
437 if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) {
Chad Rosierc337d142012-10-18 20:27:06 +0000438 if (VarDecl *Var = dyn_cast<VarDecl>(ND))
439 Size = Context.getTypeInfo(Var->getType()).first;
440
Chad Rosier7fd00b12012-10-18 15:49:40 +0000441 return ND;
442 }
443
444 // FIXME: Handle other kinds of results? (FieldDecl, etc.)
445 // FIXME: Diagnose if we find something we can't handle, like a typedef.
446 return 0;
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000447}
Chad Rosier2735df22012-08-22 19:18:30 +0000448
Chad Rosierb55e6022012-09-13 00:06:55 +0000449StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
450 ArrayRef<Token> AsmToks,SourceLocation EndLoc) {
Chad Rosiere54cba12012-10-16 21:55:39 +0000451 SmallVector<IdentifierInfo*, 4> Names;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000452 SmallVector<StringRef, 4> ConstraintRefs;
Chad Rosiere54cba12012-10-16 21:55:39 +0000453 SmallVector<Expr*, 4> Exprs;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000454 SmallVector<StringRef, 4> ClobberRefs;
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000455
456 // Empty asm statements don't need to instantiate the AsmParser, etc.
Chad Rosier7fd00b12012-10-18 15:49:40 +0000457 if (AsmToks.empty()) {
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000458 StringRef EmptyAsmStr;
459 MSAsmStmt *NS =
460 new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true,
Chad Rosiere54cba12012-10-16 21:55:39 +0000461 /*IsVolatile*/ true, AsmToks, /*NumOutputs*/ 0,
Chad Rosier7fd00b12012-10-18 15:49:40 +0000462 /*NumInputs*/ 0, Names, ConstraintRefs, Exprs,
463 EmptyAsmStr, ClobberRefs, EndLoc);
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000464 return Owned(NS);
465 }
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000466
Chad Rosier7fd00b12012-10-18 15:49:40 +0000467 std::string AsmString;
Eli Friedman5f1385b2012-10-23 02:43:30 +0000468 llvm::SmallVector<unsigned, 8> TokOffsets;
469 if (buildMSAsmString(*this, AsmLoc, AsmToks, TokOffsets, AsmString))
Bob Wilsonb0f6b9c2012-09-24 19:57:59 +0000470 return StmtError();
Chad Rosier38c71d32012-08-21 21:56:39 +0000471
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000472 // Get the target specific parser.
473 std::string Error;
474 const std::string &TT = Context.getTargetInfo().getTriple().getTriple();
475 const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error));
476
477 OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT));
478 OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
479 OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
480 OwningPtr<llvm::MCSubtargetInfo>
481 STI(TheTarget->createMCSubtargetInfo(TT, "", ""));
482
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000483 llvm::SourceMgr SrcMgr;
484 llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr);
485 llvm::MemoryBuffer *Buffer =
486 llvm::MemoryBuffer::getMemBuffer(AsmString, "<inline asm>");
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000487
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000488 // Tell SrcMgr about this buffer, which is what the parser will pick up.
489 SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc());
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000490
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000491 OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
492 OwningPtr<llvm::MCAsmParser>
493 Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI));
494 OwningPtr<llvm::MCTargetAsmParser>
495 TargetParser(TheTarget->createMCAsmParser(*STI, *Parser));
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000496
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000497 // Get the instruction descriptor.
498 const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo();
499 llvm::MCInstPrinter *IP =
500 TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI);
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000501
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000502 // Change to the Intel dialect.
503 Parser->setAssemblerDialect(1);
504 Parser->setTargetParser(*TargetParser.get());
505 Parser->setParsingInlineAsm(true);
Chad Rosiercf81cd22012-10-19 17:58:45 +0000506 TargetParser->setParsingInlineAsm(true);
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000507
Eli Friedman5f1385b2012-10-23 02:43:30 +0000508 MCAsmParserSemaCallbackImpl MCAPSI(*this, AsmLoc, AsmToks, TokOffsets);
Chad Rosier793c4052012-10-19 20:36:37 +0000509 TargetParser->setSemaCallback(&MCAPSI);
Eli Friedman5f1385b2012-10-23 02:43:30 +0000510 SrcMgr.setDiagHandler(MCAsmParserSemaCallbackImpl::MSAsmDiagHandlerCallback,
511 &MCAPSI);
Chad Rosier793c4052012-10-19 20:36:37 +0000512
Chad Rosier7fd00b12012-10-18 15:49:40 +0000513 unsigned NumOutputs;
514 unsigned NumInputs;
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000515 std::string AsmStringIR;
Chad Rosierd052ebf2012-10-18 19:39:37 +0000516 SmallVector<void *, 4> OpDecls;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000517 SmallVector<std::string, 4> Constraints;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000518 SmallVector<std::string, 4> Clobbers;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000519 if (Parser->ParseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR,
Chad Rosierd052ebf2012-10-18 19:39:37 +0000520 NumOutputs, NumInputs, OpDecls, Constraints,
521 Clobbers, MII, IP, MCAPSI))
Chad Rosier7fd00b12012-10-18 15:49:40 +0000522 return StmtError();
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000523
Chad Rosier7fd00b12012-10-18 15:49:40 +0000524 // Build the vector of clobber StringRefs.
525 unsigned NumClobbers = Clobbers.size();
526 ClobberRefs.resize(NumClobbers);
527 for (unsigned i = 0; i != NumClobbers; ++i)
528 ClobberRefs[i] = StringRef(Clobbers[i]);
Chad Rosierd9b56ed2012-10-15 19:56:10 +0000529
Chad Rosier7fd00b12012-10-18 15:49:40 +0000530 // Recast the void pointers and build the vector of constraint StringRefs.
531 unsigned NumExprs = NumOutputs + NumInputs;
Chad Rosier7fd00b12012-10-18 15:49:40 +0000532 Names.resize(NumExprs);
533 ConstraintRefs.resize(NumExprs);
534 Exprs.resize(NumExprs);
535 for (unsigned i = 0, e = NumExprs; i != e; ++i) {
Chad Rosierd052ebf2012-10-18 19:39:37 +0000536 NamedDecl *OpDecl = static_cast<NamedDecl *>(OpDecls[i]);
537 if (!OpDecl)
538 return StmtError();
539
540 DeclarationNameInfo NameInfo(OpDecl->getDeclName(), AsmLoc);
541 ExprResult OpExpr = BuildDeclarationNameExpr(CXXScopeSpec(), NameInfo,
542 OpDecl);
543 if (OpExpr.isInvalid())
544 return StmtError();
545
546 Names[i] = OpDecl->getIdentifier();
Chad Rosier7fd00b12012-10-18 15:49:40 +0000547 ConstraintRefs[i] = StringRef(Constraints[i]);
Chad Rosierd052ebf2012-10-18 19:39:37 +0000548 Exprs[i] = OpExpr.take();
Chad Rosieracc22b62012-09-06 19:35:00 +0000549 }
Chad Rosierb55e6022012-09-13 00:06:55 +0000550
Chad Rosier7fd00b12012-10-18 15:49:40 +0000551 bool IsSimple = NumExprs > 0;
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000552 MSAsmStmt *NS =
Chad Rosier7fd00b12012-10-18 15:49:40 +0000553 new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
554 /*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs,
555 Names, ConstraintRefs, Exprs, AsmStringIR,
556 ClobberRefs, EndLoc);
Chad Rosier4b5e48d2012-08-17 21:19:40 +0000557 return Owned(NS);
558}