Stack.cpp 2.4 KB

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