clang: lib/Parse/ParseStmtAsm.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
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/MC/TargetRegistry.h"
32#include "llvm/Support/SourceMgr.h"
33#include "llvm/Support/TargetSelect.h"
34using namespace clang;
35
36namespace {
37class ClangAsmParserCallback : public llvm::MCAsmParserSemaCallback {
40 StringRef AsmString;
41
42
44
45
47
48public:
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 {
67 AsmLoc);
68 }
69
70 static void DiagHandlerCallback(const llvm::SMDiagnostic &D, void *Context) {
71 ((ClangAsmParserCallback *)Context)->handleDiagnostic(D);
72 }
73
74private:
75
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
86void ClangAsmParserCallback::LookupInlineAsmIdentifier(
87 StringRef &LineBuf, llvm::InlineAsmIdentifierInfo &Info,
88 bool IsUnevaluatedContext) {
89
91 const Token *FirstOrigToken = nullptr;
92 findTokensForString(LineBuf, LineToks, FirstOrigToken);
93
94 unsigned NumConsumedToks;
96 IsUnevaluatedContext);
97
98
99
100 if (NumConsumedToks == 0 || NumConsumedToks == LineToks.size()) {
101
102
103
104 } else {
105 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;
125}
126
127StringRef ClangAsmParserCallback::LookupInlineAsmLabel(StringRef Identifier,
128 llvm::SourceMgr &LSM,
129 llvm::SMLoc Location,
134 return Label->getMSAsmLabel();
135}
136
137void ClangAsmParserCallback::findTokensForString(
139 const Token *&FirstOrigToken) const {
140
141
142 assert(!std::less<const char *>()(Str.begin(), AsmString.begin()) &&
143 !std::less<const char *>()(AsmString.end(), Str.end()));
144
145
146 unsigned FirstCharOffset = Str.begin() - AsmString.begin();
147 const unsigned *FirstTokOffset =
148 llvm::lower_bound(AsmTokOffsets, 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
167ClangAsmParserCallback::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 = llvm::lower_bound(AsmTokOffsets, Offset);
178 unsigned TokIndex = TokOffsetPtr - AsmTokOffsets.begin();
179 unsigned TokOffset = *TokOffsetPtr;
180
181
182
183
185 if (TokIndex < AsmToks.size()) {
186 const Token &Tok = AsmToks[TokIndex];
189 }
190 return Loc;
191}
192
193void ClangAsmParserCallback::handleDiagnostic(const llvm::SMDiagnostic &D) {
194 const llvm::SourceMgr &LSM = *D.getSourceMgr();
196 TheParser.Diag(Loc, diag::err_inline_ms_asm_parsing) << D.getMessage();
197}
198
199
201 unsigned &NumLineToksConsumed,
202 bool IsUnevaluatedContext) {
203
204
205
207 Token EndOfStreamTok;
209 EndOfStreamTok.setKind(EndOfStream);
210 LineToks.push_back(EndOfStreamTok);
211
212
213 LineToks.push_back(Tok);
214
215 PP.EnterTokenStream(LineToks, true,
216 true);
217
218
220
221
224 ParseOptionalCXXScopeSpecifier(SS, nullptr,
225 false,
226 false);
227
228
231 bool Invalid = true;
233 if (Tok.is(tok::kw_this)) {
234 Result = ParseCXXThis();
235 Invalid = false;
236 } else {
237 Invalid =
239 false,
240 false,
241 false,
242 false,
243 false, &TemplateKWLoc, Id);
244
246 IsUnevaluatedContext);
247 }
248
249
250
251 while (Result.isUsable() && Tok.is(tok::period)) {
253 if (IdTok.isNot(tok::identifier))
254 break;
260 }
261
262
263 unsigned LineIndex = 0;
264 if (Tok.is(EndOfStream)) {
265 LineIndex = LineToks.size() - 2;
266 } else {
267 while (LineToks[LineIndex].getLocation() != Tok.getLocation()) {
268 LineIndex++;
269 assert(LineIndex < LineToks.size() - 2);
270 }
271 }
272
273
274
275 if (Invalid || Tok.is(EndOfStream)) {
276 NumLineToksConsumed = LineToks.size() - 2;
277 } else {
278
279 NumLineToksConsumed = LineIndex;
280 }
281
282
283
284 for (unsigned i = 0, e = LineToks.size() - LineIndex - 2; i != e; ++i) {
286 }
287 assert(Tok.is(EndOfStream));
289
290
291 LineToks.pop_back();
292 LineToks.pop_back();
293
295}
296
297
298
303 assert(!AsmToks.empty() && "Didn't expect an empty AsmToks!");
304
305
306 bool isNewStatement = true;
307
308 for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) {
309 const Token &Tok = AsmToks[i];
310
311
312 if (!isNewStatement && (Tok.is(tok::kw_asm) || Tok.isAtStartOfLine())) {
313 Asm += "\n\t";
314 isNewStatement = true;
315 }
316
317
318
320 Asm += ' ';
321
322
323 TokOffsets.push_back(Asm.size());
324
325
326 if (Tok.is(tok::kw_asm)) {
327
328 if (i + 1 == e) {
329 PP.Diag(AsmLoc, diag::err_asm_empty);
330 return true;
331 }
332
333 continue;
334 }
335
336
338 bool SpellingInvalid = false;
339 Asm += PP.getSpelling(Tok, SpellingBuffer, &SpellingInvalid);
340 assert(!SpellingInvalid && "spelling was invalid after correct parse?");
341
342
343 isNewStatement = false;
344 }
345
346
347 Asm.push_back('\0');
348 Asm.pop_back();
349
350 assert(TokOffsets.size() == AsmToks.size());
351 return false;
352}
353
354
355bool Parser::isGCCAsmStatement(const Token &TokAfterAsm) const {
356 return TokAfterAsm.is(tok::l_paren) || isGNUAsmQualifier(TokAfterAsm);
357}
358
359bool Parser::isGNUAsmQualifier(const Token &TokAfterAsm) const {
360 return getGNUAsmQualifier(TokAfterAsm) != GNUAsmQualifiers::AQ_unspecified;
361}
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
382
383 bool SingleLineMode = true;
384 unsigned BraceNesting = 0;
385 unsigned short savedBraceCount = BraceCount;
386 bool InAsmComment = false;
388 unsigned LineNo = 0;
389 unsigned NumTokensRead = 0;
391 bool SkippedStartOfLine = false;
392
393 if (Tok.is(tok::l_brace)) {
394
395 SingleLineMode = false;
396 BraceNesting = 1;
397 EndLoc = ConsumeBrace();
398 LBraceLocs.push_back(EndLoc);
399 ++NumTokensRead;
400 } else {
401
402 std::pair<FileID, unsigned> ExpAsmLoc =
404 FID = ExpAsmLoc.first;
405 LineNo = SrcMgr.getLineNumber(FID, ExpAsmLoc.second);
407 }
408
410 do {
411
412 if (isEofOrEom())
413 break;
414
415 if (!InAsmComment && Tok.is(tok::l_brace)) {
416
418 AsmToks.push_back(Tok);
419 EndLoc = ConsumeBrace();
420 BraceNesting++;
421 LBraceLocs.push_back(EndLoc);
423 ++NumTokensRead;
424 continue;
425 } else if (!InAsmComment && Tok.is(tok::semi)) {
426
427 InAsmComment = true;
428 if (!SingleLineMode) {
429
430 std::pair<FileID, unsigned> ExpSemiLoc =
432 FID = ExpSemiLoc.first;
433 LineNo = SrcMgr.getLineNumber(FID, ExpSemiLoc.second);
434 }
435 } else if (SingleLineMode || InAsmComment) {
436
437
438 std::pair<FileID, unsigned> ExpLoc =
440 if (ExpLoc.first != FID ||
441 SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) {
442
443
444
445
446 bool isAsm = Tok.is(tok::kw_asm);
447 if (SingleLineMode && (!isAsm || isGCCAsmStatement(NextToken())))
448 break;
449
450 InAsmComment = false;
451 if (isAsm) {
452
453
455 break;
456 LineNo = SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second);
458 } else if (Tok.is(tok::semi)) {
459
460 InAsmComment = true;
461 FID = ExpLoc.first;
462 LineNo = SrcMgr.getLineNumber(FID, ExpLoc.second);
463 }
464 } else if (!InAsmComment && Tok.is(tok::r_brace)) {
465
466
467
468 if (!BraceNesting)
469 break;
470 }
471 }
472 if (!InAsmComment && BraceNesting && Tok.is(tok::r_brace) &&
473 BraceCount == (savedBraceCount + BraceNesting)) {
474
476
477 if (SingleLineMode || BraceNesting > 1) {
479 AsmToks.push_back(Tok);
480 }
481 EndLoc = ConsumeBrace();
482 BraceNesting--;
483
484
485 if (BraceNesting == 0 && !SingleLineMode)
486 break;
487 else {
488 LBraceLocs.pop_back();
490 ++NumTokensRead;
491 continue;
492 }
493 }
494
495
496
497 EndLoc = TokLoc;
498 if (InAsmComment)
499 PP.Lex(Tok);
500 else {
501
502
503 if (SkippedStartOfLine)
505 AsmToks.push_back(Tok);
507 }
509 ++NumTokensRead;
510 SkippedStartOfLine = false;
511 } while (true);
512
513 if (BraceNesting && BraceCount != savedBraceCount) {
514
515 for (unsigned i = 0; i < BraceNesting; ++i) {
516 Diag(Tok, diag::err_expected) << tok::r_brace;
517 Diag(LBraceLocs.back(), diag::note_matching) << tok::l_brace;
518 LBraceLocs.pop_back();
519 }
521 } else if (NumTokensRead == 0) {
522
523 Diag(Tok, diag::err_expected) << tok::l_brace;
525 }
526
527
531
532
534 const std::string &TT = TheTriple.getTriple();
535 const llvm::Target *TheTarget = nullptr;
536 if (!TheTriple.isX86()) {
537 Diag(AsmLoc, diag::err_msasm_unsupported_arch) << TheTriple.getArchName();
538 } else {
539 std::string Error;
540 TheTarget = llvm::TargetRegistry::lookupTarget(TT, Error);
541 if (!TheTarget)
542 Diag(AsmLoc, diag::err_msasm_unable_to_create_target) << Error;
543 }
544
545 assert(!LBraceLocs.empty() && "Should have at least one location here");
546
548 auto EmptyStmt = [&] {
549 return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, AsmString,
550 0, 0,
551 ConstraintRefs, ClobberRefs, Exprs, EndLoc);
552 };
553
554
555 if (!TheTarget || AsmToks.empty()) {
556 return EmptyStmt();
557 }
558
559
561 if (buildMSAsmString(PP, AsmLoc, AsmToks, TokOffsets, AsmString))
563
565 std::string FeaturesStr =
567
568 std::unique_ptrllvm::MCRegisterInfo MRI(TheTarget->createMCRegInfo(TT));
569 if (!MRI) {
570 Diag(AsmLoc, diag::err_msasm_unable_to_create_target)
571 << "target MC unavailable";
572 return EmptyStmt();
573 }
574
575 llvm::MCTargetOptions MCOptions;
576 std::unique_ptrllvm::MCAsmInfo MAI(
577 TheTarget->createMCAsmInfo(*MRI, TT, MCOptions));
578
579 std::unique_ptrllvm::MCInstrInfo MII(TheTarget->createMCInstrInfo());
580 std::unique_ptrllvm::MCSubtargetInfo STI(
581 TheTarget->createMCSubtargetInfo(TT, TO.CPU, FeaturesStr));
582
583
584 if (!MAI || !MII || !STI) {
585 Diag(AsmLoc, diag::err_msasm_unable_to_create_target)
586 << "target MC unavailable";
587 return EmptyStmt();
588 }
589
590 llvm::SourceMgr TempSrcMgr;
591 llvm::MCContext Ctx(TheTriple, MAI.get(), MRI.get(), STI.get(), &TempSrcMgr);
592 std::unique_ptrllvm::MCObjectFileInfo MOFI(
593 TheTarget->createMCObjectFileInfo(Ctx, false));
594 Ctx.setObjectFileInfo(MOFI.get());
595
596 std::unique_ptrllvm::MemoryBuffer Buffer =
597 llvm::MemoryBuffer::getMemBuffer(AsmString, "");
598
599
600 TempSrcMgr.AddNewSourceBuffer(std::move(Buffer), llvm::SMLoc());
601
602 std::unique_ptrllvm::MCStreamer Str(createNullStreamer(Ctx));
603 std::unique_ptrllvm::MCAsmParser Parser(
604 createMCAsmParser(TempSrcMgr, Ctx, *Str.get(), *MAI));
605
606 std::unique_ptrllvm::MCTargetAsmParser TargetParser(
607 TheTarget->createMCAsmParser(*STI, *Parser, *MII, MCOptions));
608
609 if (!TargetParser) {
610 Diag(AsmLoc, diag::err_msasm_unable_to_create_target)
611 << "target ASM parser unavailable";
612 return EmptyStmt();
613 }
614
615 std::unique_ptrllvm::MCInstPrinter IP(
616 TheTarget->createMCInstPrinter(llvm::Triple(TT), 1, *MAI, *MII, *MRI));
617
618
619 Parser->setAssemblerDialect(1);
620 Parser->setTargetParser(*TargetParser.get());
621 Parser->setParsingMSInlineAsm(true);
622 TargetParser->setParsingMSInlineAsm(true);
623
624 ClangAsmParserCallback Callback(*this, AsmLoc, AsmString, AsmToks,
625 TokOffsets);
626 TargetParser->setSemaCallback(&Callback);
627 TempSrcMgr.setDiagHandler(ClangAsmParserCallback::DiagHandlerCallback,
628 &Callback);
629
630 unsigned NumOutputs;
631 unsigned NumInputs;
632 std::string AsmStringIR;
636 if (Parser->parseMSInlineAsm(AsmStringIR, NumOutputs, NumInputs, OpExprs,
637 Constraints, Clobbers, MII.get(), IP.get(),
638 Callback))
640
641
642
643 llvm::erase_if(Clobbers, [](const std::string &C) {
644 return C == "fpsr" || C == "mxcsr";
645 });
646
647
648 ClobberRefs.insert(ClobberRefs.end(), Clobbers.begin(), Clobbers.end());
649
650
651 unsigned NumExprs = NumOutputs + NumInputs;
652 ConstraintRefs.resize(NumExprs);
653 Exprs.resize(NumExprs);
654 for (unsigned i = 0, e = NumExprs; i != e; ++i) {
655 Expr *OpExpr = static_cast<Expr *>(OpExprs[i].first);
656 if (!OpExpr)
658
659
660 if (OpExprs[i].second)
661 OpExpr =
663
664 ConstraintRefs[i] = StringRef(Constraints[i]);
665 Exprs[i] = OpExpr;
666 }
667
668
669 return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, AsmStringIR,
670 NumOutputs, NumInputs, ConstraintRefs,
671 ClobberRefs, Exprs, EndLoc);
672}
673
674
675
676
677
678
679
680
681
682
683bool Parser::parseGNUAsmQualifierListOpt(GNUAsmQualifiers &AQ) {
684 while (true) {
685 const GNUAsmQualifiers::AQ A = getGNUAsmQualifier(Tok);
686 if (A == GNUAsmQualifiers::AQ_unspecified) {
687 if (Tok.isNot(tok::l_paren)) {
688 Diag(Tok.getLocation(), diag::err_asm_qualifier_ignored);
690 return true;
691 }
692 return false;
693 }
694 if (AQ.setAsmQualifier(A))
696 << GNUAsmQualifiers::getQualifierName(A);
698 }
699 return false;
700}
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721StmtResult Parser::ParseAsmStatement(bool &msAsm) {
722 assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
724
725 if (getLangOpts().AsmBlocks && !isGCCAsmStatement(Tok)) {
726 msAsm = true;
727 return ParseMicrosoftAsmStatement(AsmLoc);
728 }
729
731 GNUAsmQualifiers GAQ;
732 if (parseGNUAsmQualifierListOpt(GAQ))
734
735 if (GAQ.isGoto() && getLangOpts().SpeculativeLoadHardening)
736 Diag(Loc, diag::warn_slh_does_not_support_asm_goto);
737
739 T.consumeOpen();
740
741 ExprResult AsmString(ParseAsmStringLiteral( false));
742
743
744
745 if (!(getLangOpts().GNUAsm || AsmString.isInvalid())) {
746 const auto *SL = cast(AsmString.get());
747 if (!SL->getString().trim().empty())
748 Diag(Loc, diag::err_gnu_inline_asm_disabled);
749 }
750
751 if (AsmString.isInvalid()) {
752
753 T.skipToEnd();
755 }
756
758 ExprVector Constraints;
759 ExprVector Exprs;
760 ExprVector Clobbers;
761
762 if (Tok.is(tok::r_paren)) {
763
764 T.consumeClose();
766 AsmLoc, true, GAQ.isVolatile(),
767 0, 0, nullptr, Constraints, Exprs,
768 AsmString.get(), Clobbers, 0, T.getCloseLocation());
769 }
770
771
772 bool AteExtraColon = false;
773 if (Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
774
775 AteExtraColon = Tok.is(tok::coloncolon);
777
778 if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs))
780 }
781
782 unsigned NumOutputs = Names.size();
783
784
785 if (AteExtraColon || Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
786
787 if (AteExtraColon)
788 AteExtraColon = false;
789 else {
790 AteExtraColon = Tok.is(tok::coloncolon);
792 }
793
794 if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs))
796 }
797
798 assert(Names.size() == Constraints.size() &&
799 Constraints.size() == Exprs.size() && "Input operand size mismatch!");
800
801 unsigned NumInputs = Names.size() - NumOutputs;
802
803
804 if (AteExtraColon || Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
805 if (AteExtraColon)
806 AteExtraColon = false;
807 else {
808 AteExtraColon = Tok.is(tok::coloncolon);
810 }
811
812 if (!AteExtraColon && isTokenStringLiteral()) {
813 while (true) {
814 ExprResult Clobber(ParseAsmStringLiteral( false));
815
816 if (Clobber.isInvalid())
817 break;
818
819 Clobbers.push_back(Clobber.get());
820
822 break;
823 }
824 }
825 }
826 if (!GAQ.isGoto() && (Tok.isNot(tok::r_paren) || AteExtraColon)) {
827 Diag(Tok, diag::err_expected) << tok::r_paren;
830 }
831
832
833 unsigned NumLabels = 0;
834 if (AteExtraColon || Tok.is(tok::colon)) {
835 if (!AteExtraColon)
837
838 while (true) {
839 if (Tok.isNot(tok::identifier)) {
840 Diag(Tok, diag::err_expected) << tok::identifier;
843 }
847 if (!LD) {
850 }
853 Exprs.push_back(Res.get());
854 NumLabels++;
857 break;
858 }
859 } else if (GAQ.isGoto()) {
860 Diag(Tok, diag::err_expected) << tok::colon;
863 }
864 T.consumeClose();
865 return Actions.ActOnGCCAsmStmt(AsmLoc, false, GAQ.isVolatile(), NumOutputs,
866 NumInputs, Names.data(), Constraints, Exprs,
867 AsmString.get(), Clobbers, NumLabels,
868 T.getCloseLocation());
869}
870
871
872
873
874
875
876
877
878
879
880
881
882
883
887
888 if (!isTokenStringLiteral() && Tok.isNot(tok::l_square))
889 return false;
890
891 while (true) {
892
893 if (Tok.is(tok::l_square)) {
895 T.consumeOpen();
896
897 if (Tok.isNot(tok::identifier)) {
898 Diag(Tok, diag::err_expected) << tok::identifier;
900 return true;
901 }
902
905
906 Names.push_back(II);
907 T.consumeClose();
908 } else
909 Names.push_back(nullptr);
910
911 ExprResult Constraint(ParseAsmStringLiteral( false));
912 if (Constraint.isInvalid()) {
914 return true;
915 }
916 Constraints.push_back(Constraint.get());
917
918 if (Tok.isNot(tok::l_paren)) {
919 Diag(Tok, diag::err_expected_lparen_after) << "asm operand";
921 return true;
922 }
923
924
926 T.consumeOpen();
928 T.consumeClose();
931 return true;
932 }
933 Exprs.push_back(Res.get());
934
936 return false;
937 }
938}
939
940const char *Parser::GNUAsmQualifiers::getQualifierName(AQ Qualifier) {
941 switch (Qualifier) {
942 case AQ_volatile: return "volatile";
943 case AQ_inline: return "inline";
944 case AQ_goto: return "goto";
945 case AQ_unspecified: return "unspecified";
946 }
947 llvm_unreachable("Unknown GNUAsmQualifier");
948}
949
950Parser::GNUAsmQualifiers::AQ
951Parser::getGNUAsmQualifier(const Token &Tok) const {
953 case tok::kw_volatile: return GNUAsmQualifiers::AQ_volatile;
954 case tok::kw_inline: return GNUAsmQualifiers::AQ_inline;
955 case tok::kw_goto: return GNUAsmQualifiers::AQ_goto;
956 default: return GNUAsmQualifiers::AQ_unspecified;
957 }
958}
959bool Parser::GNUAsmQualifiers::setAsmQualifier(AQ Qualifier) {
962 return IsDuplicate;
963}
Defines the clang::ASTContext interface.
Defines the Diagnostic-related interfaces.
static bool buildMSAsmString(Preprocessor &PP, SourceLocation AsmLoc, ArrayRef< Token > AsmToks, SmallVectorImpl< unsigned > &TokOffsets, SmallString< 512 > &Asm)
Turn a sequence of our tokens back into a string that we can hand to the MC asm parser.
const TargetInfo & getTargetInfo() const
RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ....
Represents a C++ nested-name-specifier or a global scope specifier.
This represents one expression.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
One of these records is kept for each identifier that is lexed.
Represents the declaration of a label.
Parser - This implements a parser for the C family of languages.
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
SourceLocation ConsumeToken()
ConsumeToken - Consume the current 'peek token' and lex the next one.
Sema & getActions() const
ExprResult ParseMSAsmIdentifier(llvm::SmallVectorImpl< Token > &LineToks, unsigned &NumLineToksConsumed, bool IsUnevaluated)
Parse an identifier in an MS-style inline assembly block.
bool ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, bool AllowDeductionGuide, SourceLocation *TemplateKWLoc, UnqualifiedId &Result)
Parse a C++ unqualified-id (or a C identifier), which describes the name of an entity.
SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok=false)
ConsumeAnyToken - Dispatch to the right Consume* method based on the current token type.
bool TryConsumeToken(tok::TokenKind Expected)
Scope * getCurScope() const
bool SkipUntil(tok::TokenKind T, SkipUntilFlags Flags=static_cast< SkipUntilFlags >(0))
SkipUntil - Read tokens until we get to the specified token, then consume it (unless StopBeforeMatch ...
const LangOptions & getLangOpts() const
ExprResult ParseExpression(TypeCastState isTypeCast=NotTypeCast)
Simple precedence-based parser for binary/ternary operators.
@ StopAtSemi
Stop skipping at semicolon.
const Token & NextToken()
NextToken - This peeks ahead one token and returns it without consuming it.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
void Lex(Token &Result)
Lex the next token for this preprocessor.
const Token & LookAhead(unsigned N)
Peeks ahead N tokens and returns that token without consuming any tokens.
SourceManager & getSourceManager() const
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const
Forwarding function for diagnostics.
The collection of all-type qualifiers we support.
StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, ArrayRef< Token > AsmToks, StringRef AsmString, unsigned NumOutputs, unsigned NumInputs, ArrayRef< StringRef > Constraints, ArrayRef< StringRef > Clobbers, ArrayRef< Expr * > Exprs, SourceLocation EndLoc)
ExprResult LookupInlineAsmIdentifier(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, bool IsUnevaluatedContext)
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp=false)
ExprResult ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc, LabelDecl *TheDecl)
ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
void FillInlineAsmIdentifierInfo(Expr *Res, llvm::InlineAsmIdentifierInfo &Info)
bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset, SourceLocation AsmLoc)
LabelDecl * LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc, SourceLocation GnuLabelLoc=SourceLocation())
LookupOrCreateLabel - Do a name lookup of a label with the specified name.
ExprResult LookupInlineAsmVarDeclField(Expr *RefExpr, StringRef Member, SourceLocation AsmLoc)
LabelDecl * GetOrCreateMSAsmLabel(StringRef ExternalLabelName, SourceLocation Location, bool AlwaysCreate)
ExprResult CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl=nullptr, bool RecoverUncorrectedTypos=false, llvm::function_ref< ExprResult(Expr *)> Filter=[](Expr *E) -> ExprResult { return E;})
Process any TypoExprs in the given Expr and its children, generating diagnostics as appropriate and r...
StmtResult ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, bool IsVolatile, unsigned NumOutputs, unsigned NumInputs, IdentifierInfo **Names, MultiExprArg Constraints, MultiExprArg Exprs, Expr *AsmString, MultiExprArg Clobbers, unsigned NumLabels, SourceLocation RParenLoc)
Encodes a location in the source.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
This class handles loading and caching of source files into memory.
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Given a SourceLocation, return the spelling line number for the position indicated.
std::pair< FileID, unsigned > getDecomposedExpansionLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
TargetOptions & getTargetOpts() const
Retrieve the target options.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Options for controlling the target.
std::vector< std::string > Features
The list of target specific features to enable or disable – this should be a list of strings starting...
std::string CPU
If given, the name of the target CPU to generate code for.
Token - This structure provides full information about a lexed token.
IdentifierInfo * getIdentifierInfo() const
void clearFlag(TokenFlags Flag)
Unset the specified flag.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
void setKind(tok::TokenKind K)
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
tok::TokenKind getKind() const
bool isAtStartOfLine() const
isAtStartOfLine - Return true if this token is at the start of a line.
bool hasLeadingSpace() const
Return true if this token has whitespace before it.
bool isNot(tok::TokenKind K) const
void startToken()
Reset all flags to cleared.
void setFlag(TokenFlags Flag)
Set the specified flag.
Represents a C++ unqualified-id that has been parsed.
Defines the clang::TargetInfo interface.
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
The JSON file list parser is used to communicate input to InstallAPI.
@ Create
'create' clause, allowed on Compute and Combined constructs, plus 'data', 'enter data',...
@ Asm
Assembly: we accept this only so that we can preprocess it.
@ Result
The result type of a method or function.
const FunctionProtoType * T