Added cwasm_arena.c and cwasm_debug.c. Arena API hasn't been tested well yet. There's also something wrong with our DebugOutputLineBuffer usage for splitting lines to multiple Javascript output calls. Also added an int level to jsStdPrint and a bunch of macros to cwasm.h

This commit is contained in:
2025-08-31 17:33:48 -07:00
parent d0aa7a1d0e
commit cca61ea163
9 changed files with 566 additions and 11 deletions

View File

@@ -10,5 +10,105 @@
"build", "build",
], ],
} }
] ],
"settings":
{
"build_options":
[
],
"custom_constants":
[
"ArenaFlag_All",
"ArenaFlag_Count",
"ArenaFlag_Debug",
"ArenaFlag_DefaultAligned16",
"ArenaFlag_DefaultAligned4",
"ArenaFlag_DefaultAligned8",
"ArenaFlag_IsMainWasmMemory",
"ArenaFlag_IsScratch",
"ArenaFlag_None",
"CWASM_ASSERTIONS_ENABLED",
"CWASM_DEBUG",
"CWASM_DEBUG_OUTPUT_LINE_BUFFER_SIZE",
"CWASM_DEBUG_OUTPUT_PRINT_BUFFER_SIZE",
"CWASM_ENABLE_DBG_LEVEL_DEBUG",
"CWASM_ENABLE_DBG_LEVEL_DEBUG",
"CWASM_ENABLE_DBG_LEVEL_ERROR",
"CWASM_ENABLE_DBG_LEVEL_ERROR",
"CWASM_ENABLE_DBG_LEVEL_INFO",
"CWASM_ENABLE_DBG_LEVEL_INFO",
"CWASM_ENABLE_DBG_LEVEL_WARNING",
"CWASM_ENABLE_DBG_LEVEL_WARNING",
"DbgLevel_Count",
"DbgLevel_Debug",
"DbgLevel_Error",
"DbgLevel_Info",
"DbgLevel_None",
"DbgLevel_Warning",
"END_EXTERN_C",
"LANGUAGE_IS_C",
"LANGUAGE_IS_CPP",
"MAYBE_END_EXTERN_C",
"MAYBE_EXTERN_C",
"MAYBE_START_EXTERN_C",
"SCRATCH_ARENAS_SIZE",
"START_EXTERN_C",
"WASM_MEMORY_MAX_NUM_PAGES",
"WASM_MEMORY_MAX_SIZE",
"WASM_MEMORY_PAGE_SIZE",
"WASM_PROTECTED_SIZE",
"ZEROED",
],
"custom_functions":
[
"#define AlignOffset(pntr, alignment)",
"#define AllocArray(type, arenaPntr, count)",
"#define AllocStruct(type, arenaPntr)",
"#define ArrayCount(array)",
"#define Assert(condition)",
"#define IsAlignedTo(pntr, alignment)",
"#define PrintLine_D(formatStrNt, ...)",
"#define PrintLine_E(formatStrNt, ...)",
"#define PrintLine_I(formatStrNt, ...)",
"#define PrintLine_W(formatStrNt, ...)",
"#define Print_D(formatStrNt, ...)",
"#define Print_E(formatStrNt, ...)",
"#define Print_I(formatStrNt, ...)",
"#define Print_W(formatStrNt, ...)",
"#define ScratchBegin(scratchName)",
"#define ScratchBegin1(scratchName, conflictArenaPntr)",
"#define ScratchEnd(scratchName)",
"#define WASM_EXPORT(functionName)",
"#define WriteLine_D(messageNt)",
"#define WriteLine_E(messageNt)",
"#define WriteLine_I(messageNt)",
"#define WriteLine_W(messageNt)",
"#define Write_D(messageNt)",
"#define Write_E(messageNt)",
"#define Write_I(messageNt)",
"#define Write_W(messageNt)",
"Arena NewArena(void* basePntr, u32 size)",
"Arena* AllocArena(Arena* sourceArena, u32 newArenaFlags, u32 newArenaSize, u32 newArenaAlignment)",
"ArenaMark GetArenaMark(Arena* arena)",
"ArenaMark GetScratch()",
"ArenaMark GetScratch1(Arena* conflictArena)",
"inline void* ReallocMem(Arena* arena, void* oldPntr, u32 oldSize, u32 newSize)",
"inline void* ReallocMemUnaligned(Arena* arena, void* oldPntr, u32 oldSize, u32 newSize)",
"void InitGlobalArenas(u32 scratchArenasSize)",
"void ResetToArenaMark(ArenaMark arenaMark)",
"void ResetToMark(Arena* arena, u32 mark)",
"void* AllocMemUnaligned(Arena* arena, u32 numBytes)",
"void* ReallocMemAligned(Arena* arena, void* oldPntr, u32 oldSize, u32 newSize, u32 newAlignment)",
],
"custom_globals":
[
],
"custom_types":
[
"Arena",
"ArenaFlag",
"ArenaMark",
"DbgLevel",
],
},
} }

