clang: include/clang/Analysis/Analyses/ThreadSafetyTraverse.h Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H

17#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H

18

23#include "llvm/ADT/StringRef.h"

24#include "llvm/Support/Casting.h"

25#include

26#include

27

29namespace threadSafety {

30namespace til {

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57template <class Self, class R>

59public:

61

62

63

64

65

66

67 template

68 typename R::R_SExpr traverse(T* &E, typename R::R_Ctx Ctx) {

70 }

71

72

73

76 }

77

78

80 switch (E->opcode()) {

81#define TIL_OPCODE_DEF(X) \

82 case COP_##X: \

83 return self()->traverse##X(cast(E), Ctx);

84#include "ThreadSafetyOps.def"

85#undef TIL_OPCODE_DEF

86 }

87 return self()->reduceNull();

88 }

89

90

91

92#define TIL_OPCODE_DEF(X) \

93 typename R::R_SExpr traverse##X(X *e, typename R::R_Ctx Ctx) { \

94 return e->traverse(*self(), Ctx); \

95 }

96#include "ThreadSafetyOps.def"

97#undef TIL_OPCODE_DEF

98};

99

100

102public:

104

106

107

109

110

112

113

116

117

118

119

121

122

124

125

126

128

129

130

132

133

135};

136

137

139public:

140

141

144

145

146

148 public:

149

151

152

154

156 };

157

159

160protected:

162};

163

164

166public:

167

170

171

173 public:

175

177

179 };

180};

181

182

183

184template

187public:

189

190public:

194

196 template

199

201 return Nvd && E0;

202 }

203

205 return Nvd && E0;

206 }

207

209 return E0 && E1;

210 }

211

213 return E0 && E1;

214 }

215

217 return E0 && E1;

218 }

219

221 return E0 && E1;

222 }

223

229

231 return E0 && E1;

232 }

233

235 return E0 && E1;

236 }

237

239

241 return E0 && E1;

242 }

243

245

248 }

249

253 }

254

257 }

258

260 return true;

261 }

262

264 return C;

265 }

266

268 return E;

269 }

270

272 return true;

273 }

274

276 return C && T && E;

277 }

278

280 return Nvd && B;

281 }

282

289

292

293public:

296 return Success;

297 }

298

300 Self Visitor;

302 }

303

304private:

305 bool Success;

306};

307

308

309template

311protected:

313

314public:

316 switch (E1->opcode()) {

317#define TIL_OPCODE_DEF(X) \

318 case COP_##X: \

319 return cast(E1)->compare(cast(E2), *self());

320#include "ThreadSafetyOps.def"

321#undef TIL_OPCODE_DEF

322 }

323 return false;

324 }

325};

326

328public:

329

330

331

333

336

340

343 return false;

345 }

346

347

350

352 return V1 == V2;

353 }

354

357 return Eq.compare(E1, E2);

358 }

359};

360

362public:

363

364

365

367

370

374

376

377 if (E1->opcode() == COP_Wildcard || E2->opcode() == COP_Wildcard)

378 return true;

379

381 return false;

383 }

384

385

388

390 return V1 == V2;

391 }

392

395 return Matcher.compare(E1, E2);

396 }

397};

398

399

400

401

402

403

404template <typename Self, typename StreamType>

406private:

407

408 bool Verbose;

409

410

411 bool Cleanup;

412

413

414 bool CStyle;

415

416public:

418 : Verbose(V), Cleanup(C), CStyle(CS) {}

419

421 Self printer;

422 printer.printSExpr(E, SS, Prec_MAX);

423 }

424

425protected:

427

429 SS << "\n";

430 }

431

432

440

441

443 switch (E->opcode()) {

444 case COP_Future: return Prec_Atom;

445 case COP_Undefined: return Prec_Atom;

446 case COP_Wildcard: return Prec_Atom;

447

448 case COP_Literal: return Prec_Atom;

449 case COP_LiteralPtr: return Prec_Atom;

450 case COP_Variable: return Prec_Atom;

451 case COP_Function: return Prec_Decl;

452 case COP_SFunction: return Prec_Decl;

454 case COP_Field: return Prec_Decl;

455

459

466

470

472 case COP_BasicBlock: return Prec_MAX;

475 case COP_Branch: return Prec_Atom;

477

478 case COP_Identifier: return Prec_Atom;

479 case COP_IfThenElse: return Prec_Other;

481 }

483 }

484

486 if (!BB) {

487 SS << "BB_null";

488 return;

489 }

490 SS << "BB_";

492 if (index >= 0) {

493 SS << ":";

494 SS << index;

495 }

496 }

497

499 if (E) {

500 self()->printNull(SS);

501 return;

502 }

