llvm-project
74 строки · 2.4 Кб
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
14#include "clang/Basic/Stack.h"15#include "llvm/Support/CrashRecoveryContext.h"16
17#ifdef _MSC_VER18#include <intrin.h> // for _AddressOfReturnAddress19#endif20
21static LLVM_THREAD_LOCAL void *BottomOfStack = nullptr;22
23static void *getStackPointer() {24#if __GNUC__ || __has_builtin(__builtin_frame_address)25return __builtin_frame_address(0);26#elif defined(_MSC_VER)27return _AddressOfReturnAddress();28#else29char CharOnStack = 0;30// The volatile store here is intended to escape the local variable, to31// prevent the compiler from optimizing CharOnStack into anything other32// than a char on the stack.33//34// Tested on: MSVC 2015 - 2019, GCC 4.9 - 9, Clang 3.2 - 9, ICC 13 - 19.35char *volatile Ptr = &CharOnStack;36return Ptr;37#endif38}
39
40void clang::noteBottomOfStack() {41if (!BottomOfStack)42BottomOfStack = getStackPointer();43}
44
45bool clang::isStackNearlyExhausted() {46// We consider 256 KiB to be sufficient for any code that runs between checks47// for stack size.48constexpr size_t SufficientStack = 256 << 10;49
50// If we don't know where the bottom of the stack is, hope for the best.51if (!BottomOfStack)52return false;53
54intptr_t StackDiff = (intptr_t)getStackPointer() - (intptr_t)BottomOfStack;55size_t StackUsage = (size_t)std::abs(StackDiff);56
57// If the stack pointer has a surprising value, we do not understand this58// stack usage scheme. (Perhaps the target allocates new stack regions on59// demand for us.) Don't try to guess what's going on.60if (StackUsage > DesiredStackSize)61return false;62
63return StackUsage >= DesiredStackSize - SufficientStack;64}
65
66void clang::runWithSufficientStackSpaceSlow(llvm::function_ref<void()> Diag,67llvm::function_ref<void()> Fn) {68llvm::CrashRecoveryContext CRC;69CRC.RunSafelyOnThread([&] {70noteBottomOfStack();71Diag();72Fn();73}, DesiredStackSize);74}
75