19
cwasm.c
View File

@@ -9,14 +9,17 @@ Description:
#include "cwasm.h" #include "cwasm.h"
#include "std/src/std_main.c" #include "std/src/std_main.c"
#include "cwasm_arena.c"
#include "cwasm_debug.c"
WASM_EXPORT(HelloFromWasm) float HelloFromWasm(float value, float value2) void InitializeCWasm(u32 scratchArenasSize)
{ {
printf("Called HelloFromWasm(%g)!\n", fmodf(value, value2)); // CwasmDebugOutput(__FILE__, __LINE__, __func__, DbgLevel_Warning, true, "Hello\nWorld!");
for (int iIndex = 0; iIndex < 1024; iIndex++) Write_D("Hello\nWorld!");
{ PrintLine_D(" Fuzzy %u Bunnies!\n%s", 31415926, "What");
void* newMem = grow_mem(1024); WriteLine_D("");
printf("mem[%d] = %p\n", iIndex, newMem); WriteLine_I("When");
} Write_D("\n");
return value*(value+1)*2; WriteLine_E("Where");
InitGlobalArenas(scratchArenasSize);
} }

66
cwasm.h
View File

@@ -31,6 +31,36 @@ Description:
#error This standard library implementation assumes little-endian byte order #error This standard library implementation assumes little-endian byte order
#endif #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 1
#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
// +--------------------------------------------------------------+ // +--------------------------------------------------------------+
// | Macros | // | Macros |
// +--------------------------------------------------------------+ // +--------------------------------------------------------------+
@@ -65,6 +95,41 @@ Description:
#define WASM_EXPORT(functionName) MAYBE_EXTERN_C __attribute__((export_name(#functionName))) #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
// +--------------------------------------------------------------+ // +--------------------------------------------------------------+
// | Standard Includes | // | Standard Includes |
// +--------------------------------------------------------------+ // +--------------------------------------------------------------+
@@ -76,6 +141,7 @@ Description:
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stddef.h> #include <stddef.h>
#include <assert.h> #include <assert.h>

182
cwasm_arena.c Normal file
View File