503 if (Sub && E->block() && E->opcode() != COP_Variable) {

504 SS << "_x" << E->id();

505 return;

506 }

508

509 SS << "(";

511 SS << ")";

512 return;

513 }

514

515 switch (E->opcode()) {

516#define TIL_OPCODE_DEF(X) \

517 case COP_##X: \

518 self()->print##X(cast(E), SS); \

519 return;

520#include "ThreadSafetyOps.def"

521#undef TIL_OPCODE_DEF

522 }

523 }

524

526 SS << "#null";

527 }

528

530 self()->printSExpr(E->maybeGetResult(), SS, Prec_Atom);

531 }

532

534 SS << "#undefined";

535 }

536

538 SS << "*";

539 }

540

541 template

543 SS << E->value();

544 }

545

547 SS << "'" << E->value() << "'";

548 }

549

551 if (E->clangExpr()) {

553 return;

554 }

555 else {

557 switch (VT.Base) {

559 SS << "void";

560 return;

562 if (E->as<bool>().value())

563 SS << "true";

564 else

565 SS << "false";

566 return;

568 switch (VT.Size) {

572 else

574 return;

578 else

580 return;

584 else

586 return;

590 else

592 return;

593 default:

594 break;

595 }

596 break;

598 switch (VT.Size) {

601 return;

604 return;

605 default:

606 break;

607 }

608 break;

610 SS << "\"";

612 SS << "\"";

613 return;

615 SS << "#ptr";

616 return;

618 SS << "#vref";

619 return;

620 }

621 }

622 SS << "#lit";

623 }

624

627 SS << D->getNameAsString();

628 else

629 SS << "";

630 }

631

634 SS << "this";

635 else

636 SS << V->name() << V->id();

637 }

638

640 switch (sugared) {

641 default:

642 SS << "\\(";

643 break;

644 case 1:

645 SS << "(";

646 break;

647 case 2:

648 SS << ", ";

649 break;

650 }

651 self()->printVariable(E->variableDecl(), SS, true);

652 SS << ": ";

653 self()->printSExpr(E->variableDecl()->definition(), SS, Prec_MAX);

654

655 const SExpr *B = E->body();

656 if (B && B->opcode() == COP_Function)

657 self()->printFunction(cast(B), SS, 2);

658 else {

659 SS << ")";

661 }

662 }

663

665 SS << "@";

666 self()->printVariable(E->variableDecl(), SS, true);

667 SS << " ";

669 }

670

672 SS << ": ";

673 self()->printSExpr(E->returnType(), SS, Prec_Decl-1);

674 SS << " -> ";

676 }

677

679 SS << ": ";

681 SS << " = ";

683 }

684

686 const SExpr *F = E->fun();

687 if (F->opcode() == COP_Apply) {

688 printApply(cast(F), SS, true);

689 SS << ", ";

690 } else {

692 SS << "(";

693 }

695 if (!sugared)

696 SS << ")$";

697 }

698

701 if (E->isDelegation()) {

702 SS << "@(";

704 SS << ")";

705 }

706 }

707

709 if (CStyle) {

710

711 if (const auto *SAP = dyn_cast(E->record())) {

712 if (const auto *V = dyn_cast(SAP->sfun())) {

714 SS << E->slotName();

715 return;

716 }

717 }

718 }

719 if (isa(E->record())) {

720

721 SS << "&";

722 SS << E->clangDecl()->getQualifiedNameAsString();

723 return;

724 }

725 }

727 if (CStyle && E->isArrow())

728 SS << "->";

729 else

730 SS << ".";

731 SS << E->slotName();

732 }

733

735 const SExpr *T = E->target();

736 if (T->opcode() == COP_Apply) {

737 self()->printApply(cast(T), SS, true);

738 SS << ")";

739 }

740 else {

742 SS << "()";

743 }

744 }

745

747 SS << "new ";

749 }

750

753 if (!CStyle)

754 SS << "^";

755 }

756

759 SS << " := ";

761 }

762

765 SS << "[";

767 SS << "]";

768 }

769

772 SS << " + ";

774 }

775

779 }

780

785 }

786

788 if (!CStyle) {

789 SS << "cast[";

790 switch (E->castOpcode()) {

792 SS << "none";

793 break;

795 SS << "extendNum";

796 break;

798 SS << "truncNum";

799 break;

801 SS << "toFloat";

802 break;

804 SS << "toInt";

805 break;

807 SS << "objToPtr";

808 break;

809 }

810 SS << "](";

812 SS << ")";

813 return;

814 }

816 }

817

819 SS << "CFG {\n";

820 for (const auto *BBI : *E)

822 SS << "}";

824 }

825

827 bool Sub = false;

