/* File: cwasm.h Author: Taylor Robbins Date: 08\28\2025 Description: ** This header should be included before any other header and at the top of every compilation unit. ** It in turn includes any files that are needed for a CWasm-based application to function */ #ifndef _CWASM_H #define _CWASM_H // +--------------------------------------------------------------+ // | Check Compiler | // +--------------------------------------------------------------+ #if !defined(__clang__) #error CWasm is only tested to function with Clang as the compiler! #endif #if !defined(__clang_major__) || !defined(__clang_minor__) || !defined(__clang_patchlevel__) #error Missing defines for __clang_major__, __clang_minor__, and __clang_patchlevel__! #endif #if !defined(__wasm32__) #error CWasm only works when compiling for 32-bit WebAssembly! #endif #if defined(__EMSCRIPTEN__) #error CWasm is not meant to be compiled with Emscripten. It functions as a standalone platform for C applications that only depend on a small subset of the C standard library #endif #ifndef __BYTE_ORDER__ #error Missing __BYTE_ORDER__ define! #elif __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ #error This standard library implementation assumes little-endian byte order #endif // +--------------------------------------------------------------+ // | Check Configuration Macros | // +--------------------------------------------------------------+ #ifndef CWASM_DEBUG #define CWASM_DEBUG 0 #endif #ifndef CWASM_ASSERTIONS_ENABLED #define CWASM_ASSERTIONS_ENABLED CWASM_DEBUG #endif #ifndef CWASM_DEBUG_OUTPUT_LINE_BUFFER_SIZE #define CWASM_DEBUG_OUTPUT_LINE_BUFFER_SIZE 1024 //chars #endif #ifndef CWASM_DEBUG_OUTPUT_PRINT_BUFFER_SIZE #define CWASM_DEBUG_OUTPUT_PRINT_BUFFER_SIZE 1024 //chars #endif #ifndef CWASM_ENABLE_DBG_LEVEL_DEBUG #define CWASM_ENABLE_DBG_LEVEL_DEBUG CWASM_DEBUG #endif #ifndef CWASM_ENABLE_DBG_LEVEL_INFO #define CWASM_ENABLE_DBG_LEVEL_INFO 1 #endif #ifndef CWASM_ENABLE_DBG_LEVEL_WARNING #define CWASM_ENABLE_DBG_LEVEL_WARNING 1 #endif #ifndef CWASM_ENABLE_DBG_LEVEL_ERROR #define CWASM_ENABLE_DBG_LEVEL_ERROR 1 #endif #ifndef CWASM_NO_STB_IMAGE #define CWASM_NO_STB_IMAGE 0 #endif // +--------------------------------------------------------------+ // | Macros | // +--------------------------------------------------------------+ #ifdef __cplusplus #define LANGUAGE_IS_C 0 #define LANGUAGE_IS_CPP 1 #else #define LANGUAGE_IS_C 1 #define LANGUAGE_IS_CPP 0 #endif #if LANGUAGE_IS_C #define nullptr ((void*)0) #endif #define START_EXTERN_C extern "C" { #define END_EXTERN_C } #if LANGUAGE_IS_CPP #define MAYBE_EXTERN_C EXTERN_C #define MAYBE_START_EXTERN_C START_EXTERN_C #define MAYBE_END_EXTERN_C END_EXTERN_C #else #define MAYBE_EXTERN_C //nothing #define MAYBE_START_EXTERN_C //nothing #define MAYBE_END_EXTERN_C //nothing #endif #define WASM_MEMORY_PAGE_SIZE (64*1024ULL) //64kB or 65,536b #define WASM_MEMORY_MAX_NUM_PAGES (64*1024ULL) //65,536 pages * 64 kB/page = 4GB #define WASM_MEMORY_MAX_SIZE ((u64)WASM_MEMORY_MAX_NUM_PAGES * (u64)WASM_MEMORY_PAGE_SIZE) #define WASM_PROTECTED_SIZE 1024 //1kB at start of wasm memory should be unused and should never be written to #define WASM_EXPORT(functionName) MAYBE_EXTERN_C __attribute__((export_name(#functionName))) #if LANGUAGE_IS_C #define ZEROED {0} #else #define ZEROED {} #endif #define ArrayCount(array) (sizeof(array) / sizeof((array)[0])) #define IsAlignedTo(pntr, alignment) ((alignment) == 0 || (((size_t)(pntr)) % (alignment)) == 0) #define AlignOffset(pntr, alignment) ((alignment) == 0 ? 0 : (((alignment) - (((size_t)(pntr)) % (alignment))) % alignment)) // Shorthand for writing things like (4 * 1024 * 1024) as Megabytes(4). // Can be used for more than just memory sizes but these powers of 1024 are often // used when partitioning memory because they relate to binary bit patterns #define Kilo(value) ((value) * 1024ULL) #define Mega(value) (Kilo(value) * 1024ULL) #define Giga(value) (Mega(value) * 1024ULL) #define Tera(value) (Giga(value) * 1024ULL) #define Kilobytes(value) Kilo(value) #define Megabytes(value) Mega(value) #define Gigabytes(value) Giga(value) #define Terabytes(value) Tera(value) #define Thousand(value) ((value) * 1000ULL) #define Million(value) ((value) * 1000000ULL) #define Billion(value) ((value) * 1000000000ULL) #define Trillion(value) ((value) * 1000000000000ULL) #if CWASM_ASSERTIONS_ENABLED #define Assert(condition) assert(condition) #define AssertMsg(condition, message) assert_msg((condition), (message)) #else #define Assert(condition) sizeof(condition) //do nothing, but make sure anything used in condition is not treated as "unused" when assertions are disabled #define AssertMsg(condition, message) sizeof(condition) #endif #define NotNull(expression) Assert((expression) != nullptr) #define Clamp(value, min, max) (((value) < (min)) ? (min) : (((value) > (max)) ? (max) : (value))) //Actual Value of Pi: 3.1415926535897932384626433832795... #define Pi64 3.14159265358979311599796346854 //accurate to 15 digits #define Pi32 3.1415927410125732421875f //accurate to 6 digits #define QuarterPi64 (Pi64/4.0) #define ThirdPi64 (Pi64/3.0) #define HalfPi64 (Pi64/2.0) #define ThreeHalfsPi64 (Pi64*(3.0/2.0)) #define TwoPi64 (2*Pi64) #define QuarterPi32 (Pi32/4.0f) #define ThirdPi32 (Pi32/3.0f) #define HalfPi32 (Pi32/2.0f) #define ThreeHalfsPi32 (Pi32*(3.0f/2.0f)) #define TwoPi32 (2*Pi32) //Actual Value of e: 2.7182818284590452353602874713526... #define e64 2.71828182845904509079559829843 //accurate to 15 digits #define e32 2.71828174591064453125f //accurate to 6 digits // +--------------------------------------------------------------+ // | Standard Includes | // +--------------------------------------------------------------+ // NOTE: These headers are all contained in CWasm's "std" folder, they are not "real" C standard library headers #include #include #include #include #include #include #include #include #include #include #include #include // +--------------------------------------------------------------+ // | Basic Type Names | // +--------------------------------------------------------------+ // We use an "i" to indicate it can hold integer numbers typedef int8_t i8; typedef int16_t i16; typedef int32_t i32; typedef long long i64; // We use a "u" to distinguish these as only holding unsigned numbers (they are still integers, but "i" is already taken) typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; typedef unsigned long long u64; // We use an "r" to indicate it can hold real numbers typedef float r32; typedef double r64; #endif // _CWASM_H