@@ -0,0 +1,182 @@
/*
File: cwasm_arena.c
Author: Taylor Robbins
Date: 08\28\2025
Description:
** Defines a basic memory Arena structure and API
** Also defines a few global memory arenas: MainWasmMemory and 2x ScratchArenas
*/
// +--------------------------------------------------------------+
// | Arena Types |
// +--------------------------------------------------------------+
typedef enum ArenaFlag ArenaFlag;
enum ArenaFlag
{
ArenaFlag_None = 0x00000000,
ArenaFlag_Debug = 0x00000001,
ArenaFlag_IsMainWasmMemory = 0x00000002,
ArenaFlag_DefaultAligned4 = 0x00000004,
ArenaFlag_DefaultAligned8 = 0x00000008,
ArenaFlag_DefaultAligned16 = 0x00000010,
ArenaFlag_IsScratch = 0x00000020,
ArenaFlag_All = 0x0000003F,
ArenaFlag_Count = 6,
};
typedef struct Arena Arena;
struct Arena
{
u32 flags; //ArenaFlags
void* base;
u32 size;
u32 used;
};
typedef struct ArenaMark ArenaMark;
struct ArenaMark
{
Arena* arena;
u32 mark;
};
// +--------------------------------------------------------------+
// | Global Arenas |
// +--------------------------------------------------------------+
static Arena MainWasmMemory = ZEROED;
static Arena ScratchArenas[2] = ZEROED;
// +--------------------------------------------------------------+
// | Arena API |
// +--------------------------------------------------------------+
__attribute__((always_inline)) Arena NewArena(u32 flags, u32 size, void* basePntr)
{
Arena result = ZEROED;
result.flags = flags;
result.size = size;
result.base = basePntr;
return result;
}
static inline ArenaMark GetArenaMark(Arena* arena)
{
ArenaMark result = ZEROED;
result.arena = arena;
result.mark = arena->used;
return result;
}
static inline void ResetToMark(Arena* arena, u32 mark)
{
arena->used = mark;
}
static inline void ResetToArenaMark(ArenaMark arenaMark) { ResetToMark(arenaMark.arena, arenaMark.mark); }
void* AllocMemAligned(Arena* arena, u32 numBytes, u32 alignment)
{
Assert(arena != nullptr && arena->base != nullptr);
u32 realAlignment = alignment;
if (realAlignment == UINT32_MAX) { realAlignment = 0; }
else if (realAlignment == 0 && (arena->flags & ArenaFlag_DefaultAligned16) != 0) { realAlignment = 16; }
else if (realAlignment == 0 && (arena->flags & ArenaFlag_DefaultAligned8) != 0) { realAlignment = 8; }
else if (realAlignment == 0 && (arena->flags & ArenaFlag_DefaultAligned4) != 0) { realAlignment = 4; }
u32 alignOffset = AlignOffset((u8*)arena->base + arena->used, realAlignment);
u32 newSize = arena->used + alignOffset + numBytes;
if (newSize > arena->size)
{
if ((arena->flags & ArenaFlag_IsMainWasmMemory) != 0)
{
void* newMemory = grow_mem(newSize - arena->size);
Assert(newMemory == (u8*)arena->base + arena->size);
arena->size = newSize;
}
else { return nullptr; }
}
void* result = (u8*)arena->base + arena->used;
arena->used += alignOffset + numBytes;
return result;
}
static inline void* AllocMemUnaligned(Arena* arena, u32 numBytes) { return AllocMemAligned(arena, numBytes, UINT32_MAX); }
static inline void* AllocMem(Arena* arena, u32 numBytes) { return AllocMemAligned(arena, numBytes, 0); }
static inline Arena* AllocArena(Arena* sourceArena, u32 newArenaFlags, u32 newArenaSize, u32 newArenaAlignment)
{
//TODO: Do we need to make sure the Arena structure is aligned to it's own struct alignment?
#if LANGUAGE_IS_C
u32 arenaStructAlignment = (u32)_Alignof(Arena);
#else
u32 arenaStructAlignment = (u32)std::alignment_of<Arena>();
#endif
u32 offsetAfterStruct = AlignOffset(sizeof(Arena), newArenaAlignment);
Arena* result = (Arena*)AllocMemAligned(sourceArena, sizeof(Arena) + offsetAfterStruct + newArenaSize, (arenaStructAlignment >= newArenaAlignment) ? arenaStructAlignment : newArenaAlignment);
if (result == nullptr) { return nullptr; }
*result = NewArena(newArenaFlags, newArenaSize, ((u8*)result) + sizeof(Arena) + offsetAfterStruct);
return result;
}
#if LANGUAGE_IS_C
#define AllocStruct(type, arenaPntr) (type*)AllocMemAligned((arenaPntr), sizeof(type), (u32)_Alignof(type))
#define AllocArray(type, arenaPntr, count) (type*)AllocMemAligned((arenaPntr), sizeof(type) * (count), (u32)_Alignof(type))
#else
#define AllocStruct(type, arenaPntr) (type*)AllocMemAligned((arenaPntr), sizeof(type), (u32)std::alignment_of<type>())
#define AllocArray(type, arenaPntr, count) (type*)AllocMemAligned((arenaPntr), sizeof(type) * (count), (u32)std::alignment_of<type>())
#endif
void* ReallocMemAligned(Arena* arena, void* oldPntr, u32 oldSize, u32 newSize, u32 newAlignment)
{
if (oldSize == newSize) { return oldPntr; }
if (oldPntr == nullptr) { return AllocMemAligned(arena, newSize, newAlignment); }
Assert(arena != nullptr && arena->base != nullptr);
u32 realAlignment = newAlignment;
if (realAlignment == UINT32_MAX) { realAlignment = 0; }
else if (realAlignment == 0 && (arena->flags & ArenaFlag_DefaultAligned16) != 0) { realAlignment = 16; }
else if (realAlignment == 0 && (arena->flags & ArenaFlag_DefaultAligned8) != 0) { realAlignment = 8; }
else if (realAlignment == 0 && (arena->flags & ArenaFlag_DefaultAligned4) != 0) { realAlignment = 4; }
if ((u8*)oldPntr + oldSize == (u8*)arena->base + arena->used && IsAlignedTo(oldPntr, realAlignment))
{
if (newSize > oldSize)
{
void* newSpace = AllocMemUnaligned(arena, newSize - oldSize);
if (newSpace == nullptr) { return nullptr; }
Assert(newSpace == (u8*)oldPntr + oldSize);
}
else { arena->used -= (oldSize - newSize); }
return oldPntr;
}
else
{
void* newPntr = AllocMemAligned(arena, newSize, newAlignment);
if (oldSize > 0 && newPntr != nullptr) { memcpy(newPntr, oldPntr, oldSize); }
return newPntr;
}
}
static inline void* ReallocMemUnaligned(Arena* arena, void* oldPntr, u32 oldSize, u32 newSize) { return ReallocMemAligned(arena, oldPntr, oldSize, newSize, UINT32_MAX); }
static inline void* ReallocMem(Arena* arena, void* oldPntr, u32 oldSize, u32 newSize) { return ReallocMemAligned(arena, oldPntr, oldSize, newSize, 0); }
void InitGlobalArenas(u32 scratchArenasSize)
{
u32 mainInitialSize = 1024;
void* mainPntr = grow_mem(mainInitialSize);
MainWasmMemory = NewArena(ArenaFlag_IsMainWasmMemory|ArenaFlag_DefaultAligned16, mainInitialSize, mainPntr);
for (u32 aIndex = 0; aIndex < ArrayCount(ScratchArenas); aIndex++)
{
void* scratchMemory = AllocMem(&MainWasmMemory, scratchArenasSize);
ScratchArenas[aIndex] = NewArena(ArenaFlag_IsScratch, scratchArenasSize, scratchMemory);
}
}
// +==============================+
// | Scratch API |
// +==============================+
ArenaMark GetScratch1(Arena* conflictArena)
{
return GetArenaMark((conflictArena == &ScratchArenas[0]) ? &ScratchArenas[1] : &ScratchArenas[0]);
}
static inline ArenaMark GetScratch() { return GetScratch1(nullptr); }
#define ScratchBegin1(scratchName, conflictArenaPntr) ArenaMark scratchName##Mark = GetScratch1(conflictArenaPntr); Arena* scratchName = scratchName##Mark.arena
#define ScratchBegin(scratchName) ScratchBegin(scratchName, nullptr)
#define ScratchEnd(scratchName) ResetToArenaMark(scratchName##Mark)