828 if (E->opcode() == COP_Variable) {

829 const auto *V = cast(E);

830 SS << "let " << V->name() << V->id() << " = ";

831 E = V->definition();

832 Sub = true;

833 }

834 else if (E->opcode() != COP_Store) {

835 SS << "let _x" << E->id() << " = ";

836 }

838 SS << ";";

840 }

841

843 SS << "BB_" << E->blockID() << ":";

844 if (E->parent())

845 SS << " BB_" << E->parent()->blockID();

847

848 for (const auto *A : E->arguments())

850

851 for (const auto *I : E->instructions())

853

854 const SExpr *T = E->terminator();

855 if (T) {

857 SS << ";";

859 }

861 }

862

864 SS << "phi(";

866 self()->printSExpr(E->values()[0], SS, Prec_MAX);

867 else {

868 unsigned i = 0;

869 for (const auto *V : E->values()) {

870 if (i++ > 0)

871 SS << ", ";

873 }

874 }

875 SS << ")";

876 }

877

879 SS << "goto ";

881 }

882

884 SS << "branch (";

885 self()->printSExpr(E->condition(), SS, Prec_MAX);

886 SS << ") ";

888 SS << " ";

890 }

891

893 SS << "return ";

895 }

896

898 SS << E->name();

899 }

900

902 if (CStyle) {

904 SS << " ? ";

906 SS << " : ";

908 return;

909 }

910 SS << "if (";

912 SS << ") then ";

914 SS << " else ";

916 }

917

919 SS << "let ";

921 SS << " = ";

923 SS << "; ";

925 }

926};

927

929

930}

931}

932}

933

934#endif

Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.

__device__ __2f16 float __ockl_bool s

This represents a decl that may have a name.

Allocate memory for a new value on the heap or stack.

Apply an argument to a function.

Pointer arithmetic, restricted to arrays only.

If p is a reference to an array, then p[i] is a reference to the i'th element of the array.

A basic block is part of an SCFG.

int blockID() const

Returns the block ID. Every block has a unique ID in the CFG.

Simple arithmetic binary operations, e.g.

A conditional branch to two other blocks.

Call a function (after all arguments have been applied).

A block of code – e.g. the body of a function.

bool compareByCase(const SExpr *E1, const SExpr *E2)

Container(CopyReducerBase &S, unsigned N)

CopyReducerBase(MemRegionRef A)

bool compare(const SExpr *E1, const SExpr *E2)

bool comparePointers(const void *P, const void *Q)

bool compareStrings(StringRef s, StringRef r)

void enterScope(const Variable *V1, const Variable *V2)

bool compareVariableRefs(const Variable *V1, const Variable *V2)

static bool compareExprs(const SExpr *E1, const SExpr *E2)

bool compareIntegers(unsigned i, unsigned j)

A typed, writable location in memory.

Placeholder for an expression that has not yet been created.

Jump to another basic block.

An if-then-else expression.

A Literal pointer to an object allocated in memory.

Load a value from memory.

bool compareVariableRefs(const Variable *V1, const Variable *V2)

bool comparePointers(const void *P, const void *Q)

static bool compareExprs(const SExpr *E1, const SExpr *E2)

bool compare(const SExpr *E1, const SExpr *E2)

bool compareIntegers(unsigned i, unsigned j)

bool compareStrings(StringRef s, StringRef r)

void enterScope(const Variable *V1, const Variable *V2)

Phi Node, for code in SSA form.

static const unsigned Prec_MAX

void printFuture(const Future *E, StreamType &SS)

void printCall(const Call *E, StreamType &SS)

void printLiteralT(const LiteralT< uint8_t > *E, StreamType &SS)

void printApply(const Apply *E, StreamType &SS, bool sugared=false)

void printProject(const Project *E, StreamType &SS)

void printWildcard(const Wildcard *E, StreamType &SS)

void printBranch(const Branch *E, StreamType &SS)

void printLet(const Let *E, StreamType &SS)

void printLiteral(const Literal *E, StreamType &SS)

void printField(const Field *E, StreamType &SS)

void printUnaryOp(const UnaryOp *E, StreamType &SS)

void printUndefined(const Undefined *E, StreamType &SS)

void printIdentifier(const Identifier *E, StreamType &SS)

static void print(const SExpr *E, StreamType &SS)

void printReturn(const Return *E, StreamType &SS)

void printVariable(const Variable *V, StreamType &SS, bool IsVarDecl=false)

static const unsigned Prec_Unary

void printCode(const Code *E, StreamType &SS)

void printStore(const Store *E, StreamType &SS)

static const unsigned Prec_Binary

static const unsigned Prec_Atom

void printCast(const Cast *E, StreamType &SS)

