1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #include "clang/Parse/Parser.h" |
14 | #include "clang/AST/ASTContext.h" |
15 | #include "clang/Basic/Diagnostic.h" |
16 | #include "clang/Basic/TargetInfo.h" |
17 | #include "clang/Parse/RAIIObjectsForParser.h" |
18 | #include "llvm/ADT/SmallString.h" |
19 | #include "llvm/ADT/StringExtras.h" |
20 | #include "llvm/MC/MCAsmInfo.h" |
21 | #include "llvm/MC/MCContext.h" |
22 | #include "llvm/MC/MCInstPrinter.h" |
23 | #include "llvm/MC/MCInstrInfo.h" |
24 | #include "llvm/MC/MCObjectFileInfo.h" |
25 | #include "llvm/MC/MCParser/MCAsmParser.h" |
26 | #include "llvm/MC/MCParser/MCTargetAsmParser.h" |
27 | #include "llvm/MC/MCRegisterInfo.h" |
28 | #include "llvm/MC/MCStreamer.h" |
29 | #include "llvm/MC/MCSubtargetInfo.h" |
30 | #include "llvm/MC/MCTargetOptions.h" |
31 | #include "llvm/Support/SourceMgr.h" |
32 | #include "llvm/Support/TargetRegistry.h" |
33 | #include "llvm/Support/TargetSelect.h" |
34 | using namespace clang; |
35 | |
36 | namespace { |
37 | class ClangAsmParserCallback : public llvm::MCAsmParserSemaCallback { |
38 | Parser &TheParser; |
39 | SourceLocation AsmLoc; |
40 | StringRef AsmString; |
41 | |
42 | |
43 | ArrayRef<Token> AsmToks; |
44 | |
45 | |
46 | ArrayRef<unsigned> AsmTokOffsets; |
47 | |
48 | public: |
49 | ClangAsmParserCallback(Parser &P, SourceLocation Loc, StringRef AsmString, |
50 | ArrayRef<Token> Toks, ArrayRef<unsigned> Offsets) |
51 | : TheParser(P), AsmLoc(Loc), AsmString(AsmString), AsmToks(Toks), |
52 | AsmTokOffsets(Offsets) { |
53 | assert(AsmToks.size() == AsmTokOffsets.size()); |
54 | } |
55 | |
56 | void LookupInlineAsmIdentifier(StringRef &LineBuf, |
57 | llvm::InlineAsmIdentifierInfo &Info, |
58 | bool IsUnevaluatedContext) override; |
59 | |
60 | StringRef LookupInlineAsmLabel(StringRef Identifier, llvm::SourceMgr &LSM, |
61 | llvm::SMLoc Location, |
62 | bool Create) override; |
63 | |
64 | bool LookupInlineAsmField(StringRef Base, StringRef Member, |
65 | unsigned &Offset) override { |
66 | return TheParser.getActions().LookupInlineAsmField(Base, Member, Offset, |
67 | AsmLoc); |
68 | } |
69 | |
70 | static void DiagHandlerCallback(const llvm::SMDiagnostic &D, void *Context) { |
71 | ((ClangAsmParserCallback *)Context)->handleDiagnostic(D); |
72 | } |
73 | |
74 | private: |
75 | |
76 | void findTokensForString(StringRef Str, SmallVectorImpl<Token> &TempToks, |
77 | const Token *&FirstOrigToken) const; |
78 | |
79 | SourceLocation translateLocation(const llvm::SourceMgr &LSM, |
80 | llvm::SMLoc SMLoc); |
81 | |
82 | void handleDiagnostic(const llvm::SMDiagnostic &D); |
83 | }; |
84 | } |
85 | |
86 | void ClangAsmParserCallback::LookupInlineAsmIdentifier( |
87 | StringRef &LineBuf, llvm::InlineAsmIdentifierInfo &Info, |
88 | bool IsUnevaluatedContext) { |
89 | |
90 | SmallVector<Token, 16> LineToks; |
91 | const Token *FirstOrigToken = nullptr; |
92 | findTokensForString(LineBuf, LineToks, FirstOrigToken); |
93 | |
94 | unsigned NumConsumedToks; |
95 | ExprResult Result = TheParser.ParseMSAsmIdentifier(LineToks, NumConsumedToks, |
96 | IsUnevaluatedContext); |
97 | |
98 | |
99 | |
100 | if (NumConsumedToks == 0 || NumConsumedToks == LineToks.size()) { |
101 | |
102 | |
103 | |
104 | } else { |
105 | (0) . __assert_fail ("FirstOrigToken && \"not using original tokens?\"", "/home/seafit/code_projects/clang_source/clang/lib/Parse/ParseStmtAsm.cpp", 105, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(FirstOrigToken && "not using original tokens?"); |
106 | |
107 | |
108 | assert(FirstOrigToken[NumConsumedToks].getLocation() == |
109 | LineToks[NumConsumedToks].getLocation()); |
110 | unsigned FirstIndex = FirstOrigToken - AsmToks.begin(); |
111 | unsigned LastIndex = FirstIndex + NumConsumedToks - 1; |
112 | |
113 | |
114 | |
115 | unsigned TotalOffset = |
116 | (AsmTokOffsets[LastIndex] + AsmToks[LastIndex].getLength() - |
117 | AsmTokOffsets[FirstIndex]); |
118 | LineBuf = LineBuf.substr(0, TotalOffset); |
119 | } |
120 | |
121 | |
122 | if (!Result.isUsable()) |
123 | return; |
124 | TheParser.getActions().FillInlineAsmIdentifierInfo(Result.get(), Info); |
125 | } |
126 | |
127 | StringRef ClangAsmParserCallback::LookupInlineAsmLabel(StringRef Identifier, |
128 | llvm::SourceMgr &LSM, |
129 | llvm::SMLoc Location, |
130 | bool Create) { |
131 | SourceLocation Loc = translateLocation(LSM, Location); |
132 | LabelDecl *Label = |
133 | TheParser.getActions().GetOrCreateMSAsmLabel(Identifier, Loc, Create); |
134 | return Label->getMSAsmLabel(); |
135 | } |
136 | |
137 | void ClangAsmParserCallback::findTokensForString( |
138 | StringRef Str, SmallVectorImpl<Token> &TempToks, |
139 | const Token *&FirstOrigToken) const { |
140 | |
141 | |
142 | ()(Str.begin(), AsmString.begin()) && !std..less()(AsmString.end(), Str.end())", "/home/seafit/code_projects/clang_source/clang/lib/Parse/ParseStmtAsm.cpp", 143, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!std::less<const char *>()(Str.begin(), AsmString.begin()) && |
143 | ()(Str.begin(), AsmString.begin()) && !std..less()(AsmString.end(), Str.end())", "/home/seafit/code_projects/clang_source/clang/lib/Parse/ParseStmtAsm.cpp", 143, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> !std::less<const char *>()(AsmString.end(), Str.end())); |
144 | |
145 | |
146 | unsigned FirstCharOffset = Str.begin() - AsmString.begin(); |
147 | const unsigned *FirstTokOffset = std::lower_bound( |
148 | AsmTokOffsets.begin(), AsmTokOffsets.end(), FirstCharOffset); |
149 | |
150 | |
151 | |
152 | assert(*FirstTokOffset == FirstCharOffset); |
153 | |
154 | |
155 | |
156 | unsigned FirstTokIndex = FirstTokOffset - AsmTokOffsets.begin(); |
157 | FirstOrigToken = &AsmToks[FirstTokIndex]; |
158 | unsigned LastCharOffset = Str.end() - AsmString.begin(); |
159 | for (unsigned i = FirstTokIndex, e = AsmTokOffsets.size(); i != e; ++i) { |
160 | if (AsmTokOffsets[i] >= LastCharOffset) |
161 | break; |
162 | TempToks.push_back(AsmToks[i]); |
163 | } |
164 | } |
165 | |
166 | SourceLocation |
167 | ClangAsmParserCallback::translateLocation(const llvm::SourceMgr &LSM, |
168 | llvm::SMLoc SMLoc) { |
169 | |
170 | |
171 | |
172 | const llvm::MemoryBuffer *LBuf = |
173 | LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(SMLoc)); |
174 | unsigned Offset = SMLoc.getPointer() - LBuf->getBufferStart(); |
175 | |
176 | |
177 | const unsigned *TokOffsetPtr = |
178 | std::lower_bound(AsmTokOffsets.begin(), AsmTokOffsets.end(), Offset); |
179 | unsigned TokIndex = TokOffsetPtr - AsmTokOffsets.begin(); |
180 | unsigned TokOffset = *TokOffsetPtr; |
181 | |
182 | |
183 | |
184 | |
185 | SourceLocation Loc = AsmLoc; |
186 | if (TokIndex < AsmToks.size()) { |
187 | const Token &Tok = AsmToks[TokIndex]; |
188 | Loc = Tok.getLocation(); |
189 | Loc = Loc.getLocWithOffset(Offset - TokOffset); |
190 | } |
191 | return Loc; |
192 | } |
193 | |
194 | void ClangAsmParserCallback::handleDiagnostic(const llvm::SMDiagnostic &D) { |
195 | const llvm::SourceMgr &LSM = *D.getSourceMgr(); |
196 | SourceLocation Loc = translateLocation(LSM, D.getLoc()); |
197 | TheParser.Diag(Loc, diag::err_inline_ms_asm_parsing) << D.getMessage(); |
198 | } |
199 | |
200 | |
201 | ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks, |
202 | unsigned &NumLineToksConsumed, |
203 | bool IsUnevaluatedContext) { |
204 | |
205 | |
206 | |
207 | const tok::TokenKind EndOfStream = tok::semi; |
208 | Token EndOfStreamTok; |
209 | EndOfStreamTok.startToken(); |
210 | EndOfStreamTok.setKind(EndOfStream); |
211 | LineToks.push_back(EndOfStreamTok); |
212 | |
213 | |
214 | LineToks.push_back(Tok); |
215 | |
216 | PP.EnterTokenStream(LineToks, true); |
217 | |
218 | |
219 | ConsumeAnyToken(); |
220 | |
221 | |
222 | CXXScopeSpec SS; |
223 | if (getLangOpts().CPlusPlus) { |
224 | ParseOptionalCXXScopeSpecifier(SS, nullptr, ); |
225 | } |
226 | |
227 | |
228 | SourceLocation TemplateKWLoc; |
229 | UnqualifiedId Id; |
230 | bool Invalid = true; |
231 | ExprResult Result; |
232 | if (Tok.is(tok::kw_this)) { |
233 | Result = ParseCXXThis(); |
234 | Invalid = false; |
235 | } else { |
236 | Invalid = ParseUnqualifiedId(SS, |
237 | , |
238 | , |
239 | , |
240 | , |
241 | , &TemplateKWLoc, Id); |
242 | |
243 | Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, |
244 | IsUnevaluatedContext); |
245 | } |
246 | |
247 | |
248 | |
249 | while (Result.isUsable() && Tok.is(tok::period)) { |
250 | Token IdTok = PP.LookAhead(0); |
251 | if (IdTok.isNot(tok::identifier)) |
252 | break; |
253 | ConsumeToken(); |
254 | IdentifierInfo *Id = Tok.getIdentifierInfo(); |
255 | ConsumeToken(); |
256 | Result = Actions.LookupInlineAsmVarDeclField(Result.get(), Id->getName(), |
257 | Tok.getLocation()); |
258 | } |
259 | |
260 | |
261 | unsigned LineIndex = 0; |
262 | if (Tok.is(EndOfStream)) { |
263 | LineIndex = LineToks.size() - 2; |
264 | } else { |
265 | while (LineToks[LineIndex].getLocation() != Tok.getLocation()) { |
266 | LineIndex++; |
267 | assert(LineIndex < LineToks.size() - 2); |
268 | } |
269 | } |
270 | |
271 | |
272 | |
273 | if (Invalid || Tok.is(EndOfStream)) { |
274 | NumLineToksConsumed = LineToks.size() - 2; |
275 | } else { |
276 | |
277 | NumLineToksConsumed = LineIndex; |
278 | } |
279 | |
280 | |
281 | |
282 | for (unsigned i = 0, e = LineToks.size() - LineIndex - 2; i != e; ++i) { |
283 | ConsumeAnyToken(); |
284 | } |
285 | assert(Tok.is(EndOfStream)); |
286 | ConsumeToken(); |
287 | |
288 | |
289 | LineToks.pop_back(); |
290 | LineToks.pop_back(); |
291 | |
292 | return Result; |
293 | } |
294 | |
295 | |
296 | |
297 | static bool buildMSAsmString(Preprocessor &PP, SourceLocation AsmLoc, |
298 | ArrayRef<Token> AsmToks, |
299 | SmallVectorImpl<unsigned> &TokOffsets, |
300 | SmallString<512> &Asm) { |
301 | (0) . __assert_fail ("!AsmToks.empty() && \"Didn't expect an empty AsmToks!\"", "/home/seafit/code_projects/clang_source/clang/lib/Parse/ParseStmtAsm.cpp", 301, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!AsmToks.empty() && "Didn't expect an empty AsmToks!"); |
302 | |
303 | |
304 | bool isNewStatement = true; |
305 | |
306 | for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) { |
307 | const Token &Tok = AsmToks[i]; |
308 | |
309 | |
310 | if (!isNewStatement && (Tok.is(tok::kw_asm) || Tok.isAtStartOfLine())) { |
311 | Asm += "\n\t"; |
312 | isNewStatement = true; |
313 | } |
314 | |
315 | |
316 | |
317 | if (!isNewStatement && Tok.hasLeadingSpace()) |
318 | Asm += ' '; |
319 | |
320 | |
321 | TokOffsets.push_back(Asm.size()); |
322 | |
323 | |
324 | if (Tok.is(tok::kw_asm)) { |
325 | |
326 | if (i + 1 == e) { |
327 | PP.Diag(AsmLoc, diag::err_asm_empty); |
328 | return true; |
329 | } |
330 | |
331 | continue; |
332 | } |
333 | |
334 | |
335 | SmallString<32> SpellingBuffer; |
336 | bool SpellingInvalid = false; |
337 | Asm += PP.getSpelling(Tok, SpellingBuffer, &SpellingInvalid); |
338 | (0) . __assert_fail ("!SpellingInvalid && \"spelling was invalid after correct parse?\"", "/home/seafit/code_projects/clang_source/clang/lib/Parse/ParseStmtAsm.cpp", 338, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!SpellingInvalid && "spelling was invalid after correct parse?"); |
339 | |
340 | |
341 | isNewStatement = false; |
342 | } |
343 | |
344 | |
345 | Asm.push_back('\0'); |
346 | Asm.pop_back(); |
347 | |
348 | assert(TokOffsets.size() == AsmToks.size()); |
349 | return false; |
350 | } |
351 | |
352 | |
353 | |
354 | static bool isTypeQualifier(const Token &Tok) { |
355 | switch (Tok.getKind()) { |
356 | default: return false; |
357 | |
358 | case tok::kw_const: |
359 | case tok::kw_volatile: |
360 | case tok::kw_restrict: |
361 | case tok::kw___private: |
362 | case tok::kw___local: |
363 | case tok::kw___global: |
364 | case tok::kw___constant: |
365 | case tok::kw___generic: |
366 | case tok::kw___read_only: |
367 | case tok::kw___read_write: |
368 | case tok::kw___write_only: |
369 | return true; |
370 | } |
371 | } |
372 | |
373 | |
374 | static bool isGCCAsmStatement(const Token &TokAfterAsm) { |
375 | return TokAfterAsm.is(tok::l_paren) || TokAfterAsm.is(tok::kw_goto) || |
376 | isTypeQualifier(TokAfterAsm); |
377 | } |
378 | |
379 | |
380 | |
381 | |
382 | |
383 | |
384 | |
385 | |
386 | |
387 | |
388 | |
389 | |
390 | |
391 | |
392 | |
393 | |
394 | StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { |
395 | SourceManager &SrcMgr = PP.getSourceManager(); |
396 | SourceLocation EndLoc = AsmLoc; |
397 | SmallVector<Token, 4> AsmToks; |
398 | |
399 | bool SingleLineMode = true; |
400 | unsigned BraceNesting = 0; |
401 | unsigned short savedBraceCount = BraceCount; |
402 | bool = false; |
403 | FileID FID; |
404 | unsigned LineNo = 0; |
405 | unsigned NumTokensRead = 0; |
406 | SmallVector<SourceLocation, 4> LBraceLocs; |
407 | bool SkippedStartOfLine = false; |
408 | |
409 | if (Tok.is(tok::l_brace)) { |
410 | |
411 | SingleLineMode = false; |
412 | BraceNesting = 1; |
413 | EndLoc = ConsumeBrace(); |
414 | LBraceLocs.push_back(EndLoc); |
415 | ++NumTokensRead; |
416 | } else { |
417 | |
418 | std::pair<FileID, unsigned> ExpAsmLoc = |
419 | SrcMgr.getDecomposedExpansionLoc(EndLoc); |
420 | FID = ExpAsmLoc.first; |
421 | LineNo = SrcMgr.getLineNumber(FID, ExpAsmLoc.second); |
422 | LBraceLocs.push_back(SourceLocation()); |
423 | } |
424 | |
425 | SourceLocation TokLoc = Tok.getLocation(); |
426 | do { |
427 | |
428 | if (isEofOrEom()) |
429 | break; |
430 | |
431 | if (!InAsmComment && Tok.is(tok::l_brace)) { |
432 | |
433 | SkippedStartOfLine = Tok.isAtStartOfLine(); |
434 | AsmToks.push_back(Tok); |
435 | EndLoc = ConsumeBrace(); |
436 | BraceNesting++; |
437 | LBraceLocs.push_back(EndLoc); |
438 | TokLoc = Tok.getLocation(); |
439 | ++NumTokensRead; |
440 | continue; |
441 | } else if (!InAsmComment && Tok.is(tok::semi)) { |
442 | |
443 | InAsmComment = true; |
444 | if (!SingleLineMode) { |
445 | |
446 | std::pair<FileID, unsigned> ExpSemiLoc = |
447 | SrcMgr.getDecomposedExpansionLoc(TokLoc); |
448 | FID = ExpSemiLoc.first; |
449 | LineNo = SrcMgr.getLineNumber(FID, ExpSemiLoc.second); |
450 | } |
451 | } else if (SingleLineMode || InAsmComment) { |
452 | |
453 | |
454 | std::pair<FileID, unsigned> ExpLoc = |
455 | SrcMgr.getDecomposedExpansionLoc(TokLoc); |
456 | if (ExpLoc.first != FID || |
457 | SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) { |
458 | |
459 | |
460 | |
461 | |
462 | bool isAsm = Tok.is(tok::kw_asm); |
463 | if (SingleLineMode && (!isAsm || isGCCAsmStatement(NextToken()))) |
464 | break; |
465 | |
466 | InAsmComment = false; |
467 | if (isAsm) { |
468 | |
469 | |
470 | if (PP.LookAhead(0).is(tok::l_brace)) |
471 | break; |
472 | LineNo = SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second); |
473 | SkippedStartOfLine = Tok.isAtStartOfLine(); |
474 | } else if (Tok.is(tok::semi)) { |
475 | |
476 | InAsmComment = true; |
477 | FID = ExpLoc.first; |
478 | LineNo = SrcMgr.getLineNumber(FID, ExpLoc.second); |
479 | } |
480 | } else if (!InAsmComment && Tok.is(tok::r_brace)) { |
481 | |
482 | |
483 | |
484 | if (!BraceNesting) |
485 | break; |
486 | } |
487 | } |
488 | if (!InAsmComment && BraceNesting && Tok.is(tok::r_brace) && |
489 | BraceCount == (savedBraceCount + BraceNesting)) { |
490 | |
491 | SkippedStartOfLine = Tok.isAtStartOfLine(); |
492 | |
493 | if (SingleLineMode || BraceNesting > 1) { |
494 | Tok.clearFlag(Token::LeadingSpace); |
495 | AsmToks.push_back(Tok); |
496 | } |
497 | EndLoc = ConsumeBrace(); |
498 | BraceNesting--; |
499 | |
500 | |
501 | if (BraceNesting == 0 && !SingleLineMode) |
502 | break; |
503 | else { |
504 | LBraceLocs.pop_back(); |
505 | TokLoc = Tok.getLocation(); |
506 | ++NumTokensRead; |
507 | continue; |
508 | } |
509 | } |
510 | |
511 | |
512 | |
513 | EndLoc = TokLoc; |
514 | if (InAsmComment) |
515 | PP.Lex(Tok); |
516 | else { |
517 | |
518 | |
519 | if (SkippedStartOfLine) |
520 | Tok.setFlag(Token::StartOfLine); |
521 | AsmToks.push_back(Tok); |
522 | ConsumeAnyToken(); |
523 | } |
524 | TokLoc = Tok.getLocation(); |
525 | ++NumTokensRead; |
526 | SkippedStartOfLine = false; |
527 | } while (1); |
528 | |
529 | if (BraceNesting && BraceCount != savedBraceCount) { |
530 | |
531 | for (unsigned i = 0; i < BraceNesting; ++i) { |
532 | Diag(Tok, diag::err_expected) << tok::r_brace; |
533 | Diag(LBraceLocs.back(), diag::note_matching) << tok::l_brace; |
534 | LBraceLocs.pop_back(); |
535 | } |
536 | return StmtError(); |
537 | } else if (NumTokensRead == 0) { |
538 | |
539 | Diag(Tok, diag::err_expected) << tok::l_brace; |
540 | return StmtError(); |
541 | } |
542 | |
543 | |
544 | SmallVector<StringRef, 4> ConstraintRefs; |
545 | SmallVector<Expr *, 4> Exprs; |
546 | SmallVector<StringRef, 4> ClobberRefs; |
547 | |
548 | |
549 | const llvm::Triple &TheTriple = Actions.Context.getTargetInfo().getTriple(); |
550 | llvm::Triple::ArchType ArchTy = TheTriple.getArch(); |
551 | const std::string &TT = TheTriple.getTriple(); |
552 | const llvm::Target *TheTarget = nullptr; |
553 | bool UnsupportedArch = |
554 | (ArchTy != llvm::Triple::x86 && ArchTy != llvm::Triple::x86_64); |
555 | if (UnsupportedArch) { |
556 | Diag(AsmLoc, diag::err_msasm_unsupported_arch) << TheTriple.getArchName(); |
557 | } else { |
558 | std::string Error; |
559 | TheTarget = llvm::TargetRegistry::lookupTarget(TT, Error); |
560 | if (!TheTarget) |
561 | Diag(AsmLoc, diag::err_msasm_unable_to_create_target) << Error; |
562 | } |
563 | |
564 | (0) . __assert_fail ("!LBraceLocs.empty() && \"Should have at least one location here\"", "/home/seafit/code_projects/clang_source/clang/lib/Parse/ParseStmtAsm.cpp", 564, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!LBraceLocs.empty() && "Should have at least one location here"); |
565 | |
566 | |
567 | |
568 | if (!TheTarget || AsmToks.empty()) { |
569 | return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, StringRef(), |
570 | 0, 0, |
571 | ConstraintRefs, ClobberRefs, Exprs, EndLoc); |
572 | } |
573 | |
574 | |
575 | SmallString<512> AsmString; |
576 | SmallVector<unsigned, 8> TokOffsets; |
577 | if (buildMSAsmString(PP, AsmLoc, AsmToks, TokOffsets, AsmString)) |
578 | return StmtError(); |
579 | |
580 | const TargetOptions &TO = Actions.Context.getTargetInfo().getTargetOpts(); |
581 | std::string FeaturesStr = |
582 | llvm::join(TO.Features.begin(), TO.Features.end(), ","); |
583 | |
584 | std::unique_ptr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); |
585 | std::unique_ptr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT)); |
586 | |
587 | std::unique_ptr<llvm::MCInstrInfo> MII(TheTarget->createMCInstrInfo()); |
588 | std::unique_ptr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo()); |
589 | std::unique_ptr<llvm::MCSubtargetInfo> STI( |
590 | TheTarget->createMCSubtargetInfo(TT, TO.CPU, FeaturesStr)); |
591 | |
592 | llvm::SourceMgr TempSrcMgr; |
593 | llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr); |
594 | MOFI->InitMCObjectFileInfo(TheTriple, false, Ctx); |
595 | std::unique_ptr<llvm::MemoryBuffer> Buffer = |
596 | llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS inline asm>"); |
597 | |
598 | |
599 | TempSrcMgr.AddNewSourceBuffer(std::move(Buffer), llvm::SMLoc()); |
600 | |
601 | std::unique_ptr<llvm::MCStreamer> Str(createNullStreamer(Ctx)); |
602 | std::unique_ptr<llvm::MCAsmParser> Parser( |
603 | createMCAsmParser(TempSrcMgr, Ctx, *Str.get(), *MAI)); |
604 | |
605 | |
606 | llvm::MCTargetOptions MCOptions; |
607 | std::unique_ptr<llvm::MCTargetAsmParser> TargetParser( |
608 | TheTarget->createMCAsmParser(*STI, *Parser, *MII, MCOptions)); |
609 | |
610 | std::unique_ptr<llvm::MCInstPrinter> IP( |
611 | TheTarget->createMCInstPrinter(llvm::Triple(TT), 1, *MAI, *MII, *MRI)); |
612 | |
613 | |
614 | Parser->setAssemblerDialect(1); |
615 | Parser->setTargetParser(*TargetParser.get()); |
616 | Parser->setParsingInlineAsm(true); |
617 | TargetParser->setParsingInlineAsm(true); |
618 | |
619 | ClangAsmParserCallback Callback(*this, AsmLoc, AsmString, AsmToks, |
620 | TokOffsets); |
621 | TargetParser->setSemaCallback(&Callback); |
622 | TempSrcMgr.setDiagHandler(ClangAsmParserCallback::DiagHandlerCallback, |
623 | &Callback); |
624 | |
625 | unsigned NumOutputs; |
626 | unsigned NumInputs; |
627 | std::string AsmStringIR; |
628 | SmallVector<std::pair<void *, bool>, 4> OpExprs; |
629 | SmallVector<std::string, 4> Constraints; |
630 | SmallVector<std::string, 4> Clobbers; |
631 | if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, NumOutputs, |
632 | NumInputs, OpExprs, Constraints, Clobbers, |
633 | MII.get(), IP.get(), Callback)) |
634 | return StmtError(); |
635 | |
636 | |
637 | |
638 | llvm::erase_if(Clobbers, [](const std::string &C) { |
639 | return C == "fpsr" || C == "mxcsr"; |
640 | }); |
641 | |
642 | |
643 | ClobberRefs.insert(ClobberRefs.end(), Clobbers.begin(), Clobbers.end()); |
644 | |
645 | |
646 | unsigned NumExprs = NumOutputs + NumInputs; |
647 | ConstraintRefs.resize(NumExprs); |
648 | Exprs.resize(NumExprs); |
649 | for (unsigned i = 0, e = NumExprs; i != e; ++i) { |
650 | Expr *OpExpr = static_cast<Expr *>(OpExprs[i].first); |
651 | if (!OpExpr) |
652 | return StmtError(); |
653 | |
654 | |
655 | if (OpExprs[i].second) |
656 | OpExpr = |
657 | Actions.BuildUnaryOp(getCurScope(), AsmLoc, UO_AddrOf, OpExpr).get(); |
658 | |
659 | ConstraintRefs[i] = StringRef(Constraints[i]); |
660 | Exprs[i] = OpExpr; |
661 | } |
662 | |
663 | |
664 | return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, AsmStringIR, |
665 | NumOutputs, NumInputs, ConstraintRefs, |
666 | ClobberRefs, Exprs, EndLoc); |
667 | } |
668 | |
669 | |
670 | |
671 | |
672 | |
673 | |
674 | |
675 | |
676 | |
677 | |
678 | |
679 | |
680 | |
681 | |
682 | |
683 | |
684 | |
685 | |
686 | |
687 | |
688 | StmtResult Parser::ParseAsmStatement(bool &msAsm) { |
689 | (0) . __assert_fail ("Tok.is(tok..kw_asm) && \"Not an asm stmt\"", "/home/seafit/code_projects/clang_source/clang/lib/Parse/ParseStmtAsm.cpp", 689, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Tok.is(tok::kw_asm) && "Not an asm stmt"); |
690 | SourceLocation AsmLoc = ConsumeToken(); |
691 | |
692 | if (getLangOpts().AsmBlocks && !isGCCAsmStatement(Tok)) { |
693 | msAsm = true; |
694 | return ParseMicrosoftAsmStatement(AsmLoc); |
695 | } |
696 | |
697 | DeclSpec DS(AttrFactory); |
698 | SourceLocation Loc = Tok.getLocation(); |
699 | ParseTypeQualifierListOpt(DS, AR_VendorAttributesParsed); |
700 | |
701 | |
702 | if (DS.getTypeQualifiers() & DeclSpec::TQ_const) |
703 | Diag(Loc, diag::warn_asm_qualifier_ignored) << "const"; |
704 | if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict) |
705 | Diag(Loc, diag::warn_asm_qualifier_ignored) << "restrict"; |
706 | |
707 | if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic) |
708 | Diag(Loc, diag::warn_asm_qualifier_ignored) << "_Atomic"; |
709 | |
710 | |
711 | bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile; |
712 | |
713 | |
714 | if (Tok.is(tok::kw_goto)) { |
715 | Diag(Tok, diag::err_asm_goto_not_supported_yet); |
716 | SkipUntil(tok::r_paren, StopAtSemi); |
717 | return StmtError(); |
718 | } |
719 | |
720 | if (Tok.isNot(tok::l_paren)) { |
721 | Diag(Tok, diag::err_expected_lparen_after) << "asm"; |
722 | SkipUntil(tok::r_paren, StopAtSemi); |
723 | return StmtError(); |
724 | } |
725 | BalancedDelimiterTracker T(*this, tok::l_paren); |
726 | T.consumeOpen(); |
727 | |
728 | ExprResult AsmString(ParseAsmStringLiteral()); |
729 | |
730 | |
731 | |
732 | if (!(getLangOpts().GNUAsm || AsmString.isInvalid())) { |
733 | const auto *SL = cast<StringLiteral>(AsmString.get()); |
734 | if (!SL->getString().trim().empty()) |
735 | Diag(Loc, diag::err_gnu_inline_asm_disabled); |
736 | } |
737 | |
738 | if (AsmString.isInvalid()) { |
739 | |
740 | T.skipToEnd(); |
741 | return StmtError(); |
742 | } |
743 | |
744 | SmallVector<IdentifierInfo *, 4> Names; |
745 | ExprVector Constraints; |
746 | ExprVector Exprs; |
747 | ExprVector Clobbers; |
748 | |
749 | if (Tok.is(tok::r_paren)) { |
750 | |
751 | T.consumeClose(); |
752 | return Actions.ActOnGCCAsmStmt(AsmLoc, true, isVolatile, |
753 | 0, 0, nullptr, |
754 | Constraints, Exprs, AsmString.get(), |
755 | Clobbers, T.getCloseLocation()); |
756 | } |
757 | |
758 | |
759 | bool = false; |
760 | if (Tok.is(tok::colon) || Tok.is(tok::coloncolon)) { |
761 | |
762 | AteExtraColon = Tok.is(tok::coloncolon); |
763 | ConsumeToken(); |
764 | |
765 | if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs)) |
766 | return StmtError(); |
767 | } |
768 | |
769 | unsigned NumOutputs = Names.size(); |
770 | |
771 | |
772 | if (AteExtraColon || Tok.is(tok::colon) || Tok.is(tok::coloncolon)) { |
773 | |
774 | if (AteExtraColon) |
775 | AteExtraColon = false; |
776 | else { |
777 | AteExtraColon = Tok.is(tok::coloncolon); |
778 | ConsumeToken(); |
779 | } |
780 | |
781 | if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs)) |
782 | return StmtError(); |
783 | } |
784 | |
785 | (0) . __assert_fail ("Names.size() == Constraints.size() && Constraints.size() == Exprs.size() && \"Input operand size mismatch!\"", "/home/seafit/code_projects/clang_source/clang/lib/Parse/ParseStmtAsm.cpp", 786, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Names.size() == Constraints.size() && |
786 | (0) . __assert_fail ("Names.size() == Constraints.size() && Constraints.size() == Exprs.size() && \"Input operand size mismatch!\"", "/home/seafit/code_projects/clang_source/clang/lib/Parse/ParseStmtAsm.cpp", 786, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> Constraints.size() == Exprs.size() && "Input operand size mismatch!"); |
787 | |
788 | unsigned NumInputs = Names.size() - NumOutputs; |
789 | |
790 | |
791 | if (AteExtraColon || Tok.is(tok::colon)) { |
792 | if (!AteExtraColon) |
793 | ConsumeToken(); |
794 | |
795 | |
796 | if (Tok.isNot(tok::r_paren)) { |
797 | while (1) { |
798 | ExprResult Clobber(ParseAsmStringLiteral()); |
799 | |
800 | if (Clobber.isInvalid()) |
801 | break; |
802 | |
803 | Clobbers.push_back(Clobber.get()); |
804 | |
805 | if (!TryConsumeToken(tok::comma)) |
806 | break; |
807 | } |
808 | } |
809 | } |
810 | |
811 | T.consumeClose(); |
812 | return Actions.ActOnGCCAsmStmt( |
813 | AsmLoc, false, isVolatile, NumOutputs, NumInputs, Names.data(), |
814 | Constraints, Exprs, AsmString.get(), Clobbers, T.getCloseLocation()); |
815 | } |
816 | |
817 | |
818 | |
819 | |
820 | |
821 | |
822 | |
823 | |
824 | |
825 | |
826 | |
827 | |
828 | |
829 | |
830 | bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names, |
831 | SmallVectorImpl<Expr *> &Constraints, |
832 | SmallVectorImpl<Expr *> &Exprs) { |
833 | |
834 | if (!isTokenStringLiteral() && Tok.isNot(tok::l_square)) |
835 | return false; |
836 | |
837 | while (1) { |
838 | |
839 | if (Tok.is(tok::l_square)) { |
840 | BalancedDelimiterTracker T(*this, tok::l_square); |
841 | T.consumeOpen(); |
842 | |
843 | if (Tok.isNot(tok::identifier)) { |
844 | Diag(Tok, diag::err_expected) << tok::identifier; |
845 | SkipUntil(tok::r_paren, StopAtSemi); |
846 | return true; |
847 | } |
848 | |
849 | IdentifierInfo *II = Tok.getIdentifierInfo(); |
850 | ConsumeToken(); |
851 | |
852 | Names.push_back(II); |
853 | T.consumeClose(); |
854 | } else |
855 | Names.push_back(nullptr); |
856 | |
857 | ExprResult Constraint(ParseAsmStringLiteral()); |
858 | if (Constraint.isInvalid()) { |
859 | SkipUntil(tok::r_paren, StopAtSemi); |
860 | return true; |
861 | } |
862 | Constraints.push_back(Constraint.get()); |
863 | |
864 | if (Tok.isNot(tok::l_paren)) { |
865 | Diag(Tok, diag::err_expected_lparen_after) << "asm operand"; |
866 | SkipUntil(tok::r_paren, StopAtSemi); |
867 | return true; |
868 | } |
869 | |
870 | |
871 | BalancedDelimiterTracker T(*this, tok::l_paren); |
872 | T.consumeOpen(); |
873 | ExprResult Res = Actions.CorrectDelayedTyposInExpr(ParseExpression()); |
874 | T.consumeClose(); |
875 | if (Res.isInvalid()) { |
876 | SkipUntil(tok::r_paren, StopAtSemi); |
877 | return true; |
878 | } |
879 | Exprs.push_back(Res.get()); |
880 | |
881 | if (!TryConsumeToken(tok::comma)) |
882 | return false; |
883 | } |
884 | } |
885 | |