CGCleanup.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. //===-- CGCleanup.h - Classes for cleanups IR generation --------*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // These classes support the generation of LLVM IR for cleanups.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef CLANG_CODEGEN_CGCLEANUP_H
  14. #define CLANG_CODEGEN_CGCLEANUP_H
  15. /// EHScopeStack is defined in CodeGenFunction.h, but its
  16. /// implementation is in this file and in CGCleanup.cpp.
  17. #include "CodeGenFunction.h"
  18. namespace llvm {
  19. class Value;
  20. class BasicBlock;
  21. }
  22. namespace clang {
  23. namespace CodeGen {
  24. /// A protected scope for zero-cost EH handling.
  25. class EHScope {
  26. llvm::BasicBlock *CachedLandingPad;
  27. llvm::BasicBlock *CachedEHDispatchBlock;
  28. EHScopeStack::stable_iterator EnclosingEHScope;
  29. class CommonBitFields {
  30. friend class EHScope;
  31. unsigned Kind : 2;
  32. };
  33. enum { NumCommonBits = 2 };
  34. protected:
  35. class CatchBitFields {
  36. friend class EHCatchScope;
  37. unsigned : NumCommonBits;
  38. unsigned NumHandlers : 32 - NumCommonBits;
  39. };
  40. class CleanupBitFields {
  41. friend class EHCleanupScope;
  42. unsigned : NumCommonBits;
  43. /// Whether this cleanup needs to be run along normal edges.
  44. unsigned IsNormalCleanup : 1;
  45. /// Whether this cleanup needs to be run along exception edges.
  46. unsigned IsEHCleanup : 1;
  47. /// Whether this cleanup is currently active.
  48. unsigned IsActive : 1;
  49. /// Whether the normal cleanup should test the activation flag.
  50. unsigned TestFlagInNormalCleanup : 1;
  51. /// Whether the EH cleanup should test the activation flag.
  52. unsigned TestFlagInEHCleanup : 1;
  53. /// The amount of extra storage needed by the Cleanup.
  54. /// Always a multiple of the scope-stack alignment.
  55. unsigned CleanupSize : 12;
  56. /// The number of fixups required by enclosing scopes (not including
  57. /// this one). If this is the top cleanup scope, all the fixups
  58. /// from this index onwards belong to this scope.
  59. unsigned FixupDepth : 32 - 17 - NumCommonBits; // currently 13
  60. };
  61. class FilterBitFields {
  62. friend class EHFilterScope;
  63. unsigned : NumCommonBits;
  64. unsigned NumFilters : 32 - NumCommonBits;
  65. };
  66. union {
  67. CommonBitFields CommonBits;
  68. CatchBitFields CatchBits;
  69. CleanupBitFields CleanupBits;
  70. FilterBitFields FilterBits;
  71. };
  72. public:
  73. enum Kind { Cleanup, Catch, Terminate, Filter };
  74. EHScope(Kind kind, EHScopeStack::stable_iterator enclosingEHScope)
  75. : CachedLandingPad(0), CachedEHDispatchBlock(0),
  76. EnclosingEHScope(enclosingEHScope) {
  77. CommonBits.Kind = kind;
  78. }
  79. Kind getKind() const { return static_cast<Kind>(CommonBits.Kind); }
  80. llvm::BasicBlock *getCachedLandingPad() const {
  81. return CachedLandingPad;
  82. }
  83. void setCachedLandingPad(llvm::BasicBlock *block) {
  84. CachedLandingPad = block;
  85. }
  86. llvm::BasicBlock *getCachedEHDispatchBlock() const {
  87. return CachedEHDispatchBlock;
  88. }
  89. void setCachedEHDispatchBlock(llvm::BasicBlock *block) {
  90. CachedEHDispatchBlock = block;
  91. }
  92. bool hasEHBranches() const {
  93. if (llvm::BasicBlock *block = getCachedEHDispatchBlock())
  94. return !block->use_empty();
  95. return false;
  96. }
  97. EHScopeStack::stable_iterator getEnclosingEHScope() const {
  98. return EnclosingEHScope;
  99. }
  100. };
  101. /// A scope which attempts to handle some, possibly all, types of
  102. /// exceptions.
  103. ///
  104. /// Objective C @finally blocks are represented using a cleanup scope
  105. /// after the catch scope.
  106. class EHCatchScope : public EHScope {
  107. // In effect, we have a flexible array member
  108. // Handler Handlers[0];
  109. // But that's only standard in C99, not C++, so we have to do
  110. // annoying pointer arithmetic instead.
  111. public:
  112. struct Handler {
  113. /// A type info value, or null (C++ null, not an LLVM null pointer)
  114. /// for a catch-all.
  115. llvm::Value *Type;
  116. /// The catch handler for this type.
  117. llvm::BasicBlock *Block;
  118. bool isCatchAll() const { return Type == 0; }
  119. };
  120. private:
  121. friend class EHScopeStack;
  122. Handler *getHandlers() {
  123. return reinterpret_cast<Handler*>(this+1);
  124. }
  125. const Handler *getHandlers() const {
  126. return reinterpret_cast<const Handler*>(this+1);
  127. }
  128. public:
  129. static size_t getSizeForNumHandlers(unsigned N) {
  130. return sizeof(EHCatchScope) + N * sizeof(Handler);
  131. }
  132. EHCatchScope(unsigned numHandlers,
  133. EHScopeStack::stable_iterator enclosingEHScope)
  134. : EHScope(Catch, enclosingEHScope) {
  135. CatchBits.NumHandlers = numHandlers;
  136. }
  137. unsigned getNumHandlers() const {
  138. return CatchBits.NumHandlers;
  139. }
  140. void setCatchAllHandler(unsigned I, llvm::BasicBlock *Block) {
  141. setHandler(I, /*catchall*/ 0, Block);
  142. }
  143. void setHandler(unsigned I, llvm::Value *Type, llvm::BasicBlock *Block) {
  144. assert(I < getNumHandlers());
  145. getHandlers()[I].Type = Type;
  146. getHandlers()[I].Block = Block;
  147. }
  148. const Handler &getHandler(unsigned I) const {
  149. assert(I < getNumHandlers());
  150. return getHandlers()[I];
  151. }
  152. typedef const Handler *iterator;
  153. iterator begin() const { return getHandlers(); }
  154. iterator end() const { return getHandlers() + getNumHandlers(); }
  155. static bool classof(const EHScope *Scope) {
  156. return Scope->getKind() == Catch;
  157. }
  158. };
  159. /// A cleanup scope which generates the cleanup blocks lazily.
  160. class EHCleanupScope : public EHScope {
  161. /// The nearest normal cleanup scope enclosing this one.
  162. EHScopeStack::stable_iterator EnclosingNormal;
  163. /// The nearest EH scope enclosing this one.
  164. EHScopeStack::stable_iterator EnclosingEH;
  165. /// The dual entry/exit block along the normal edge. This is lazily
  166. /// created if needed before the cleanup is popped.
  167. llvm::BasicBlock *NormalBlock;
  168. /// An optional i1 variable indicating whether this cleanup has been
  169. /// activated yet.
  170. llvm::AllocaInst *ActiveFlag;
  171. /// Extra information required for cleanups that have resolved
  172. /// branches through them. This has to be allocated on the side
  173. /// because everything on the cleanup stack has be trivially
  174. /// movable.
  175. struct ExtInfo {
  176. /// The destinations of normal branch-afters and branch-throughs.
  177. llvm::SmallPtrSet<llvm::BasicBlock*, 4> Branches;
  178. /// Normal branch-afters.
  179. SmallVector<std::pair<llvm::BasicBlock*,llvm::ConstantInt*>, 4>
  180. BranchAfters;
  181. };
  182. mutable struct ExtInfo *ExtInfo;
  183. struct ExtInfo &getExtInfo() {
  184. if (!ExtInfo) ExtInfo = new struct ExtInfo();
  185. return *ExtInfo;
  186. }
  187. const struct ExtInfo &getExtInfo() const {
  188. if (!ExtInfo) ExtInfo = new struct ExtInfo();
  189. return *ExtInfo;
  190. }
  191. public:
  192. /// Gets the size required for a lazy cleanup scope with the given
  193. /// cleanup-data requirements.
  194. static size_t getSizeForCleanupSize(size_t Size) {
  195. return sizeof(EHCleanupScope) + Size;
  196. }
  197. size_t getAllocatedSize() const {
  198. return sizeof(EHCleanupScope) + CleanupBits.CleanupSize;
  199. }
  200. EHCleanupScope(bool isNormal, bool isEH, bool isActive,
  201. unsigned cleanupSize, unsigned fixupDepth,
  202. EHScopeStack::stable_iterator enclosingNormal,
  203. EHScopeStack::stable_iterator enclosingEH)
  204. : EHScope(EHScope::Cleanup, enclosingEH), EnclosingNormal(enclosingNormal),
  205. NormalBlock(0), ActiveFlag(0), ExtInfo(0) {
  206. CleanupBits.IsNormalCleanup = isNormal;
  207. CleanupBits.IsEHCleanup = isEH;
  208. CleanupBits.IsActive = isActive;
  209. CleanupBits.TestFlagInNormalCleanup = false;
  210. CleanupBits.TestFlagInEHCleanup = false;
  211. CleanupBits.CleanupSize = cleanupSize;
  212. CleanupBits.FixupDepth = fixupDepth;
  213. assert(CleanupBits.CleanupSize == cleanupSize && "cleanup size overflow");
  214. }
  215. ~EHCleanupScope() {
  216. delete ExtInfo;
  217. }
  218. bool isNormalCleanup() const { return CleanupBits.IsNormalCleanup; }
  219. llvm::BasicBlock *getNormalBlock() const { return NormalBlock; }
  220. void setNormalBlock(llvm::BasicBlock *BB) { NormalBlock = BB; }
  221. bool isEHCleanup() const { return CleanupBits.IsEHCleanup; }
  222. llvm::BasicBlock *getEHBlock() const { return getCachedEHDispatchBlock(); }
  223. void setEHBlock(llvm::BasicBlock *BB) { setCachedEHDispatchBlock(BB); }
  224. bool isActive() const { return CleanupBits.IsActive; }
  225. void setActive(bool A) { CleanupBits.IsActive = A; }
  226. llvm::AllocaInst *getActiveFlag() const { return ActiveFlag; }
  227. void setActiveFlag(llvm::AllocaInst *Var) { ActiveFlag = Var; }
  228. void setTestFlagInNormalCleanup() {
  229. CleanupBits.TestFlagInNormalCleanup = true;
  230. }
  231. bool shouldTestFlagInNormalCleanup() const {
  232. return CleanupBits.TestFlagInNormalCleanup;
  233. }
  234. void setTestFlagInEHCleanup() {
  235. CleanupBits.TestFlagInEHCleanup = true;
  236. }
  237. bool shouldTestFlagInEHCleanup() const {
  238. return CleanupBits.TestFlagInEHCleanup;
  239. }
  240. unsigned getFixupDepth() const { return CleanupBits.FixupDepth; }
  241. EHScopeStack::stable_iterator getEnclosingNormalCleanup() const {
  242. return EnclosingNormal;
  243. }
  244. size_t getCleanupSize() const { return CleanupBits.CleanupSize; }
  245. void *getCleanupBuffer() { return this + 1; }
  246. EHScopeStack::Cleanup *getCleanup() {
  247. return reinterpret_cast<EHScopeStack::Cleanup*>(getCleanupBuffer());
  248. }
  249. /// True if this cleanup scope has any branch-afters or branch-throughs.
  250. bool hasBranches() const { return ExtInfo && !ExtInfo->Branches.empty(); }
  251. /// Add a branch-after to this cleanup scope. A branch-after is a
  252. /// branch from a point protected by this (normal) cleanup to a
  253. /// point in the normal cleanup scope immediately containing it.
  254. /// For example,
  255. /// for (;;) { A a; break; }
  256. /// contains a branch-after.
  257. ///
  258. /// Branch-afters each have their own destination out of the
  259. /// cleanup, guaranteed distinct from anything else threaded through
  260. /// it. Therefore branch-afters usually force a switch after the
  261. /// cleanup.
  262. void addBranchAfter(llvm::ConstantInt *Index,
  263. llvm::BasicBlock *Block) {
  264. struct ExtInfo &ExtInfo = getExtInfo();
  265. if (ExtInfo.Branches.insert(Block))
  266. ExtInfo.BranchAfters.push_back(std::make_pair(Block, Index));
  267. }
  268. /// Return the number of unique branch-afters on this scope.
  269. unsigned getNumBranchAfters() const {
  270. return ExtInfo ? ExtInfo->BranchAfters.size() : 0;
  271. }
  272. llvm::BasicBlock *getBranchAfterBlock(unsigned I) const {
  273. assert(I < getNumBranchAfters());
  274. return ExtInfo->BranchAfters[I].first;
  275. }
  276. llvm::ConstantInt *getBranchAfterIndex(unsigned I) const {
  277. assert(I < getNumBranchAfters());
  278. return ExtInfo->BranchAfters[I].second;
  279. }
  280. /// Add a branch-through to this cleanup scope. A branch-through is
  281. /// a branch from a scope protected by this (normal) cleanup to an
  282. /// enclosing scope other than the immediately-enclosing normal
  283. /// cleanup scope.
  284. ///
  285. /// In the following example, the branch through B's scope is a
  286. /// branch-through, while the branch through A's scope is a
  287. /// branch-after:
  288. /// for (;;) { A a; B b; break; }
  289. ///
  290. /// All branch-throughs have a common destination out of the
  291. /// cleanup, one possibly shared with the fall-through. Therefore
  292. /// branch-throughs usually don't force a switch after the cleanup.
  293. ///
  294. /// \return true if the branch-through was new to this scope
  295. bool addBranchThrough(llvm::BasicBlock *Block) {
  296. return getExtInfo().Branches.insert(Block);
  297. }
  298. /// Determines if this cleanup scope has any branch throughs.
  299. bool hasBranchThroughs() const {
  300. if (!ExtInfo) return false;
  301. return (ExtInfo->BranchAfters.size() != ExtInfo->Branches.size());
  302. }
  303. static bool classof(const EHScope *Scope) {
  304. return (Scope->getKind() == Cleanup);
  305. }
  306. };
  307. /// An exceptions scope which filters exceptions thrown through it.
  308. /// Only exceptions matching the filter types will be permitted to be
  309. /// thrown.
  310. ///
  311. /// This is used to implement C++ exception specifications.
  312. class EHFilterScope : public EHScope {
  313. // Essentially ends in a flexible array member:
  314. // llvm::Value *FilterTypes[0];
  315. llvm::Value **getFilters() {
  316. return reinterpret_cast<llvm::Value**>(this+1);
  317. }
  318. llvm::Value * const *getFilters() const {
  319. return reinterpret_cast<llvm::Value* const *>(this+1);
  320. }
  321. public:
  322. EHFilterScope(unsigned numFilters)
  323. : EHScope(Filter, EHScopeStack::stable_end()) {
  324. FilterBits.NumFilters = numFilters;
  325. }
  326. static size_t getSizeForNumFilters(unsigned numFilters) {
  327. return sizeof(EHFilterScope) + numFilters * sizeof(llvm::Value*);
  328. }
  329. unsigned getNumFilters() const { return FilterBits.NumFilters; }
  330. void setFilter(unsigned i, llvm::Value *filterValue) {
  331. assert(i < getNumFilters());
  332. getFilters()[i] = filterValue;
  333. }
  334. llvm::Value *getFilter(unsigned i) const {
  335. assert(i < getNumFilters());
  336. return getFilters()[i];
  337. }
  338. static bool classof(const EHScope *scope) {
  339. return scope->getKind() == Filter;
  340. }
  341. };
  342. /// An exceptions scope which calls std::terminate if any exception
  343. /// reaches it.
  344. class EHTerminateScope : public EHScope {
  345. public:
  346. EHTerminateScope(EHScopeStack::stable_iterator enclosingEHScope)
  347. : EHScope(Terminate, enclosingEHScope) {}
  348. static size_t getSize() { return sizeof(EHTerminateScope); }
  349. static bool classof(const EHScope *scope) {
  350. return scope->getKind() == Terminate;
  351. }
  352. };
  353. /// A non-stable pointer into the scope stack.
  354. class EHScopeStack::iterator {
  355. char *Ptr;
  356. friend class EHScopeStack;
  357. explicit iterator(char *Ptr) : Ptr(Ptr) {}
  358. public:
  359. iterator() : Ptr(0) {}
  360. EHScope *get() const {
  361. return reinterpret_cast<EHScope*>(Ptr);
  362. }
  363. EHScope *operator->() const { return get(); }
  364. EHScope &operator*() const { return *get(); }
  365. iterator &operator++() {
  366. switch (get()->getKind()) {
  367. case EHScope::Catch:
  368. Ptr += EHCatchScope::getSizeForNumHandlers(
  369. static_cast<const EHCatchScope*>(get())->getNumHandlers());
  370. break;
  371. case EHScope::Filter:
  372. Ptr += EHFilterScope::getSizeForNumFilters(
  373. static_cast<const EHFilterScope*>(get())->getNumFilters());
  374. break;
  375. case EHScope::Cleanup:
  376. Ptr += static_cast<const EHCleanupScope*>(get())
  377. ->getAllocatedSize();
  378. break;
  379. case EHScope::Terminate:
  380. Ptr += EHTerminateScope::getSize();
  381. break;
  382. }
  383. return *this;
  384. }
  385. iterator next() {
  386. iterator copy = *this;
  387. ++copy;
  388. return copy;
  389. }
  390. iterator operator++(int) {
  391. iterator copy = *this;
  392. operator++();
  393. return copy;
  394. }
  395. bool encloses(iterator other) const { return Ptr >= other.Ptr; }
  396. bool strictlyEncloses(iterator other) const { return Ptr > other.Ptr; }
  397. bool operator==(iterator other) const { return Ptr == other.Ptr; }
  398. bool operator!=(iterator other) const { return Ptr != other.Ptr; }
  399. };
  400. inline EHScopeStack::iterator EHScopeStack::begin() const {
  401. return iterator(StartOfData);
  402. }
  403. inline EHScopeStack::iterator EHScopeStack::end() const {
  404. return iterator(EndOfBuffer);
  405. }
  406. inline void EHScopeStack::popCatch() {
  407. assert(!empty() && "popping exception stack when not empty");
  408. EHCatchScope &scope = cast<EHCatchScope>(*begin());
  409. InnermostEHScope = scope.getEnclosingEHScope();
  410. StartOfData += EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers());
  411. }
  412. inline void EHScopeStack::popTerminate() {
  413. assert(!empty() && "popping exception stack when not empty");
  414. EHTerminateScope &scope = cast<EHTerminateScope>(*begin());
  415. InnermostEHScope = scope.getEnclosingEHScope();
  416. StartOfData += EHTerminateScope::getSize();
  417. }
  418. inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const {
  419. assert(sp.isValid() && "finding invalid savepoint");
  420. assert(sp.Size <= stable_begin().Size && "finding savepoint after pop");
  421. return iterator(EndOfBuffer - sp.Size);
  422. }
  423. inline EHScopeStack::stable_iterator
  424. EHScopeStack::stabilize(iterator ir) const {
  425. assert(StartOfData <= ir.Ptr && ir.Ptr <= EndOfBuffer);
  426. return stable_iterator(EndOfBuffer - ir.Ptr);
  427. }
  428. }
  429. }
  430. #endif