void printIfThenElse(const IfThenElse *E, StreamType &SS)

void printBasicBlock(const BasicBlock *E, StreamType &SS)

void printLiteralPtr(const LiteralPtr *E, StreamType &SS)

void newline(StreamType &SS)

void printGoto(const Goto *E, StreamType &SS)

void printBBInstr(const SExpr *E, StreamType &SS)

void printAlloc(const Alloc *E, StreamType &SS)

void printNull(StreamType &SS)

void printPhi(const Phi *E, StreamType &SS)

void printSCFG(const SCFG *E, StreamType &SS)

static const unsigned Prec_Decl

unsigned precedence(const SExpr *E)

static const unsigned Prec_Postfix

void printFunction(const Function *E, StreamType &SS, unsigned sugared=0)

void printBinaryOp(const BinaryOp *E, StreamType &SS)

void printArrayAdd(const ArrayAdd *E, StreamType &SS)

static const unsigned Prec_Other

void printSFunction(const SFunction *E, StreamType &SS)

void printArrayIndex(const ArrayIndex *E, StreamType &SS)

void printSApply(const SApply *E, StreamType &SS)

void printLoad(const Load *E, StreamType &SS)

void printLiteralT(const LiteralT< T > *E, StreamType &SS)

PrettyPrinter(bool V=false, bool C=true, bool CS=true)

void printBlockLabel(StreamType &SS, const BasicBlock *BB, int index)

void printSExpr(const SExpr *E, StreamType &SS, unsigned P, bool Sub=true)

Project a named slot from a C++ struct or class.

Return from the enclosing function, passing the return value to the caller.

Apply a self-argument to a self-applicable function.

An SCFG is a control-flow graph.

Base class for AST nodes in the typed intermediate language.

TIL_Opcode opcode() const

A self-applicable function.

R_Ctx subExprCtx(R_Ctx Ctx)

R::R_SExpr traverse(T *&E, typename R::R_Ctx Ctx)

R::R_SExpr traverseSExpr(SExpr *E, typename R::R_Ctx Ctx)

R::R_SExpr traverseByCase(SExpr *E, typename R::R_Ctx Ctx)

Simple arithmetic unary operations, e.g.

Placeholder for expressions that cannot be represented in the TIL.

@ VK_SFun

SFunction (self) parameter.

Container(VisitReducerBase &S, unsigned N)

Variable * enterScope(Variable &Orig, R_SExpr E0)

R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1)

R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1)

R_SExpr reduceProject(Project &Orig, R_SExpr E0)

R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B)

R_SExpr reduceArrayAdd(Store &Orig, R_SExpr E0, R_SExpr E1)

R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0)

void exitScope(const Variable &Orig)

void exitBasicBlock(BasicBlock &BB)

R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0)

R_SExpr reduceIdentifier(Identifier &Orig)

R_SExpr reduceLiteral(Literal &Orig)

R_SExpr reduceSCFG(SCFG &Orig, Container< BasicBlock * > Bbs)

R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1)

R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container< R_SExpr > &As, Container< R_SExpr > &Is, R_SExpr T)

BasicBlock * reduceBasicBlockRef(BasicBlock *Obb)

R_SExpr reduceGoto(Goto &Orig, BasicBlock *B)

R_SExpr reduceUndefined(Undefined &Orig)

bool traverse(SExpr *E, TraversalKind K=TRV_Normal)

R_SExpr reduceWildcard(Wildcard &Orig)

R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1)

R_SExpr reducePhi(Phi &Orig, Container< R_SExpr > &As)

R_SExpr reduceLoad(Load &Orig, R_SExpr E0)

R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1)

R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0)

Variable * reduceVariableRef(Variable *Ovd)

R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1)

R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0)

R_SExpr reduceLiteralT(LiteralT< T > &Orig)

R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1)

void enterBasicBlock(BasicBlock &BB)

R_SExpr reduceReturn(Return &O, R_SExpr E)

R_SExpr reduceCast(Cast &Orig, R_SExpr E0)

R_SExpr reduceCall(Call &Orig, R_SExpr E0)

R_SExpr reduceArrayIndex(Store &Orig, R_SExpr E0, R_SExpr E1)

static bool visit(SExpr *E)

R_SExpr reduceLiteralPtr(Literal &Orig)

R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E)

Placeholder for a wildcard that matches any other expression.

StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op)

Return the name of a binary opcode.

StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op)

Return the name of a unary opcode.

std::string getSourceLiteralString(const Expr *CE)

The JSON file list parser is used to communicate input to InstallAPI.

@ Self

'self' clause, allowed on Compute and Combined Constructs, plus 'update'.

const FunctionProtoType * T

ValueTypes are data types that can actually be held in registers.