186
cwasm_debug.c Normal file
View File

@@ -0,0 +1,186 @@
/*
File: cwasm_debug.c
Author: Taylor Robbins
Date: 08\29\2025
Description:
** Holds functions and macros for the debug output API we use in the application
*/
typedef enum DbgLevel DbgLevel;
enum DbgLevel
{
DbgLevel_Debug = 0,
DbgLevel_Info,
DbgLevel_Warning,
DbgLevel_Error,
DbgLevel_Count,
};
static DbgLevel DebugOutputLineBufferLevel = DbgLevel_Debug;
static u32 DebugOutputLineBufferLength = 0;
static char DebugOutputLineBuffer[CWASM_DEBUG_OUTPUT_LINE_BUFFER_SIZE];
static char DebugOutputPrintBuffer[CWASM_DEBUG_OUTPUT_PRINT_BUFFER_SIZE];
#if CWASM_DEBUG
void CwasmDebugOutput(const char* filePath, u32 lineNumber, const char* functionName, DbgLevel level, bool newLine, const char* messageNt)
#else
void CwasmDebugOutput(DbgLevel level, bool newLine, const char* messageNt)
#endif
{
if (level == DbgLevel_Debug && !CWASM_ENABLE_DBG_LEVEL_DEBUG) { return; }
if (level == DbgLevel_Info && !CWASM_ENABLE_DBG_LEVEL_INFO) { return; }
if (level == DbgLevel_Warning && !CWASM_ENABLE_DBG_LEVEL_WARNING) { return; }
if (level == DbgLevel_Error && !CWASM_ENABLE_DBG_LEVEL_ERROR) { return; }
u32 lineStart = 0;
int messageLength = (messageNt != nullptr) ? strlen(messageNt) : 0;
for (int cIndex = 0; cIndex < messageLength + (newLine ? 1 : 0); cIndex++)
{
char character = (cIndex < messageLength) ? messageNt[cIndex] : '\n';
if (character == '\n')
{
if (DebugOutputLineBufferLength > 0)
{
DebugOutputLineBufferLevel = (level > DebugOutputLineBufferLevel) ? level : DebugOutputLineBufferLevel;
u32 numCharsToCopy = ((cIndex - lineStart) < (CWASM_DEBUG_OUTPUT_LINE_BUFFER_SIZE - DebugOutputLineBufferLength))
? (cIndex - lineStart)
: (CWASM_DEBUG_OUTPUT_LINE_BUFFER_SIZE - DebugOutputLineBufferLength);
if (numCharsToCopy > 0)
{
memcpy(&DebugOutputLineBuffer[DebugOutputLineBufferLength], &messageNt[lineStart], numCharsToCopy);
DebugOutputLineBufferLength += numCharsToCopy;
}
jsStdPrint((int)DebugOutputLineBufferLevel, &DebugOutputLineBuffer[0], DebugOutputLineBufferLength);
DebugOutputLineBufferLength = 0;
DebugOutputLineBufferLevel = DbgLevel_Debug;
}
else
{
jsStdPrint((int)level, &messageNt[lineStart], messageLength - lineStart);
}
lineStart = cIndex+1;
}
}
if (lineStart < messageLength)
{
u32 numCharsToCopy = ((messageLength - lineStart) < (CWASM_DEBUG_OUTPUT_LINE_BUFFER_SIZE - DebugOutputLineBufferLength))
? (messageLength - lineStart)
: (CWASM_DEBUG_OUTPUT_LINE_BUFFER_SIZE - DebugOutputLineBufferLength);
if (numCharsToCopy > 0)
{
DebugOutputLineBufferLevel = (level > DebugOutputLineBufferLevel) ? level : DebugOutputLineBufferLevel;
memcpy(&DebugOutputLineBuffer[DebugOutputLineBufferLength], &messageNt[lineStart], numCharsToCopy);
DebugOutputLineBufferLength += numCharsToCopy;
}
}
}
#if CWASM_DEBUG
void CwasmDebugOutputPrint(const char* filePath, u32 lineNumber, const char* functionName, DbgLevel level, bool newLine, const char* formatStrNt, ...)
#else
void CwasmDebugOutputPrint(DbgLevel level, bool newLine, const char* formatStrNt, ...)
#endif
{
va_list args;
va_start(args, formatStrNt);
int printResult = vsnprintf(&DebugOutputPrintBuffer[0], CWASM_DEBUG_OUTPUT_PRINT_BUFFER_SIZE, formatStrNt, args);
va_end(args);
if (printResult >= 0)
{
DebugOutputPrintBuffer[CWASM_DEBUG_OUTPUT_PRINT_BUFFER_SIZE-1] = '\0';
#if CWASM_DEBUG
CwasmDebugOutput(filePath, lineNumber, functionName, level, newLine, &DebugOutputPrintBuffer[0]);
#else
CwasmDebugOutput(level, newLine, &DebugOutputPrintBuffer[0]);
#endif
}
else
{
#if CWASM_DEBUG
CwasmDebugOutput(filePath, lineNumber, functionName, level, false, "CWASM_PRINT_ERROR(");
CwasmDebugOutput(filePath, lineNumber, functionName, level, false, formatStrNt);
CwasmDebugOutput(filePath, lineNumber, functionName, level, true, ")");
#else
CwasmDebugOutput(level, false, "CWASM_PRINT_ERROR(");
CwasmDebugOutput(level, false, formatStrNt);
CwasmDebugOutput(level, true, ")");
#endif
}
}
#if CWASM_ENABLE_DBG_LEVEL_DEBUG
#if CWASM_DEBUG
#define Write_D(messageNt) CwasmDebugOutput(__FILE__, __LINE__, __func__, DbgLevel_Debug, false, (messageNt))
#define Print_D(formatStrNt, ...) CwasmDebugOutputPrint(__FILE__, __LINE__, __func__, DbgLevel_Debug, false, (formatStrNt), ##__VA_ARGS__)
#define WriteLine_D(messageNt) CwasmDebugOutput(__FILE__, __LINE__, __func__, DbgLevel_Debug, true, (messageNt))
#define PrintLine_D(formatStrNt, ...) CwasmDebugOutputPrint(__FILE__, __LINE__, __func__, DbgLevel_Debug, true, (formatStrNt), ##__VA_ARGS__)
#else
#define Write_D(messageNt) CwasmDebugOutput(DbgLevel_Debug, false, (messageNt))
#define Print_D(formatStrNt, ...) CwasmDebugOutputPrint(DbgLevel_Debug, false, (formatStrNt), ##__VA_ARGS__)
#define WriteLine_D(messageNt) CwasmDebugOutput(DbgLevel_Debug, true, (messageNt))
#define PrintLine_D(formatStrNt, ...) CwasmDebugOutputPrint(DbgLevel_Debug, true, (formatStrNt), ##__VA_ARGS__)
#endif
#else
#define Write_D(messageNt) //nothing
#define Print_D(formatStrNt, ...) //nothing
#define WriteLine_D(messageNt) //nothing
#define PrintLine_D(formatStrNt, ...) //nothing
#endif
#if CWASM_ENABLE_DBG_LEVEL_INFO
#if CWASM_DEBUG
#define Write_I(messageNt) CwasmDebugOutput(__FILE__, __LINE__, __func__, DbgLevel_Info, false, (messageNt))
#define Print_I(formatStrNt, ...) CwasmDebugOutputPrint(__FILE__, __LINE__, __func__, DbgLevel_Info, false, (formatStrNt), ##__VA_ARGS__)
#define WriteLine_I(messageNt) CwasmDebugOutput(__FILE__, __LINE__, __func__, DbgLevel_Info, true, (messageNt))
#define PrintLine_I(formatStrNt, ...) CwasmDebugOutputPrint(__FILE__, __LINE__, __func__, DbgLevel_Info, true, (formatStrNt), ##__VA_ARGS__)
#else
#define Write_I(messageNt) CwasmDebugOutput(DbgLevel_Info, false, (messageNt))
#define Print_I(formatStrNt, ...) CwasmDebugOutputPrint(DbgLevel_Info, false, (formatStrNt), ##__VA_ARGS__)
#define WriteLine_I(messageNt) CwasmDebugOutput(DbgLevel_Info, true, (messageNt))
#define PrintLine_I(formatStrNt, ...) CwasmDebugOutputPrint(DbgLevel_Info, true, (formatStrNt), ##__VA_ARGS__)
#endif
#else
#define Write_I(messageNt) //nothing
#define Print_I(formatStrNt, ...) //nothing
#define WriteLine_I(messageNt) //nothing
#define PrintLine_I(formatStrNt, ...) //nothing
#endif
#if CWASM_ENABLE_DBG_LEVEL_WARNING
#if CWASM_DEBUG
#define Write_W(messageNt) CwasmDebugOutput(__FILE__, __LINE__, __func__, DbgLevel_Warning, false, (messageNt))
#define Print_W(formatStrNt, ...) CwasmDebugOutputPrint(__FILE__, __LINE__, __func__, DbgLevel_Warning, false, (formatStrNt), ##__VA_ARGS__)
#define WriteLine_W(messageNt) CwasmDebugOutput(__FILE__, __LINE__, __func__, DbgLevel_Warning, true, (messageNt))
#define PrintLine_W(formatStrNt, ...) CwasmDebugOutputPrint(__FILE__, __LINE__, __func__, DbgLevel_Warning, true, (formatStrNt), ##__VA_ARGS__)
#else
#define Write_W(messageNt) CwasmDebugOutput(DbgLevel_Warning, false, (messageNt))
#define Print_W(formatStrNt, ...) CwasmDebugOutputPrint(DbgLevel_Warning, false, (formatStrNt), ##__VA_ARGS__)
#define WriteLine_W(messageNt) CwasmDebugOutput(DbgLevel_Warning, true, (messageNt))
#define PrintLine_W(formatStrNt, ...) CwasmDebugOutputPrint(DbgLevel_Warning, true, (formatStrNt), ##__VA_ARGS__)
#endif
#else
#define Write_W(messageNt) //nothing
#define Print_W(formatStrNt, ...) //nothing
#define WriteLine_W(messageNt) //nothing
#define PrintLine_W(formatStrNt, ...) //nothing
#endif
#if CWASM_ENABLE_DBG_LEVEL_ERROR
#if CWASM_DEBUG
#define Write_E(messageNt) CwasmDebugOutput(__FILE__, __LINE__, __func__, DbgLevel_Error, false, (messageNt))
#define Print_E(formatStrNt, ...) CwasmDebugOutputPrint(__FILE__, __LINE__, __func__, DbgLevel_Error, false, (formatStrNt), ##__VA_ARGS__)
#define WriteLine_E(messageNt) CwasmDebugOutput(__FILE__, __LINE__, __func__, DbgLevel_Error, true, (messageNt))
#define PrintLine_E(formatStrNt, ...) CwasmDebugOutputPrint(__FILE__, __LINE__, __func__, DbgLevel_Error, true, (formatStrNt), ##__VA_ARGS__)
#else
#define Write_E(messageNt) CwasmDebugOutput(DbgLevel_Error, false, (messageNt))
#define Print_E(formatStrNt, ...) CwasmDebugOutputPrint(DbgLevel_Error, false, (formatStrNt), ##__VA_ARGS__)
#define WriteLine_E(messageNt) CwasmDebugOutput(DbgLevel_Error, true, (messageNt))
#define PrintLine_E(formatStrNt, ...) CwasmDebugOutputPrint(DbgLevel_Error, true, (formatStrNt), ##__VA_ARGS__)
#endif
#else
#define Write_E(messageNt) //nothing
#define Print_E(formatStrNt, ...) //nothing
#define WriteLine_E(messageNt) //nothing
#define PrintLine_E(formatStrNt, ...) //nothing
#endif

