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