File indexing completed on 2026-05-10 08:36:24
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
0017 #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
0018
0019 #include "clang/AST/Decl.h"
0020 #include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
0021 #include "clang/Analysis/Analyses/ThreadSafetyUtil.h"
0022 #include "clang/Basic/LLVM.h"
0023 #include "llvm/ADT/StringRef.h"
0024 #include "llvm/Support/Casting.h"
0025 #include <cstdint>
0026 #include <ostream>
0027
0028 namespace clang {
0029 namespace threadSafety {
0030 namespace til {
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057 template <class Self, class R>
0058 class Traversal {
0059 public:
0060 Self *self() { return static_cast<Self *>(this); }
0061
0062
0063
0064
0065
0066
0067 template <class T>
0068 typename R::R_SExpr traverse(T* &E, typename R::R_Ctx Ctx) {
0069 return traverseSExpr(E, Ctx);
0070 }
0071
0072
0073
0074 typename R::R_SExpr traverseSExpr(SExpr *E, typename R::R_Ctx Ctx) {
0075 return traverseByCase(E, Ctx);
0076 }
0077
0078
0079 typename R::R_SExpr traverseByCase(SExpr *E, typename R::R_Ctx Ctx) {
0080 switch (E->opcode()) {
0081 #define TIL_OPCODE_DEF(X) \
0082 case COP_##X: \
0083 return self()->traverse##X(cast<X>(E), Ctx);
0084 #include "ThreadSafetyOps.def"
0085 #undef TIL_OPCODE_DEF
0086 }
0087 return self()->reduceNull();
0088 }
0089
0090
0091
0092 #define TIL_OPCODE_DEF(X) \
0093 typename R::R_SExpr traverse##X(X *e, typename R::R_Ctx Ctx) { \
0094 return e->traverse(*self(), Ctx); \
0095 }
0096 #include "ThreadSafetyOps.def"
0097 #undef TIL_OPCODE_DEF
0098 };
0099
0100
0101 class SimpleReducerBase {
0102 public:
0103 enum TraversalKind {
0104
0105 TRV_Normal,
0106
0107
0108 TRV_Decl,
0109
0110
0111 TRV_Lazy,
0112
0113
0114 TRV_Type
0115 };
0116
0117
0118
0119
0120 using R_Ctx = TraversalKind;
0121
0122
0123 R_Ctx subExprCtx(R_Ctx Ctx) { return TRV_Normal; }
0124
0125
0126
0127 R_Ctx declCtx(R_Ctx Ctx) { return TRV_Decl; }
0128
0129
0130
0131 R_Ctx lazyCtx(R_Ctx Ctx) { return TRV_Lazy; }
0132
0133
0134 R_Ctx typeCtx(R_Ctx Ctx) { return TRV_Type; }
0135 };
0136
0137
0138 class CopyReducerBase : public SimpleReducerBase {
0139 public:
0140
0141
0142 using R_SExpr = SExpr *;
0143 using R_BasicBlock = BasicBlock *;
0144
0145
0146
0147 template <class T> class Container {
0148 public:
0149
0150 Container(CopyReducerBase &S, unsigned N) : Elems(S.Arena, N) {}
0151
0152
0153 void push_back(T E) { Elems.push_back(E); }
0154
0155 SimpleArray<T> Elems;
0156 };
0157
0158 CopyReducerBase(MemRegionRef A) : Arena(A) {}
0159
0160 protected:
0161 MemRegionRef Arena;
0162 };
0163
0164
0165 class VisitReducerBase : public SimpleReducerBase {
0166 public:
0167
0168 using R_SExpr = bool;
0169 using R_BasicBlock = bool;
0170
0171
0172 template <class T> class Container {
0173 public:
0174 bool Success = true;
0175
0176 Container(VisitReducerBase &S, unsigned N) {}
0177
0178 void push_back(bool E) { Success = Success && E; }
0179 };
0180 };
0181
0182
0183
0184 template <class Self>
0185 class VisitReducer : public Traversal<Self, VisitReducerBase>,
0186 public VisitReducerBase {
0187 public:
0188 VisitReducer() = default;
0189
0190 public:
0191 R_SExpr reduceNull() { return true; }
0192 R_SExpr reduceUndefined(Undefined &Orig) { return true; }
0193 R_SExpr reduceWildcard(Wildcard &Orig) { return true; }
0194
0195 R_SExpr reduceLiteral(Literal &Orig) { return true; }
0196 template<class T>
0197 R_SExpr reduceLiteralT(LiteralT<T> &Orig) { return true; }
0198 R_SExpr reduceLiteralPtr(Literal &Orig) { return true; }
0199
0200 R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) {
0201 return Nvd && E0;
0202 }
0203
0204 R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) {
0205 return Nvd && E0;
0206 }
0207
0208 R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) {
0209 return E0 && E1;
0210 }
0211
0212 R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) {
0213 return E0 && E1;
0214 }
0215
0216 R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) {
0217 return E0 && E1;
0218 }
0219
0220 R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) {
0221 return E0 && E1;
0222 }
0223
0224 R_SExpr reduceProject(Project &Orig, R_SExpr E0) { return E0; }
0225 R_SExpr reduceCall(Call &Orig, R_SExpr E0) { return E0; }
0226 R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { return E0; }
0227 R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { return E0; }
0228 R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; }
0229
0230 R_SExpr reduceArrayIndex(Store &Orig, R_SExpr E0, R_SExpr E1) {
0231 return E0 && E1;
0232 }
0233
0234 R_SExpr reduceArrayAdd(Store &Orig, R_SExpr E0, R_SExpr E1) {
0235 return E0 && E1;
0236 }
0237
0238 R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { return E0; }
0239
0240 R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
0241 return E0 && E1;
0242 }
0243
0244 R_SExpr reduceCast(Cast &Orig, R_SExpr E0) { return E0; }
0245
0246 R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> Bbs) {
0247 return Bbs.Success;
0248 }
0249
0250 R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<R_SExpr> &As,
0251 Container<R_SExpr> &Is, R_SExpr T) {
0252 return (As.Success && Is.Success && T);
0253 }
0254
0255 R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) {
0256 return As.Success;
0257 }
0258
0259 R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) {
0260 return true;
0261 }
0262
0263 R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
0264 return C;
0265 }
0266
0267 R_SExpr reduceReturn(Return &O, R_SExpr E) {
0268 return E;
0269 }
0270
0271 R_SExpr reduceIdentifier(Identifier &Orig) {
0272 return true;
0273 }
0274
0275 R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) {
0276 return C && T && E;
0277 }
0278
0279 R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) {
0280 return Nvd && B;
0281 }
0282
0283 Variable *enterScope(Variable &Orig, R_SExpr E0) { return &Orig; }
0284 void exitScope(const Variable &Orig) {}
0285 void enterCFG(SCFG &Cfg) {}
0286 void exitCFG(SCFG &Cfg) {}
0287 void enterBasicBlock(BasicBlock &BB) {}
0288 void exitBasicBlock(BasicBlock &BB) {}
0289
0290 Variable *reduceVariableRef(Variable *Ovd) { return Ovd; }
0291 BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; }
0292
0293 public:
0294 bool traverse(SExpr *E, TraversalKind K = TRV_Normal) {
0295 Success = Success && this->traverseByCase(E);
0296 return Success;
0297 }
0298
0299 static bool visit(SExpr *E) {
0300 Self Visitor;
0301 return Visitor.traverse(E, TRV_Normal);
0302 }
0303
0304 private:
0305 bool Success;
0306 };
0307
0308
0309 template <typename Self>
0310 class Comparator {
0311 protected:
0312 Self *self() { return reinterpret_cast<Self *>(this); }
0313
0314 public:
0315 bool compareByCase(const SExpr *E1, const SExpr* E2) {
0316 switch (E1->opcode()) {
0317 #define TIL_OPCODE_DEF(X) \
0318 case COP_##X: \
0319 return cast<X>(E1)->compare(cast<X>(E2), *self());
0320 #include "ThreadSafetyOps.def"
0321 #undef TIL_OPCODE_DEF
0322 }
0323 return false;
0324 }
0325 };
0326
0327 class EqualsComparator : public Comparator<EqualsComparator> {
0328 public:
0329
0330
0331
0332 using CType = bool;
0333
0334 CType trueResult() { return true; }
0335 bool notTrue(CType ct) { return !ct; }
0336
0337 bool compareIntegers(unsigned i, unsigned j) { return i == j; }
0338 bool compareStrings (StringRef s, StringRef r) { return s == r; }
0339 bool comparePointers(const void* P, const void* Q) { return P == Q; }
0340
0341 bool compare(const SExpr *E1, const SExpr* E2) {
0342 if (E1->opcode() != E2->opcode())
0343 return false;
0344 return compareByCase(E1, E2);
0345 }
0346
0347
0348 void enterScope(const Variable *V1, const Variable *V2) {}
0349 void leaveScope() {}
0350
0351 bool compareVariableRefs(const Variable *V1, const Variable *V2) {
0352 return V1 == V2;
0353 }
0354
0355 static bool compareExprs(const SExpr *E1, const SExpr* E2) {
0356 EqualsComparator Eq;
0357 return Eq.compare(E1, E2);
0358 }
0359 };
0360
0361 class MatchComparator : public Comparator<MatchComparator> {
0362 public:
0363
0364
0365
0366 using CType = bool;
0367
0368 CType trueResult() { return true; }
0369 bool notTrue(CType ct) { return !ct; }
0370
0371 bool compareIntegers(unsigned i, unsigned j) { return i == j; }
0372 bool compareStrings (StringRef s, StringRef r) { return s == r; }
0373 bool comparePointers(const void *P, const void *Q) { return P == Q; }
0374
0375 bool compare(const SExpr *E1, const SExpr *E2) {
0376
0377 if (E1->opcode() == COP_Wildcard || E2->opcode() == COP_Wildcard)
0378 return true;
0379
0380 if (E1->opcode() != E2->opcode())
0381 return false;
0382 return compareByCase(E1, E2);
0383 }
0384
0385
0386 void enterScope(const Variable* V1, const Variable* V2) {}
0387 void leaveScope() {}
0388
0389 bool compareVariableRefs(const Variable* V1, const Variable* V2) {
0390 return V1 == V2;
0391 }
0392
0393 static bool compareExprs(const SExpr *E1, const SExpr* E2) {
0394 MatchComparator Matcher;
0395 return Matcher.compare(E1, E2);
0396 }
0397 };
0398
0399
0400
0401
0402
0403
0404 template <typename Self, typename StreamType>
0405 class PrettyPrinter {
0406 private:
0407
0408 bool Verbose;
0409
0410
0411 bool Cleanup;
0412
0413
0414 bool CStyle;
0415
0416 public:
0417 PrettyPrinter(bool V = false, bool C = true, bool CS = true)
0418 : Verbose(V), Cleanup(C), CStyle(CS) {}
0419
0420 static void print(const SExpr *E, StreamType &SS) {
0421 Self printer;
0422 printer.printSExpr(E, SS, Prec_MAX);
0423 }
0424
0425 protected:
0426 Self *self() { return reinterpret_cast<Self *>(this); }
0427
0428 void newline(StreamType &SS) {
0429 SS << "\n";
0430 }
0431
0432
0433 static const unsigned Prec_Atom = 0;
0434 static const unsigned Prec_Postfix = 1;
0435 static const unsigned Prec_Unary = 2;
0436 static const unsigned Prec_Binary = 3;
0437 static const unsigned Prec_Other = 4;
0438 static const unsigned Prec_Decl = 5;
0439 static const unsigned Prec_MAX = 6;
0440
0441
0442 unsigned precedence(const SExpr *E) {
0443 switch (E->opcode()) {
0444 case COP_Future: return Prec_Atom;
0445 case COP_Undefined: return Prec_Atom;
0446 case COP_Wildcard: return Prec_Atom;
0447
0448 case COP_Literal: return Prec_Atom;
0449 case COP_LiteralPtr: return Prec_Atom;
0450 case COP_Variable: return Prec_Atom;
0451 case COP_Function: return Prec_Decl;
0452 case COP_SFunction: return Prec_Decl;
0453 case COP_Code: return Prec_Decl;
0454 case COP_Field: return Prec_Decl;
0455
0456 case COP_Apply: return Prec_Postfix;
0457 case COP_SApply: return Prec_Postfix;
0458 case COP_Project: return Prec_Postfix;
0459
0460 case COP_Call: return Prec_Postfix;
0461 case COP_Alloc: return Prec_Other;
0462 case COP_Load: return Prec_Postfix;
0463 case COP_Store: return Prec_Other;
0464 case COP_ArrayIndex: return Prec_Postfix;
0465 case COP_ArrayAdd: return Prec_Postfix;
0466
0467 case COP_UnaryOp: return Prec_Unary;
0468 case COP_BinaryOp: return Prec_Binary;
0469 case COP_Cast: return Prec_Atom;
0470
0471 case COP_SCFG: return Prec_Decl;
0472 case COP_BasicBlock: return Prec_MAX;
0473 case COP_Phi: return Prec_Atom;
0474 case COP_Goto: return Prec_Atom;
0475 case COP_Branch: return Prec_Atom;
0476 case COP_Return: return Prec_Other;
0477
0478 case COP_Identifier: return Prec_Atom;
0479 case COP_IfThenElse: return Prec_Other;
0480 case COP_Let: return Prec_Decl;
0481 }
0482 return Prec_MAX;
0483 }
0484
0485 void printBlockLabel(StreamType & SS, const BasicBlock *BB, int index) {
0486 if (!BB) {
0487 SS << "BB_null";
0488 return;
0489 }
0490 SS << "BB_";
0491 SS << BB->blockID();
0492 if (index >= 0) {
0493 SS << ":";
0494 SS << index;
0495 }
0496 }
0497
0498 void printSExpr(const SExpr *E, StreamType &SS, unsigned P, bool Sub=true) {
0499 if (!E) {
0500 self()->printNull(SS);
0501 return;
0502 }
0503 if (Sub && E->block() && E->opcode() != COP_Variable) {
0504 SS << "_x" << E->id();
0505 return;
0506 }
0507 if (self()->precedence(E) > P) {
0508
0509 SS << "(";
0510 self()->printSExpr(E, SS, Prec_MAX);
0511 SS << ")";
0512 return;
0513 }
0514
0515 switch (E->opcode()) {
0516 #define TIL_OPCODE_DEF(X) \
0517 case COP_##X: \
0518 self()->print##X(cast<X>(E), SS); \
0519 return;
0520 #include "ThreadSafetyOps.def"
0521 #undef TIL_OPCODE_DEF
0522 }
0523 }
0524
0525 void printNull(StreamType &SS) {
0526 SS << "#null";
0527 }
0528
0529 void printFuture(const Future *E, StreamType &SS) {
0530 self()->printSExpr(E->maybeGetResult(), SS, Prec_Atom);
0531 }
0532
0533 void printUndefined(const Undefined *E, StreamType &SS) {
0534 SS << "#undefined";
0535 }
0536
0537 void printWildcard(const Wildcard *E, StreamType &SS) {
0538 SS << "*";
0539 }
0540
0541 template<class T>
0542 void printLiteralT(const LiteralT<T> *E, StreamType &SS) {
0543 SS << E->value();
0544 }
0545
0546 void printLiteralT(const LiteralT<uint8_t> *E, StreamType &SS) {
0547 SS << "'" << E->value() << "'";
0548 }
0549
0550 void printLiteral(const Literal *E, StreamType &SS) {
0551 if (E->clangExpr()) {
0552 SS << getSourceLiteralString(E->clangExpr());
0553 return;
0554 }
0555 else {
0556 ValueType VT = E->valueType();
0557 switch (VT.Base) {
0558 case ValueType::BT_Void:
0559 SS << "void";
0560 return;
0561 case ValueType::BT_Bool:
0562 if (E->as<bool>().value())
0563 SS << "true";
0564 else
0565 SS << "false";
0566 return;
0567 case ValueType::BT_Int:
0568 switch (VT.Size) {
0569 case ValueType::ST_8:
0570 if (VT.Signed)
0571 printLiteralT(&E->as<int8_t>(), SS);
0572 else
0573 printLiteralT(&E->as<uint8_t>(), SS);
0574 return;
0575 case ValueType::ST_16:
0576 if (VT.Signed)
0577 printLiteralT(&E->as<int16_t>(), SS);
0578 else
0579 printLiteralT(&E->as<uint16_t>(), SS);
0580 return;
0581 case ValueType::ST_32:
0582 if (VT.Signed)
0583 printLiteralT(&E->as<int32_t>(), SS);
0584 else
0585 printLiteralT(&E->as<uint32_t>(), SS);
0586 return;
0587 case ValueType::ST_64:
0588 if (VT.Signed)
0589 printLiteralT(&E->as<int64_t>(), SS);
0590 else
0591 printLiteralT(&E->as<uint64_t>(), SS);
0592 return;
0593 default:
0594 break;
0595 }
0596 break;
0597 case ValueType::BT_Float:
0598 switch (VT.Size) {
0599 case ValueType::ST_32:
0600 printLiteralT(&E->as<float>(), SS);
0601 return;
0602 case ValueType::ST_64:
0603 printLiteralT(&E->as<double>(), SS);
0604 return;
0605 default:
0606 break;
0607 }
0608 break;
0609 case ValueType::BT_String:
0610 SS << "\"";
0611 printLiteralT(&E->as<StringRef>(), SS);
0612 SS << "\"";
0613 return;
0614 case ValueType::BT_Pointer:
0615 SS << "#ptr";
0616 return;
0617 case ValueType::BT_ValueRef:
0618 SS << "#vref";
0619 return;
0620 }
0621 }
0622 SS << "#lit";
0623 }
0624
0625 void printLiteralPtr(const LiteralPtr *E, StreamType &SS) {
0626 if (const NamedDecl *D = E->clangDecl())
0627 SS << D->getNameAsString();
0628 else
0629 SS << "<temporary>";
0630 }
0631
0632 void printVariable(const Variable *V, StreamType &SS, bool IsVarDecl=false) {
0633 if (CStyle && V->kind() == Variable::VK_SFun)
0634 SS << "this";
0635 else
0636 SS << V->name() << V->id();
0637 }
0638
0639 void printFunction(const Function *E, StreamType &SS, unsigned sugared = 0) {
0640 switch (sugared) {
0641 default:
0642 SS << "\\(";
0643 break;
0644 case 1:
0645 SS << "(";
0646 break;
0647 case 2:
0648 SS << ", ";
0649 break;
0650 }
0651 self()->printVariable(E->variableDecl(), SS, true);
0652 SS << ": ";
0653 self()->printSExpr(E->variableDecl()->definition(), SS, Prec_MAX);
0654
0655 const SExpr *B = E->body();
0656 if (B && B->opcode() == COP_Function)
0657 self()->printFunction(cast<Function>(B), SS, 2);
0658 else {
0659 SS << ")";
0660 self()->printSExpr(B, SS, Prec_Decl);
0661 }
0662 }
0663
0664 void printSFunction(const SFunction *E, StreamType &SS) {
0665 SS << "@";
0666 self()->printVariable(E->variableDecl(), SS, true);
0667 SS << " ";
0668 self()->printSExpr(E->body(), SS, Prec_Decl);
0669 }
0670
0671 void printCode(const Code *E, StreamType &SS) {
0672 SS << ": ";
0673 self()->printSExpr(E->returnType(), SS, Prec_Decl-1);
0674 SS << " -> ";
0675 self()->printSExpr(E->body(), SS, Prec_Decl);
0676 }
0677
0678 void printField(const Field *E, StreamType &SS) {
0679 SS << ": ";
0680 self()->printSExpr(E->range(), SS, Prec_Decl-1);
0681 SS << " = ";
0682 self()->printSExpr(E->body(), SS, Prec_Decl);
0683 }
0684
0685 void printApply(const Apply *E, StreamType &SS, bool sugared = false) {
0686 const SExpr *F = E->fun();
0687 if (F->opcode() == COP_Apply) {
0688 printApply(cast<Apply>(F), SS, true);
0689 SS << ", ";
0690 } else {
0691 self()->printSExpr(F, SS, Prec_Postfix);
0692 SS << "(";
0693 }
0694 self()->printSExpr(E->arg(), SS, Prec_MAX);
0695 if (!sugared)
0696 SS << ")$";
0697 }
0698
0699 void printSApply(const SApply *E, StreamType &SS) {
0700 self()->printSExpr(E->sfun(), SS, Prec_Postfix);
0701 if (E->isDelegation()) {
0702 SS << "@(";
0703 self()->printSExpr(E->arg(), SS, Prec_MAX);
0704 SS << ")";
0705 }
0706 }
0707
0708 void printProject(const Project *E, StreamType &SS) {
0709 if (CStyle) {
0710
0711 if (const auto *SAP = dyn_cast<SApply>(E->record())) {
0712 if (const auto *V = dyn_cast<Variable>(SAP->sfun())) {
0713 if (!SAP->isDelegation() && V->kind() == Variable::VK_SFun) {
0714 SS << E->slotName();
0715 return;
0716 }
0717 }
0718 }
0719 if (isa<Wildcard>(E->record())) {
0720
0721 SS << "&";
0722 SS << E->clangDecl()->getQualifiedNameAsString();
0723 return;
0724 }
0725 }
0726 self()->printSExpr(E->record(), SS, Prec_Postfix);
0727 if (CStyle && E->isArrow())
0728 SS << "->";
0729 else
0730 SS << ".";
0731 SS << E->slotName();
0732 }
0733
0734 void printCall(const Call *E, StreamType &SS) {
0735 const SExpr *T = E->target();
0736 if (T->opcode() == COP_Apply) {
0737 self()->printApply(cast<Apply>(T), SS, true);
0738 SS << ")";
0739 }
0740 else {
0741 self()->printSExpr(T, SS, Prec_Postfix);
0742 SS << "()";
0743 }
0744 }
0745
0746 void printAlloc(const Alloc *E, StreamType &SS) {
0747 SS << "new ";
0748 self()->printSExpr(E->dataType(), SS, Prec_Other-1);
0749 }
0750
0751 void printLoad(const Load *E, StreamType &SS) {
0752 self()->printSExpr(E->pointer(), SS, Prec_Postfix);
0753 if (!CStyle)
0754 SS << "^";
0755 }
0756
0757 void printStore(const Store *E, StreamType &SS) {
0758 self()->printSExpr(E->destination(), SS, Prec_Other-1);
0759 SS << " := ";
0760 self()->printSExpr(E->source(), SS, Prec_Other-1);
0761 }
0762
0763 void printArrayIndex(const ArrayIndex *E, StreamType &SS) {
0764 self()->printSExpr(E->array(), SS, Prec_Postfix);
0765 SS << "[";
0766 self()->printSExpr(E->index(), SS, Prec_MAX);
0767 SS << "]";
0768 }
0769
0770 void printArrayAdd(const ArrayAdd *E, StreamType &SS) {
0771 self()->printSExpr(E->array(), SS, Prec_Postfix);
0772 SS << " + ";
0773 self()->printSExpr(E->index(), SS, Prec_Atom);
0774 }
0775
0776 void printUnaryOp(const UnaryOp *E, StreamType &SS) {
0777 SS << getUnaryOpcodeString(E->unaryOpcode());
0778 self()->printSExpr(E->expr(), SS, Prec_Unary);
0779 }
0780
0781 void printBinaryOp(const BinaryOp *E, StreamType &SS) {
0782 self()->printSExpr(E->expr0(), SS, Prec_Binary-1);
0783 SS << " " << getBinaryOpcodeString(E->binaryOpcode()) << " ";
0784 self()->printSExpr(E->expr1(), SS, Prec_Binary-1);
0785 }
0786
0787 void printCast(const Cast *E, StreamType &SS) {
0788 if (!CStyle) {
0789 SS << "cast[";
0790 switch (E->castOpcode()) {
0791 case CAST_none:
0792 SS << "none";
0793 break;
0794 case CAST_extendNum:
0795 SS << "extendNum";
0796 break;
0797 case CAST_truncNum:
0798 SS << "truncNum";
0799 break;
0800 case CAST_toFloat:
0801 SS << "toFloat";
0802 break;
0803 case CAST_toInt:
0804 SS << "toInt";
0805 break;
0806 case CAST_objToPtr:
0807 SS << "objToPtr";
0808 break;
0809 }
0810 SS << "](";
0811 self()->printSExpr(E->expr(), SS, Prec_Unary);
0812 SS << ")";
0813 return;
0814 }
0815 self()->printSExpr(E->expr(), SS, Prec_Unary);
0816 }
0817
0818 void printSCFG(const SCFG *E, StreamType &SS) {
0819 SS << "CFG {\n";
0820 for (const auto *BBI : *E)
0821 printBasicBlock(BBI, SS);
0822 SS << "}";
0823 newline(SS);
0824 }
0825
0826 void printBBInstr(const SExpr *E, StreamType &SS) {
0827 bool Sub = false;
0828 if (E->opcode() == COP_Variable) {
0829 const auto *V = cast<Variable>(E);
0830 SS << "let " << V->name() << V->id() << " = ";
0831 E = V->definition();
0832 Sub = true;
0833 }
0834 else if (E->opcode() != COP_Store) {
0835 SS << "let _x" << E->id() << " = ";
0836 }
0837 self()->printSExpr(E, SS, Prec_MAX, Sub);
0838 SS << ";";
0839 newline(SS);
0840 }
0841
0842 void printBasicBlock(const BasicBlock *E, StreamType &SS) {
0843 SS << "BB_" << E->blockID() << ":";
0844 if (E->parent())
0845 SS << " BB_" << E->parent()->blockID();
0846 newline(SS);
0847
0848 for (const auto *A : E->arguments())
0849 printBBInstr(A, SS);
0850
0851 for (const auto *I : E->instructions())
0852 printBBInstr(I, SS);
0853
0854 const SExpr *T = E->terminator();
0855 if (T) {
0856 self()->printSExpr(T, SS, Prec_MAX, false);
0857 SS << ";";
0858 newline(SS);
0859 }
0860 newline(SS);
0861 }
0862
0863 void printPhi(const Phi *E, StreamType &SS) {
0864 SS << "phi(";
0865 if (E->status() == Phi::PH_SingleVal)
0866 self()->printSExpr(E->values()[0], SS, Prec_MAX);
0867 else {
0868 unsigned i = 0;
0869 for (const auto *V : E->values()) {
0870 if (i++ > 0)
0871 SS << ", ";
0872 self()->printSExpr(V, SS, Prec_MAX);
0873 }
0874 }
0875 SS << ")";
0876 }
0877
0878 void printGoto(const Goto *E, StreamType &SS) {
0879 SS << "goto ";
0880 printBlockLabel(SS, E->targetBlock(), E->index());
0881 }
0882
0883 void printBranch(const Branch *E, StreamType &SS) {
0884 SS << "branch (";
0885 self()->printSExpr(E->condition(), SS, Prec_MAX);
0886 SS << ") ";
0887 printBlockLabel(SS, E->thenBlock(), -1);
0888 SS << " ";
0889 printBlockLabel(SS, E->elseBlock(), -1);
0890 }
0891
0892 void printReturn(const Return *E, StreamType &SS) {
0893 SS << "return ";
0894 self()->printSExpr(E->returnValue(), SS, Prec_Other);
0895 }
0896
0897 void printIdentifier(const Identifier *E, StreamType &SS) {
0898 SS << E->name();
0899 }
0900
0901 void printIfThenElse(const IfThenElse *E, StreamType &SS) {
0902 if (CStyle) {
0903 printSExpr(E->condition(), SS, Prec_Unary);
0904 SS << " ? ";
0905 printSExpr(E->thenExpr(), SS, Prec_Unary);
0906 SS << " : ";
0907 printSExpr(E->elseExpr(), SS, Prec_Unary);
0908 return;
0909 }
0910 SS << "if (";
0911 printSExpr(E->condition(), SS, Prec_MAX);
0912 SS << ") then ";
0913 printSExpr(E->thenExpr(), SS, Prec_Other);
0914 SS << " else ";
0915 printSExpr(E->elseExpr(), SS, Prec_Other);
0916 }
0917
0918 void printLet(const Let *E, StreamType &SS) {
0919 SS << "let ";
0920 printVariable(E->variableDecl(), SS, true);
0921 SS << " = ";
0922 printSExpr(E->variableDecl()->definition(), SS, Prec_Decl-1);
0923 SS << "; ";
0924 printSExpr(E->body(), SS, Prec_Decl-1);
0925 }
0926 };
0927
0928 class StdPrinter : public PrettyPrinter<StdPrinter, std::ostream> {};
0929
0930 }
0931 }
0932 }
0933
0934 #endif