View File

@@ -7,6 +7,8 @@ Date: 08\28\2025
#ifndef _ASSERT_H #ifndef _ASSERT_H
#define _ASSERT_H #define _ASSERT_H
#include "src/std_js_imports.h"
#define assert(condition) do { if (!(condition)) { jsStdAssertFailure(__FILE__, __LINE__, __func__, #condition, nullptr); } } while(0) #define assert(condition) do { if (!(condition)) { jsStdAssertFailure(__FILE__, __LINE__, __func__, #condition, nullptr); } } while(0)
//NOTE: assert_msg is not a standard function but we want to be able to pass a message to jsStdAssertFailure so we added this variant //NOTE: assert_msg is not a standard function but we want to be able to pass a message to jsStdAssertFailure so we added this variant
#define assert_msg(condition, message) do { if (!(condition)) { jsStdAssertFailure(__FILE__, __LINE__, __func__, #condition, (message)); } } while(0) #define assert_msg(condition, message) do { if (!(condition)) { jsStdAssertFailure(__FILE__, __LINE__, __func__, #condition, (message)); } } while(0)

View File

@@ -9,7 +9,7 @@ Description:
#ifndef _STD_JS_IMPORTS_H #ifndef _STD_JS_IMPORTS_H
#define _STD_JS_IMPORTS_H #define _STD_JS_IMPORTS_H
MAYBE_EXTERN_C void jsStdPrint(const char* messageStrPntr, int messageLength); MAYBE_EXTERN_C void jsStdPrint(int level, const char* messageStrPntr, int messageLength);
MAYBE_EXTERN_C _Noreturn void jsStdAbort(const char* messageStrPntr, int exitCode); MAYBE_EXTERN_C _Noreturn void jsStdAbort(const char* messageStrPntr, int exitCode);
MAYBE_EXTERN_C _Noreturn void jsStdAssertFailure(const char* filePathPntr, int fileLineNum, const char* funcNamePntr, const char* conditionStrPntr, const char* messageStrPntr); MAYBE_EXTERN_C _Noreturn void jsStdAssertFailure(const char* filePathPntr, int fileLineNum, const char* funcNamePntr, const char* conditionStrPntr, const char* messageStrPntr);
MAYBE_EXTERN_C void jsStdDebugBreak(); MAYBE_EXTERN_C void jsStdDebugBreak();

