Last active
November 15, 2023 16:52
-
-
Save ThePhD/d59c383aa7ac350ba1efef9326ca4b39 to your computer and use it in GitHub Desktop.
Having too much fun imaigning a better future.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/////////////////////// | |
// platform boilerplate | |
/////////////////////// | |
#define _GNU_SOURCE | |
#define WIN32_LEAN_AND_MEAN | |
#if defined(_MSC_VER) | |
#define MY_FLATTEN __forceinline | |
#define MY_OUTLINE __declspec(noinline) | |
#include <malloc.h> | |
#include <windows.h> | |
#elif defined(__clang__) || defined(__GNUC__) | |
#define MY_FLATTEN [[gnu::flatten]] | |
#define MY_OUTLINE [[gnu::noinline]] | |
#else | |
#define MY_FLATTEN | |
#define MY_OUTLINE | |
#error "unsupported platform: do not how to inline function call into parent function call on this vendor" | |
#endif | |
#if defined(_REENTRANT) && (_REENTRANT == 1) && \ | |
__has_include(<pthread.h>) | |
#define MY_PTHREAD_H 1 | |
#include <pthread.h> | |
#else | |
#define MY_PTHREAD_H 0 | |
#endif | |
#include <stddef.h> | |
#include <stdint.h> | |
MY_OUTLINE | |
bool my_is_stack_available(size_t amount, size_t alignment) | |
{ | |
// TODO: support alignment | |
#if defined(_MSVC_VER) | |
// https://devblogs.microsoft.com/oldnewthing/20200610-00/?p=103855 | |
ULONG_PTR low = 0, high = 0; | |
GetCurrentThreadStackLimits(&low, &high); | |
ptrdiff_t remaining = reinterpret_cast<ULONG_PTR>(&low) - low; | |
ptrdiff_t available = high - low; | |
if (remaining > available) { | |
// Ssssshhhooould not be possible?! | |
// Something is horrifically wrong here...! | |
__fastfail(FAST_FAIL_INCORRECT_STACK); | |
} | |
return remaining >= amount; | |
#elif MY_PTHREAD_H | |
char* low_stack_addr; | |
size_t stack_size; | |
pthread_attr_t attr; | |
int getattr_res = pthread_getattr_np(pthread_self(), &attr); | |
if (getattr_res != 0) { | |
return false; | |
} | |
int getstack_res = pthread_attr_getstack(&attr, | |
(void**)&low_stack_addr, | |
&stack_size); | |
if (getstack_res != 0 { | |
return false; | |
} | |
// some nerd will scream about provenance or whatever, I'm sure | |
char* local_address_guess = ((char*)(void*)&low_stack_addr); | |
ptrdiff_t remaining = local_address_guess - low_stack_addr; | |
if (remaining > stack_size) { | |
// Absolutely should NOT be possible?! | |
abort(); | |
} | |
return remaining >= amount; | |
#else | |
#error "cannot determine current stack size: insufficient hacks" | |
#endif | |
} | |
#include <stddef.h> | |
#include <stdlib.h> | |
/////////////////////////// | |
// User-Defined VLA Control | |
/////////////////////////// | |
MY_FLATTEN inline void* my_vla_alloc(size_t size, | |
size_t alignment, | |
size_t* actual_size) | |
{ | |
if (!my_is_stack_available(size, alignment)) { | |
abort(); | |
return nullptr; | |
} | |
*actual_size = size; | |
#ifdef _MSC_VER | |
return __alloca(size); | |
#else | |
return __builtin_alloca_with_align(size, alignment); | |
#endif | |
} | |
MY_FLATTEN inline void my_vla_free(void* ptr, | |
size_t size, | |
size_t alignment) | |
{ | |
// nothing, it's alloca | |
} | |
/////////////// | |
// main program | |
/////////////// | |
extern int n; | |
int main () { | |
// we are in compiler that doesn't support VLAs (e.g., MSVC) | |
static_assert(__STDC_NO_VLA__ != 0, | |
"this will work even if VLAs are not present"); | |
// error: VLA not supported | |
int will_error[n]; | |
// new scope | |
{ | |
// Aliases: artisanal, handmade, scope-based name feature | |
// Aliases: https://thephd.dev/_vendor/future_cxx/papers/C%20-%20Transparent%20Aliases.html | |
_Alias stdc_vla_alloc = my_vla_alloc; | |
_Alias stdc_vla_free = my_vla_free; | |
// because both stdc_vla_alloc and stdc_vla_free are available, | |
// VLA will use that to retrieve memory | |
// and ignore whatever implementation does | |
int vla[n] = {}; | |
// use as normal... | |
/* … */ | |
} | |
// error: VLA not supported again, | |
// and stdc_vla_* functions are no longer in scope | |
int will_error_again[n]; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment