Stack.cpp 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. //===--- Stack.h - Utilities for dealing with stack space -------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. ///
  9. /// \file
  10. /// Defines utilities for dealing with stack allocation and stack space.
  11. ///
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/Basic/Stack.h"
  14. #include "llvm/ADT/Optional.h"
  15. #include "llvm/Support/CrashRecoveryContext.h"
  16. static LLVM_THREAD_LOCAL void *BottomOfStack = nullptr;
  17. static void *getStackPointer() {
  18. #if __GNUC__ || __has_builtin(__builtin_frame_address)
  19. return __builtin_frame_address(0);
  20. #elif defined(_MSC_VER)
  21. return _AddressOfReturnAddress();
  22. #else
  23. char CharOnStack = 0;
  24. // The volatile store here is intended to escape the local variable, to
  25. // prevent the compiler from optimizing CharOnStack into anything other
  26. // than a char on the stack.
  27. //
  28. // Tested on: MSVC 2015 - 2019, GCC 4.9 - 9, Clang 3.2 - 9, ICC 13 - 19.
  29. char *volatile Ptr = &CharOnStack;
  30. return Ptr;
  31. #endif
  32. }
  33. void clang::noteBottomOfStack() {
  34. if (!BottomOfStack)
  35. BottomOfStack = getStackPointer();
  36. }
  37. bool clang::isStackNearlyExhausted() {
  38. // We consider 256 KiB to be sufficient for any code that runs between checks
  39. // for stack size.
  40. constexpr size_t SufficientStack = 256 << 10;
  41. // If we don't know where the bottom of the stack is, hope for the best.
  42. if (!BottomOfStack)
  43. return false;
  44. intptr_t StackDiff = (intptr_t)getStackPointer() - (intptr_t)BottomOfStack;
  45. size_t StackUsage = (size_t)std::abs(StackDiff);
  46. // If the stack pointer has a surprising value, we do not understand this
  47. // stack usage scheme. (Perhaps the target allocates new stack regions on
  48. // demand for us.) Don't try to guess what's going on.
  49. if (StackUsage > DesiredStackSize)
  50. return false;
  51. return StackUsage >= DesiredStackSize - SufficientStack;
  52. }
  53. void clang::runWithSufficientStackSpaceSlow(llvm::function_ref<void()> Diag,
  54. llvm::function_ref<void()> Fn) {
  55. llvm::CrashRecoveryContext CRC;
  56. CRC.RunSafelyOnThread([&] {
  57. noteBottomOfStack();
  58. Diag();
  59. Fn();
  60. }, DesiredStackSize);
  61. }