View File

@@ -31,7 +31,7 @@ int vprintf(const char* restrict formatStr, va_list args)
if (result > 0 && result < STD_PRINTF_BUFFER_SIZE) if (result > 0 && result < STD_PRINTF_BUFFER_SIZE)
{ {
stdGlobalPrintBuffer[result] = '\0'; //ensure null-termination stdGlobalPrintBuffer[result] = '\0'; //ensure null-termination
jsStdPrint(&stdGlobalPrintBuffer[0], result); jsStdPrint(1, &stdGlobalPrintBuffer[0], result);
} }
return result; return result;
} }

View File

@@ -8,4 +8,20 @@ Description:
#include "cwasm.c" #include "cwasm.c"
#define SCRATCH_ARENAS_SIZE Kilobytes(128)
WASM_EXPORT(InitializeApp) void InitializeApp()
{
InitializeCWasm(SCRATCH_ARENAS_SIZE);
}
WASM_EXPORT(HelloFromWasm) float HelloFromWasm(float value, float value2)
{
printf("Called HelloFromWasm(%g)!\n", fmodf(value, value2));
for (int iIndex = 0; iIndex < 1024; iIndex++)
{
void* newMem = grow_mem(1024);
printf("mem[%d] = %p\n", iIndex, newMem);
}
return value*(value+1)*2;
}