Got a basic WebAssembly module compiling with support for calling jsStdPrint through printf implementation (provided by stb_sprintf.h). We have a single function "HelloFromWasm" exported for testing purposes. Pulled in a bunch of standard library headers from PigCore's wasm layer.
This commit is contained in:
85
.gitignore
vendored
85
.gitignore
vendored
@@ -1,87 +1,4 @@
|
||||
# ---> C
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Linker output
|
||||
*.ilk
|
||||
*.map
|
||||
*.exp
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
*.su
|
||||
*.idb
|
||||
*.pdb
|
||||
|
||||
# Kernel Module Compile Results
|
||||
*.mod*
|
||||
*.cmd
|
||||
.tmp_versions/
|
||||
modules.order
|
||||
Module.symvers
|
||||
Mkfile.old
|
||||
dkms.conf
|
||||
|
||||
# ---> SublimeText
|
||||
# Cache files for Sublime Text
|
||||
*.tmlanguage.cache
|
||||
*.tmPreferences.cache
|
||||
*.stTheme.cache
|
||||
build/
|
||||
|
||||
# Workspace files are user-specific
|
||||
*.sublime-workspace
|
||||
|
||||
# Project files should be checked into the repository, unless a significant
|
||||
# proportion of contributors will probably not be using Sublime Text
|
||||
# *.sublime-project
|
||||
|
||||
# SFTP configuration file
|
||||
sftp-config.json
|
||||
sftp-config-alt*.json
|
||||
|
||||
# Package control specific files
|
||||
Package Control.last-run
|
||||
Package Control.ca-list
|
||||
Package Control.ca-bundle
|
||||
Package Control.system-ca-bundle
|
||||
Package Control.cache/
|
||||
Package Control.ca-certs/
|
||||
Package Control.merged-ca-bundle
|
||||
Package Control.user-ca-bundle
|
||||
oscrypto-ca-bundle.crt
|
||||
bh_unicode_properties.cache
|
||||
|
||||
# Sublime-github package stores a github token in this file
|
||||
# https://packagecontrol.io/packages/sublime-github
|
||||
GitHub.sublime-settings
|
||||
|
||||
|
||||
14
CWasm.sublime-project
Normal file
14
CWasm.sublime-project
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"folders":
|
||||
[
|
||||
{
|
||||
"path": ".",
|
||||
"file_exclude_patterns": [
|
||||
"*.o",
|
||||
],
|
||||
"folder_exclude_patterns": [
|
||||
"build",
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
10
README.md
10
README.md
@@ -1,3 +1,11 @@
|
||||
# CWasm
|
||||
|
||||
A minimal layer for compiling C applications that render graphics through WebGL from a WebAssembly module using Clang (not Emscripten)
|
||||
A minimal layer for compiling C applications that render graphics through WebGL from a WebAssembly module using Clang (not Emscripten)
|
||||
|
||||
# Compilation
|
||||
CWasm is compiled with the applicaiton as a [Unity Build](https://en.wikipedia.org/wiki/Unity_build). The application's main source file must #include cwasm.c before anything else. The code in this repository is only tested with Clang as the compiler and `wasm32-unknown-unknown` as the target architecture. You must have a version of Clang that supports compiling to WebAssembly.
|
||||
|
||||
1. Install Clang (LLVM's Compiler) from [LLVM's Download Page](https://releases.llvm.org/download.html)
|
||||
2. Make sure Clang is available from the command-line by doing `clang -v`. If it's not, make sure you update your `PATH` environment variable to include the `bin/` folder of the LLVM install directory
|
||||
3. Ensure you have **Clang 11.0** or greater for proper WebAssembly support (we recommend using the latest, that's **v18.1.8** as this is written)
|
||||
4. On Windows run the `build.bat [path/to/app.c]`. On Linux or OSX run the `build.sh [path/to/app.c]`. If compiling CWasm without a real application the app.c argument may be ommitted and test_app.c will be used instead.
|
||||
|
||||
41
build.bat
Normal file
41
build.bat
Normal file
@@ -0,0 +1,41 @@
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
set app_source_path=..\test_app.c
|
||||
echo %1 | findstr /r "^[A-Za-z]:" >nul
|
||||
if not "%1"=="" (
|
||||
if %errorlevel% equ 0 (
|
||||
set app_source_path=%1
|
||||
) else (
|
||||
set app_source_path=..\%1
|
||||
)
|
||||
)
|
||||
set app_module_name=app.wasm
|
||||
if not "%2"=="" (
|
||||
set app_module_name=%2
|
||||
)
|
||||
|
||||
if not exist build mkdir build
|
||||
pushd build
|
||||
|
||||
rem TODO: Take the app.c file path as an argument?
|
||||
echo [Compiling %app_source_path% to %app_module_name%...]
|
||||
clang %app_source_path% -o "%app_module_name%" -I ".." -I "..\std" -std=gnu2x --target=wasm32-unknown-unknown -mbulk-memory -Wl,--no-entry,--export-dynamic,--allow-undefined,--export=__heap_base --no-standard-libraries --no-standard-includes
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo [FAILED to build %app_module_name%!]
|
||||
goto :build_end
|
||||
) else (
|
||||
echo [Done!]
|
||||
)
|
||||
|
||||
|
||||
rem Convert .wasm to .wat (the text format for WebAssembly) for debug inspection
|
||||
set "app_module_wat_name=%app_module_name:.wasm=.wat%"
|
||||
if "%app_module_wat_name%" == "%app_module_name%" (
|
||||
set app_module_wat_name=%app_module_name%.wat
|
||||
)
|
||||
echo [Converting %app_module_name% to %app_module_wat_name%...]
|
||||
wasm2wat "%app_module_name%" > "%app_module_wat_name%"
|
||||
|
||||
:build_end
|
||||
popd
|
||||
17
cwasm.c
Normal file
17
cwasm.c
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
File: main.c
|
||||
Author: Taylor Robbins
|
||||
Date: 08\28\2025
|
||||
Description:
|
||||
** This file serves as the compilable file for all of CWasm. It may be #included by the app.c file
|
||||
*/
|
||||
|
||||
#include "cwasm.h"
|
||||
|
||||
#include "std/src/std_main.c"
|
||||
|
||||
WASM_EXPORT(HelloFromWasm) int HelloFromWasm(int value)
|
||||
{
|
||||
printf("Called HelloFromWasm(%d)!\n", value);
|
||||
return value*(value+1)*2;
|
||||
}
|
||||
91
cwasm.h
Normal file
91
cwasm.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
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
|
||||
|
||||
#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)))
|
||||
|
||||
// +--------------------------------------------------------------+
|
||||
// | Standard Includes |
|
||||
// +--------------------------------------------------------------+
|
||||
// NOTE: These headers are all contained in CWasm's "std" folder, they are not "real" C standard library headers
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
// +--------------------------------------------------------------+
|
||||
// | 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
|
||||
14
std/assert.h
Normal file
14
std/assert.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
File: assert.h
|
||||
Author: Taylor Robbins
|
||||
Date: 08\28\2025
|
||||
*/
|
||||
|
||||
#ifndef _ASSERT_H
|
||||
#define _ASSERT_H
|
||||
|
||||
#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
|
||||
#define assert_msg(condition, message) do { if (!(condition)) { jsStdAssertFailure(__FILE__, __LINE__, __func__, #condition, (message)); } } while(0)
|
||||
|
||||
#endif // _ASSERT_H
|
||||
32
std/limits.h
Normal file
32
std/limits.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
File: limits.h
|
||||
Author: Taylor Robbins
|
||||
Date: 08\28\2025
|
||||
*/
|
||||
|
||||
#ifndef _LIMITS_H
|
||||
#define _LIMITS_H
|
||||
|
||||
#define CHAR_MIN (-128)
|
||||
#define CHAR_MAX 127
|
||||
|
||||
#define CHAR_BIT 8
|
||||
#define SCHAR_MIN (-128)
|
||||
#define SCHAR_MAX 127
|
||||
#define UCHAR_MAX 255
|
||||
#define SHRT_MIN (-1-0x7fff)
|
||||
#define SHRT_MAX 0x7fff
|
||||
#define USHRT_MAX 0xffff
|
||||
#define INT_MIN (-1-0x7fffffff)
|
||||
#define INT_MAX 0x7fffffff
|
||||
#define UINT_MAX 0xffffffffU
|
||||
#define LONG_MIN (-LONG_MAX-1)
|
||||
#define LONG_MAX __LONG_MAX
|
||||
#define ULONG_MAX (2UL*LONG_MAX+1)
|
||||
#define LLONG_MIN (-LLONG_MAX-1)
|
||||
#define LLONG_MAX 0x7fffffffffffffffLL
|
||||
#define ULLONG_MAX (2ULL*LLONG_MAX+1)
|
||||
|
||||
//TODO: Define PAGESIZE?
|
||||
|
||||
#endif // _LIMITS_H
|
||||
1906
std/src/stb_sprintf.h
Normal file
1906
std/src/stb_sprintf.h
Normal file
File diff suppressed because it is too large
Load Diff
18
std/src/std_js_imports.h
Normal file
18
std/src/std_js_imports.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
File: std_js_imports.h
|
||||
Author: Taylor Robbins
|
||||
Date: 08\28\2025
|
||||
Description:
|
||||
** Holds the declarations for functions that we expect to be imported by the Javascript glue code and imported to the module when it's loaded
|
||||
*/
|
||||
|
||||
#ifndef _STD_JS_IMPORTS_H
|
||||
#define _STD_JS_IMPORTS_H
|
||||
|
||||
MAYBE_EXTERN_C void jsStdPrint(const char* messageStrPntr, int messageLength);
|
||||
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 void jsStdDebugBreak();
|
||||
MAYBE_EXTERN_C void jsStdGrowMemory(unsigned int numPages);
|
||||
|
||||
#endif // _STD_JS_IMPORTS_H
|
||||
21
std/src/std_main.c
Normal file
21
std/src/std_main.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
File: std_main.c
|
||||
Author: Taylor Robbins
|
||||
Date: 08\28\2025
|
||||
Description:
|
||||
** Contains the implementations for all standard library functions that are declared in the headers in the parent folder
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <uchar.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "std_js_imports.h"
|
||||
|
||||
#include "std_memset.c"
|
||||
#include "std_printf.c"
|
||||
370
std/src/std_memset.c
Normal file
370
std/src/std_memset.c
Normal file
@@ -0,0 +1,370 @@
|
||||
/*
|
||||
File: std_memset.c
|
||||
Author: Taylor Robbins
|
||||
Date: 08\28\2025
|
||||
Description:
|
||||
** Holds implementations of functions like memset(), memcpy(), memmove(), etc.
|
||||
*/
|
||||
|
||||
#define WORD_CONTAINS_ZERO(word) ((word)-((size_t)-1/UCHAR_MAX) & ~(word) & (((size_t)-1/UCHAR_MAX) * (UCHAR_MAX/2+1)))
|
||||
|
||||
#define MAX(left, right) ((left) > (right) ? (left) : (right))
|
||||
#define MIN(left, right) ((left) < (right) ? (left) : (right))
|
||||
|
||||
typedef size_t __attribute__((__may_alias__)) a_size_t;
|
||||
#define SIZEOF_A_SIZE_T sizeof(a_size_t)
|
||||
typedef uint32_t __attribute__((__may_alias__)) a_u32;
|
||||
typedef uint64_t __attribute__((__may_alias__)) a_u64;
|
||||
|
||||
#if !WASM_STD_USE_BUILTIN_MEMSET
|
||||
void* _memset(void* pntr, int value, size_t numBytes)
|
||||
{
|
||||
unsigned char* charPntr = pntr;
|
||||
size_t alignment;
|
||||
|
||||
// Fill head and tail with minimal branching. Each
|
||||
// conditional ensures that all the subsequently used
|
||||
// offsets are well-defined and in the pntr region.
|
||||
|
||||
if (!numBytes) { return pntr; }
|
||||
charPntr[0] = value;
|
||||
charPntr[numBytes-1] = value;
|
||||
if (numBytes <= 2) { return pntr; }
|
||||
charPntr[1] = value;
|
||||
charPntr[2] = value;
|
||||
charPntr[numBytes-2] = value;
|
||||
charPntr[numBytes-3] = value;
|
||||
if (numBytes <= 6) { return pntr; }
|
||||
charPntr[3] = value;
|
||||
charPntr[numBytes-4] = value;
|
||||
if (numBytes <= 8) { return pntr; }
|
||||
|
||||
// Advance pointer to align it at a 4-byte boundary,
|
||||
// and truncate numBytes to a multiple of 4. The previous code
|
||||
// already took care of any head/tail that get cut off
|
||||
// by the alignment.
|
||||
alignment = (-(uintptr_t)charPntr & 3);
|
||||
charPntr += alignment;
|
||||
numBytes -= alignment;
|
||||
numBytes &= -4;
|
||||
|
||||
a_u32 value32 = ((a_u32) - 1) / 255 * (unsigned char)value;
|
||||
|
||||
// In preparation to copy 32 bytes at a time, aligned on
|
||||
// an 8-byte bounary, fill head/tail up to 28 bytes each.
|
||||
// As in the initial byte-based head/tail fill, each
|
||||
// conditional below ensures that the subsequent offsets
|
||||
// are valid (e.g. !(numBytes<=24) implies numBytes>=28).
|
||||
*(a_u32*)(charPntr + 0) = value32;
|
||||
*(a_u32*)(charPntr + numBytes - 4) = value32;
|
||||
if (numBytes <= 8) { return pntr; }
|
||||
*(a_u32*)(charPntr + 4) = value32;
|
||||
*(a_u32*)(charPntr + 8) = value32;
|
||||
*(a_u32*)(charPntr + numBytes - 12) = value32;
|
||||
*(a_u32*)(charPntr + numBytes - 8) = value32;
|
||||
if (numBytes <= 24) { return pntr; }
|
||||
*(a_u32*)(charPntr + 12) = value32;
|
||||
*(a_u32*)(charPntr + 16) = value32;
|
||||
*(a_u32*)(charPntr + 20) = value32;
|
||||
*(a_u32*)(charPntr + 24) = value32;
|
||||
*(a_u32*)(charPntr + numBytes - 28) = value32;
|
||||
*(a_u32*)(charPntr + numBytes - 24) = value32;
|
||||
*(a_u32*)(charPntr + numBytes - 20) = value32;
|
||||
*(a_u32*)(charPntr + numBytes - 16) = value32;
|
||||
|
||||
// Align to a multiple of 8 so we can fill 64 bits at a time,
|
||||
// and avoid writing the same bytes twice as much as is
|
||||
// practical without introducing additional branching.
|
||||
alignment = 24 + ((uintptr_t)charPntr & 4);
|
||||
charPntr += alignment;
|
||||
numBytes -= alignment;
|
||||
|
||||
// If this loop is reached, 28 tail bytes have already been
|
||||
// filled, so any remainder when numBytes drops below 32 can be
|
||||
// safely ignored.
|
||||
a_u64 value64 = (value32 | ((a_u64)value32 << 32));
|
||||
for (; numBytes >= 32; numBytes -= 32, charPntr += 32)
|
||||
{
|
||||
*(a_u64*)(charPntr + 0) = value64;
|
||||
*(a_u64*)(charPntr + 8) = value64;
|
||||
*(a_u64*)(charPntr + 16) = value64;
|
||||
*(a_u64*)(charPntr + 24) = value64;
|
||||
}
|
||||
|
||||
return pntr;
|
||||
}
|
||||
#endif //!WASM_STD_USE_BUILTIN_MEMSET
|
||||
|
||||
#if !WASM_STD_USE_BUILTIN_MEMCPY
|
||||
void* _memcpy(void* dest, const void* source, size_t numBytes)
|
||||
{
|
||||
unsigned char* destCharPntr = dest;
|
||||
const unsigned char* sourceCharPntr = source;
|
||||
|
||||
uint32_t wVarU32, xVarU32;
|
||||
|
||||
for (; (uintptr_t)sourceCharPntr % 4 && numBytes; numBytes--)
|
||||
{
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
}
|
||||
|
||||
if ((uintptr_t)destCharPntr % 4 == 0)
|
||||
{
|
||||
for (; numBytes >= 16; sourceCharPntr += 16, destCharPntr += 16, numBytes -= 16)
|
||||
{
|
||||
*(a_u32*)(destCharPntr + 0) = *(a_u32*)(sourceCharPntr + 0);
|
||||
*(a_u32*)(destCharPntr + 4) = *(a_u32*)(sourceCharPntr + 4);
|
||||
*(a_u32*)(destCharPntr + 8) = *(a_u32*)(sourceCharPntr + 8);
|
||||
*(a_u32*)(destCharPntr + 12) = *(a_u32*)(sourceCharPntr + 12);
|
||||
}
|
||||
if (numBytes & 8)
|
||||
{
|
||||
*(a_u32*)(destCharPntr + 0) = *(a_u32*)(sourceCharPntr + 0);
|
||||
*(a_u32*)(destCharPntr + 4) = *(a_u32*)(sourceCharPntr + 4);
|
||||
destCharPntr += 8;
|
||||
sourceCharPntr += 8;
|
||||
}
|
||||
if (numBytes & 4)
|
||||
{
|
||||
*(a_u32*)(destCharPntr+0) = *(a_u32*)(sourceCharPntr + 0);
|
||||
destCharPntr += 4;
|
||||
sourceCharPntr += 4;
|
||||
}
|
||||
if (numBytes & 2)
|
||||
{
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
}
|
||||
if (numBytes & 1)
|
||||
{
|
||||
*destCharPntr = *sourceCharPntr;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
if (numBytes >= 32)
|
||||
{
|
||||
switch ((uintptr_t)destCharPntr % 4)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
wVarU32 = *(a_u32*)sourceCharPntr;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
numBytes -= 3;
|
||||
for (; numBytes >= 17; sourceCharPntr += 16, destCharPntr += 16, numBytes -= 16)
|
||||
{
|
||||
xVarU32 = *(a_u32*)(sourceCharPntr + 1);
|
||||
*(a_u32*)(destCharPntr + 0) = ((wVarU32 >> 24) | (xVarU32 << 8));
|
||||
wVarU32 = *(a_u32*)(sourceCharPntr + 5);
|
||||
*(a_u32*)(destCharPntr + 4) = ((xVarU32 >> 24) | (wVarU32 << 8));
|
||||
xVarU32 = *(a_u32*)(sourceCharPntr + 9);
|
||||
*(a_u32*)(destCharPntr + 8) = ((wVarU32 >> 24) | (xVarU32 << 8));
|
||||
wVarU32 = *(a_u32*)(sourceCharPntr + 13);
|
||||
*(a_u32*)(destCharPntr + 12) = ((xVarU32 >> 24) | (wVarU32 << 8));
|
||||
}
|
||||
} break;
|
||||
case 2:
|
||||
{
|
||||
wVarU32 = *(a_u32*)sourceCharPntr;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
numBytes -= 2;
|
||||
for (; numBytes >= 18; sourceCharPntr += 16, destCharPntr += 16, numBytes -= 16)
|
||||
{
|
||||
xVarU32 = *(a_u32*)(sourceCharPntr + 2);
|
||||
*(a_u32*)(destCharPntr + 0) = ((wVarU32 >> 16) | (xVarU32 << 16));
|
||||
wVarU32 = *(a_u32*)(sourceCharPntr + 6);
|
||||
*(a_u32*)(destCharPntr + 4) = ((xVarU32 >> 16) | (wVarU32 << 16));
|
||||
xVarU32 = *(a_u32*)(sourceCharPntr + 10);
|
||||
*(a_u32*)(destCharPntr + 8) = ((wVarU32 >> 16) | (xVarU32 << 16));
|
||||
wVarU32 = *(a_u32*)(sourceCharPntr + 14);
|
||||
*(a_u32*)(destCharPntr + 12) = ((xVarU32 >> 16) | (wVarU32 << 16));
|
||||
}
|
||||
} break;
|
||||
case 3:
|
||||
{
|
||||
wVarU32 = *(a_u32*)sourceCharPntr;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
numBytes -= 1;
|
||||
for (; numBytes >= 19; sourceCharPntr += 16, destCharPntr += 16, numBytes -= 16)
|
||||
{
|
||||
xVarU32 = *(a_u32*)(sourceCharPntr + 3);
|
||||
*(a_u32*)(destCharPntr + 0) = ((wVarU32 >> 8) | (xVarU32 << 24));
|
||||
wVarU32 = *(a_u32*)(sourceCharPntr + 7);
|
||||
*(a_u32*)(destCharPntr + 4) = ((xVarU32 >> 8) | (wVarU32 << 24));
|
||||
xVarU32 = *(a_u32*)(sourceCharPntr + 11);
|
||||
*(a_u32*)(destCharPntr + 8) = ((wVarU32 >> 8) | (xVarU32 << 24));
|
||||
wVarU32 = *(a_u32*)(sourceCharPntr + 15);
|
||||
*(a_u32*)(destCharPntr + 12) = ((xVarU32 >> 8) | (wVarU32 << 24));
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
if (numBytes & 16)
|
||||
{
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
}
|
||||
if (numBytes & 8)
|
||||
{
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
}
|
||||
if (numBytes & 4)
|
||||
{
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
}
|
||||
if (numBytes & 2)
|
||||
{
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
}
|
||||
if (numBytes & 1)
|
||||
{
|
||||
*destCharPntr = *sourceCharPntr;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
#endif //!WASM_STD_USE_BUILTIN_MEMSET
|
||||
|
||||
#if !WASM_STD_USE_BUILTIN_MEMMOVE
|
||||
void* _memmove(void* dest, const void* source, size_t numBytes)
|
||||
{
|
||||
char* destCharPntr = dest;
|
||||
const char* sourceCharPntr = source;
|
||||
|
||||
if (destCharPntr == sourceCharPntr) { return destCharPntr; }
|
||||
if ((uintptr_t)sourceCharPntr - (uintptr_t)destCharPntr - numBytes <= -2 * numBytes)
|
||||
{
|
||||
return memcpy(destCharPntr, sourceCharPntr, numBytes);
|
||||
}
|
||||
|
||||
if (destCharPntr < sourceCharPntr)
|
||||
{
|
||||
if ((uintptr_t)sourceCharPntr % SIZEOF_A_SIZE_T == (uintptr_t)destCharPntr % SIZEOF_A_SIZE_T)
|
||||
{
|
||||
while ((uintptr_t)destCharPntr % SIZEOF_A_SIZE_T)
|
||||
{
|
||||
if (!numBytes--) { return dest; }
|
||||
*destCharPntr++ = *sourceCharPntr++;
|
||||
}
|
||||
for (; numBytes >= SIZEOF_A_SIZE_T; numBytes -= SIZEOF_A_SIZE_T, destCharPntr += SIZEOF_A_SIZE_T, sourceCharPntr += SIZEOF_A_SIZE_T)
|
||||
{
|
||||
*(a_size_t*)destCharPntr = *(a_size_t*)sourceCharPntr;
|
||||
}
|
||||
}
|
||||
for (; numBytes; numBytes--) { *destCharPntr++ = *sourceCharPntr++; }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (((uintptr_t)sourceCharPntr % SIZEOF_A_SIZE_T) == ((uintptr_t)destCharPntr % SIZEOF_A_SIZE_T))
|
||||
{
|
||||
while ((uintptr_t)(destCharPntr + numBytes) % SIZEOF_A_SIZE_T)
|
||||
{
|
||||
if (!numBytes--) { return dest; }
|
||||
destCharPntr[numBytes] = sourceCharPntr[numBytes];
|
||||
}
|
||||
while (numBytes >= SIZEOF_A_SIZE_T)
|
||||
{
|
||||
numBytes -= SIZEOF_A_SIZE_T;
|
||||
*(a_size_t*)(destCharPntr+numBytes) = *(a_size_t*)(sourceCharPntr + numBytes);
|
||||
}
|
||||
}
|
||||
while (numBytes)
|
||||
{
|
||||
numBytes--;
|
||||
destCharPntr[numBytes] = sourceCharPntr[numBytes];
|
||||
}
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
#endif //!WASM_STD_USE_BUILTIN_MEMMOVE
|
||||
|
||||
int memcmp(const void* left, const void* right, size_t numBytes)
|
||||
{
|
||||
const unsigned char *leftByte = left, *rightByte = right;
|
||||
for (; (numBytes && *leftByte == *rightByte); numBytes--, leftByte++, rightByte++);
|
||||
return (numBytes ? *leftByte - *rightByte : 0);
|
||||
}
|
||||
|
||||
int strcmp(const char* left, const char* right)
|
||||
{
|
||||
for (; *left == *right && *left; left++, right++);
|
||||
return (*(unsigned char*)left - *(unsigned char*)right);
|
||||
}
|
||||
|
||||
char* strcpy(char* dest, const char* source)
|
||||
{
|
||||
a_size_t* destWord;
|
||||
const a_size_t* sourceWord;
|
||||
if ((uintptr_t)source % sizeof(size_t) == (uintptr_t)dest % sizeof(size_t))
|
||||
{
|
||||
for (; (uintptr_t)source % sizeof(size_t); source++, dest++)
|
||||
{
|
||||
if (!(*dest=*source)) { return dest; }
|
||||
}
|
||||
destWord = (void*)dest;
|
||||
sourceWord = (const void*)source;
|
||||
for (; !WORD_CONTAINS_ZERO(*sourceWord); *destWord++ = *sourceWord++) { }
|
||||
dest=(void*)destWord;
|
||||
source=(const void*)sourceWord;
|
||||
}
|
||||
for (; (*dest=*source); source++, dest++) { }
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
//TODO: Add strstr implementation!
|
||||
|
||||
int strncmp(const char* left, const char* right, size_t numBytes)
|
||||
{
|
||||
const unsigned char* leftPntr = (void*)left;
|
||||
const unsigned char* rightPntr = (void*)right;
|
||||
if (!numBytes--) { return 0; }
|
||||
for (; (*leftPntr && *rightPntr && numBytes && *leftPntr == *rightPntr); leftPntr++, rightPntr++, numBytes--);
|
||||
return *leftPntr - *rightPntr;
|
||||
}
|
||||
|
||||
size_t strlen(const char* str)
|
||||
{
|
||||
const char* startPntr = str;
|
||||
const a_size_t* wordPntr;
|
||||
//Walk 1 character at a time until we are size_t aligned
|
||||
for (; ((uintptr_t)str % sizeof(size_t)) != 0; str++)
|
||||
{
|
||||
if (!*str) { return str-startPntr; }
|
||||
}
|
||||
//Check size_t bytes at once with WORD_CONTAINS_ZERO
|
||||
for (wordPntr = (const void *)str; !WORD_CONTAINS_ZERO(*wordPntr); wordPntr++) { }
|
||||
str = (const void *)wordPntr;
|
||||
//Walk 0-3 bytes until we find the 0 in the word
|
||||
for (; *str; str++) { }
|
||||
return (str - startPntr);
|
||||
}
|
||||
65
std/src/std_printf.c
Normal file
65
std/src/std_printf.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
File: std_printf.c
|
||||
Author: Taylor Robbins
|
||||
Date: 08\28\2025
|
||||
Description:
|
||||
** None
|
||||
*/
|
||||
|
||||
#define STB_SPRINTF_IMPLEMENTATION
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
|
||||
#include "stb_sprintf.h"
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
//TODO: Should we increase this buffer size? Or make it an option for the user to change? Or dynamically allocate from the stack? Or something else?
|
||||
#define STD_PRINTF_BUFFER_SIZE 1024 //chars
|
||||
char stdGlobalPrintBuffer[STD_PRINTF_BUFFER_SIZE];
|
||||
|
||||
int vsnprintf(char* bufferPntr, size_t bufferSize, const char* formatStr, va_list args)
|
||||
{
|
||||
assert(bufferSize <= INT_MAX);
|
||||
return stbsp_vsnprintf(bufferPntr, bufferSize, formatStr, args);
|
||||
}
|
||||
int vsprintf(char* restrict bufferPntr, const char* restrict formatStr, va_list args)
|
||||
{
|
||||
return vsnprintf(bufferPntr, INT_MAX, formatStr, args);
|
||||
}
|
||||
int vprintf(const char* restrict formatStr, va_list args)
|
||||
{
|
||||
int result = stbsp_vsnprintf(stdGlobalPrintBuffer, STD_PRINTF_BUFFER_SIZE, formatStr, args);
|
||||
if (result > 0 && result < STD_PRINTF_BUFFER_SIZE)
|
||||
{
|
||||
stdGlobalPrintBuffer[result] = '\0'; //ensure null-termination
|
||||
jsStdPrint(&stdGlobalPrintBuffer[0], result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int snprintf(char* restrict bufferPntr, size_t bufferSize, const char* restrict formatStr, ...)
|
||||
{
|
||||
int result;
|
||||
va_list args;
|
||||
va_start(args, formatStr);
|
||||
result = vsnprintf(bufferPntr, bufferSize, formatStr, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
int sprintf(char* restrict bufferPntr, const char* restrict formatStr, ...)
|
||||
{
|
||||
int result;
|
||||
va_list args;
|
||||
va_start(args, formatStr);
|
||||
result = vsprintf(bufferPntr, formatStr, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
int printf(const char* restrict formatStr, ...)
|
||||
{
|
||||
int result;
|
||||
va_list args;
|
||||
va_start(args, formatStr);
|
||||
result = vprintf(formatStr, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
18
std/stdarg.h
Normal file
18
std/stdarg.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
File: stdarg.h
|
||||
Author: Taylor Robbins
|
||||
Date: 08\28\2025
|
||||
*/
|
||||
|
||||
#ifndef _STDARG_H
|
||||
#define _STDARG_H
|
||||
|
||||
typedef __builtin_va_list va_list;
|
||||
typedef __builtin_va_list __isoc_va_list;
|
||||
|
||||
#define va_start(v,l) __builtin_va_start(v,l)
|
||||
#define va_end(v) __builtin_va_end(v)
|
||||
#define va_arg(v,l) __builtin_va_arg(v,l)
|
||||
#define va_copy(d,s) __builtin_va_copy(d,s)
|
||||
|
||||
#endif // _STDARG_H
|
||||
20
std/stddef.h
Normal file
20
std/stddef.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
File: stddef.h
|
||||
Author: Taylor Robbins
|
||||
Date: 08\28\2025
|
||||
*/
|
||||
|
||||
#ifndef _STDDEF_H
|
||||
#define _STDDEF_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if LANGUAGE_IS_CPP
|
||||
#define NULL nullptr
|
||||
#else
|
||||
#define NULL ((void*)0)
|
||||
#endif
|
||||
|
||||
#define offsetof(type, member) __builtin_offsetof(type, member)
|
||||
|
||||
#endif // _STDDEF_H
|
||||
132
std/stdint.h
Normal file
132
std/stdint.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
File: stdint.h
|
||||
Author: Taylor Robbins
|
||||
Date: 08\28\2025
|
||||
*/
|
||||
|
||||
#ifndef _STDINT_H
|
||||
#define _STDINT_H
|
||||
|
||||
// +--------------------------------------------------------------+
|
||||
// | Typedefs |
|
||||
// +--------------------------------------------------------------+
|
||||
#define _Addr long
|
||||
#define _Int64 long long
|
||||
#define _Reg long
|
||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
#define __LONG_MAX 0x7FFFFFFFFFFFFFFFL
|
||||
#if LANGUAGE_IS_C
|
||||
#ifdef __WCHAR_TYPE__
|
||||
typedef __WCHAR_TYPE__ wchar_t;
|
||||
#else
|
||||
typedef long wchar_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef float float_t;
|
||||
typedef double double_t;
|
||||
|
||||
typedef unsigned _Addr size_t;
|
||||
typedef unsigned _Addr uintptr_t;
|
||||
typedef _Addr ptrdiff_t;
|
||||
typedef _Addr ssize_t;
|
||||
typedef _Addr intptr_t;
|
||||
// typedef _Addr regoff_t;
|
||||
// typedef _Reg register_t;
|
||||
// typedef _Int64 time_t;
|
||||
// typedef _Int64 suseconds_t;
|
||||
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef signed _Int64 int64_t;
|
||||
typedef signed _Int64 intmax_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned _Int64 uint64_t;
|
||||
typedef unsigned _Int64 u_int64_t;
|
||||
typedef unsigned _Int64 uintmax_t;
|
||||
|
||||
// typedef unsigned mode_t;
|
||||
// typedef unsigned _Reg nlink_t;
|
||||
// typedef _Int64 off_t;
|
||||
// typedef unsigned _Int64 ino_t;
|
||||
// typedef unsigned _Int64 dev_t;
|
||||
// typedef long blksize_t;
|
||||
// typedef _Int64 blkcnt_t;
|
||||
// typedef unsigned _Int64 fsblkcnt_t;
|
||||
// typedef unsigned _Int64 fsfilcnt_t;
|
||||
|
||||
// typedef unsigned wint_t;
|
||||
// typedef unsigned long wctype_t;
|
||||
|
||||
// typedef void * timer_t;
|
||||
// typedef int clockid_t;
|
||||
// typedef long clock_t;
|
||||
// struct timeval { time_t tv_sec; suseconds_t tv_usec; };
|
||||
// struct timespec { time_t tv_sec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER==__BIG_ENDIAN); long tv_nsec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER!=__BIG_ENDIAN); };
|
||||
|
||||
// typedef int pid_t;
|
||||
// typedef unsigned id_t;
|
||||
// typedef unsigned uid_t;
|
||||
// typedef unsigned gid_t;
|
||||
// typedef int key_t;
|
||||
// typedef unsigned useconds_t;
|
||||
|
||||
// +--------------------------------------------------------------+
|
||||
// | MAX and MIN #defines |
|
||||
// +--------------------------------------------------------------+
|
||||
#define INT8_MIN (-1-0x7f)
|
||||
#define INT16_MIN (-1-0x7fff)
|
||||
#define INT32_MIN (-1-0x7fffffff)
|
||||
#define INT64_MIN (-1-0x7fffffffffffffff)
|
||||
|
||||
#define INT8_MAX (0x7f)
|
||||
#define INT16_MAX (0x7fff)
|
||||
#define INT32_MAX (0x7fffffff)
|
||||
#define INT64_MAX (0x7fffffffffffffff)
|
||||
|
||||
#define UINT8_MAX (0xff)
|
||||
#define UINT16_MAX (0xffff)
|
||||
#define UINT32_MAX (0xffffffffu)
|
||||
#define UINT64_MAX (0xffffffffffffffffu)
|
||||
|
||||
// #define INT_FAST8_MIN INT8_MIN
|
||||
// #define INT_FAST64_MIN INT64_MIN
|
||||
|
||||
// #define INT_LEAST8_MIN INT8_MIN
|
||||
// #define INT_LEAST16_MIN INT16_MIN
|
||||
// #define INT_LEAST32_MIN INT32_MIN
|
||||
// #define INT_LEAST64_MIN INT64_MIN
|
||||
|
||||
// #define INT_FAST8_MAX INT8_MAX
|
||||
// #define INT_FAST64_MAX INT64_MAX
|
||||
|
||||
// #define INT_LEAST8_MAX INT8_MAX
|
||||
// #define INT_LEAST16_MAX INT16_MAX
|
||||
// #define INT_LEAST32_MAX INT32_MAX
|
||||
// #define INT_LEAST64_MAX INT64_MAX
|
||||
|
||||
// #define UINT_FAST8_MAX UINT8_MAX
|
||||
// #define UINT_FAST64_MAX UINT64_MAX
|
||||
|
||||
// #define UINT_LEAST8_MAX UINT8_MAX
|
||||
// #define UINT_LEAST16_MAX UINT16_MAX
|
||||
// #define UINT_LEAST32_MAX UINT32_MAX
|
||||
// #define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
#define INTMAX_MIN INT64_MIN
|
||||
#define INTMAX_MAX INT64_MAX
|
||||
#define UINTMAX_MAX UINT64_MAX
|
||||
|
||||
// #define WINT_MIN 0U
|
||||
// #define WINT_MAX UINT32_MAX
|
||||
|
||||
#define WCHAR_MAX (0x7FFFFFFF+L'\0')
|
||||
#define WCHAR_MIN (-1-0x7FFFFFFF+L'\0')
|
||||
|
||||
#define SIG_ATOMIC_MIN INT32_MIN
|
||||
#define SIG_ATOMIC_MAX INT32_MAX
|
||||
|
||||
#endif // _STDINT_H
|
||||
27
std/stdio.h
Normal file
27
std/stdio.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
File: stdio.h
|
||||
Author: Taylor Robbins
|
||||
Date: 08\28\2025
|
||||
*/
|
||||
|
||||
#ifndef _STDIO_H
|
||||
#define _STDIO_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
MAYBE_START_EXTERN_C
|
||||
|
||||
int vprintf(const char* formatStr, va_list args);
|
||||
// TODO: int vfprintf(FILE*, const char*, va_list args);
|
||||
int vsprintf(char* bufferPntr, const char* formatStr, va_list args);
|
||||
int vsnprintf(char* bufferPntr, size_t bufferSize, const char* formatStr, va_list args);
|
||||
|
||||
int printf(const char* formatStr, ...);
|
||||
// TODO: int fprintf(FILE*, const char*, ...);
|
||||
int sprintf(char* bufferPntr, const char* formatStr, ...);
|
||||
int snprintf(char* bufferPntr, size_t bufferSize, const char* formatStr, ...);
|
||||
|
||||
MAYBE_END_EXTERN_C
|
||||
|
||||
#endif // _STDIO_H
|
||||
56
std/string.h
Normal file
56
std/string.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
File: string.h
|
||||
Author: Taylor Robbins
|
||||
Date: 08\28\2025
|
||||
*/
|
||||
|
||||
#ifndef _STRING_H
|
||||
#define _STRING_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define WASM_STD_USE_BUILTIN_MEMSET 1
|
||||
#define WASM_STD_USE_BUILTIN_MEMCPY 1
|
||||
#define WASM_STD_USE_BUILTIN_MEMMOVE 1
|
||||
|
||||
MAYBE_START_EXTERN_C
|
||||
|
||||
#if WASM_STD_USE_BUILTIN_MEMSET
|
||||
// Basically converts to memory.fill instruction
|
||||
#define memset(pntr, value, numBytes) __builtin_memset((pntr), (value), (numBytes));
|
||||
#else
|
||||
void* _memset(void* pntr, int value, size_t numBytes);
|
||||
#define memset(pntr, value, numBytes) _memset((pntr), (value), (numBytes))
|
||||
#endif
|
||||
|
||||
#if WASM_STD_USE_BUILTIN_MEMCPY
|
||||
// Basically converts to memory.copy instruction
|
||||
#define memcpy(dest, source, numBytes) __builtin_memcpy((dest), (source), (numBytes));
|
||||
#else
|
||||
void* _memcpy(void* dest, const void* source, size_t numBytes);
|
||||
#define memcpy(dest, source, numBytes) _memcpy((dest), (source), (numBytes))
|
||||
#endif
|
||||
|
||||
#if WASM_STD_USE_BUILTIN_MEMMOVE
|
||||
// Basically converts to memory.copy instruction
|
||||
#define memmove(dest, source, numBytes) __builtin_memmove((dest), (source), (numBytes));
|
||||
#else
|
||||
void* _memmove(void* dest, const void* source, size_t numBytes);
|
||||
#define memmove(dest, source, numBytes) _memmove((dest), (source), (numBytes))
|
||||
#endif
|
||||
|
||||
int memcmp(const void* left, const void* right, size_t numBytes);
|
||||
char* strcpy(char* dest, const char* source);
|
||||
// TODO: char* strstr(const char* haystack, const char* needle);
|
||||
|
||||
int strcmp(const char* left, const char* right);
|
||||
int strncmp(const char* left, const char* right, size_t numBytes);
|
||||
size_t strlen(const char* str);
|
||||
// TODO: size_t wcslen(const wchar_t* str);
|
||||
|
||||
//TODO: char *strchr (const char *, int); //NEEDED for slre.c
|
||||
//TODO: char *strrchr (const char *, int); //NEEDED for slre.c
|
||||
|
||||
MAYBE_END_EXTERN_C
|
||||
|
||||
#endif // _STRING_H
|
||||
19
std/uchar.h
Normal file
19
std/uchar.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
File: uchar.h
|
||||
Author: Taylor Robbins
|
||||
Date: 08\28\2025
|
||||
*/
|
||||
|
||||
#ifndef _UCHAR_H
|
||||
#define _UCHAR_H
|
||||
|
||||
typedef unsigned short char16_t;
|
||||
typedef unsigned char32_t;
|
||||
|
||||
// TODO: size_t c16rtomb(char *__restrict, char16_t, mbstate_t *__restrict);
|
||||
// TODO: size_t mbrtoc16(char16_t *__restrict, const char *__restrict, size_t, mbstate_t *__restrict);
|
||||
|
||||
// TODO: size_t c32rtomb(char *__restrict, char32_t, mbstate_t *__restrict);
|
||||
// TODO: size_t mbrtoc32(char32_t *__restrict, const char *__restrict, size_t, mbstate_t *__restrict);
|
||||
|
||||
#endif // _UCHAR_H
|
||||
11
test_app.c
Normal file
11
test_app.c
Normal file
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
File: test_app.c
|
||||
Author: Taylor Robbins
|
||||
Date: 08\28\2025
|
||||
Description:
|
||||
** When no other application is present, this serves as a simple test case for the CWasm layer
|
||||
*/
|
||||
|
||||
#include "cwasm.c"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user