Starting to build a codebase for messing with assembly generation compatible with yasm

This commit is contained in:
Edward R. Gonzalez 2024-11-29 14:31:38 -05:00
parent 531daa38c1
commit 80c830b59d
18 changed files with 26940 additions and 1 deletions

View File

@ -14,7 +14,7 @@ indent_size = 4
[*.{h, c, hpp, cpp}]
indent_style = tab
indent_size = 4
indent_size = 2
[*.{ps1, psm1}]
indent_style = tab

37
.vscode/c_cpp_propertiees.json vendored Normal file
View File

@ -0,0 +1,37 @@
{
"configurations": [
{
"name": "Win32 msvc",
"includePath": [
"${workspaceFolder}/source/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE",
"INTELLISENSE_DIRECTIVES"
],
"windowsSdkVersion": "10.0.19041.0",
"compilerPath": "C:/Program Files/Microsoft Visual Studio/2022/Professional/VC/Tools/MSVC/14.29.30133/bin/HostX64/x64/cl.exe",
"intelliSenseMode": "msvc-x64",
"compileCommands": "${workspaceFolder}/project/build/compile_commands.json"
},
{
"name": "Win32 clang",
"includePath": [
"${workspaceFolder}/source/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE",
"INTELLISENSE_DIRECTIVES"
],
"windowsSdkVersion": "10.0.19041.0",
"compilerPath": "C:/Users/Ed/scoop/apps/llvm/current/bin/clang++.exe",
"intelliSenseMode": "windows-clang-x64",
"compileCommands": "${workspaceFolder}/project/build/compile_commands.json"
}
],
"version": 4
}

9
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,9 @@
{
"files.associations": {
"*.rmd": "markdown",
"pop_ignores.inline.h": "c",
"basic_types.h": "c",
"push_ignores.inline.h": "c",
"memory.h": "c"
}
}

View File

@ -1,6 +1,9 @@
$misc = join-path $PSScriptRoot 'helpers/misc.ps1'
. $misc
$update_deps = join-path $PSScriptRoot 'update_deps.ps1'
. $update_deps
$path_root = git rev-parse --show-toplevel
$path_build = join-path $path_root 'build'
$path_scripts = join-path $path_root 'scripts'

15
scripts/update_deps.ps1 Normal file
View File

@ -0,0 +1,15 @@
$misc = join-path $PSScriptRoot 'helpers/misc.ps1'
. $misc
$path_root = git rev-parse --show-toplevel
$path_build = join-path $path_root 'build'
$path_scripts = join-path $path_root 'scripts'
$path_source = join-path $path_root 'source'
$path_toolchain = join-path $path_root 'toolchain'
$url_yasm = 'https://github.com/yasm/yasm.git'
$path_yasm = join-path $path_toolchain 'yasm'
$path_libyasm = join-path $path_yasm 'libyasm'
clone-gitrepo $path_yasm $url_yasm

128
source/base/basic_types.h Normal file
View File

@ -0,0 +1,128 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "macros.hpp"
#endif
#pragma region Basic Types
#define U8_MIN 0u
#define U8_MAX 0xffu
#define I8_MIN ( -0x7f - 1 )
#define I8_MAX 0x7f
#define U16_MIN 0u
#define U16_MAX 0xffffu
#define I16_MIN ( -0x7fff - 1 )
#define I16_MAX 0x7fff
#define U32_MIN 0u
#define U32_MAX 0xffffffffu
#define I32_MIN ( -0x7fffffff - 1 )
#define I32_MAX 0x7fffffff
#define U64_MIN 0ull
#define U64_MAX 0xffffffffffffffffull
#define I64_MIN ( -0x7fffffffffffffffll - 1 )
#define I64_MAX 0x7fffffffffffffffll
#if defined( ARCH_32_BIT )
# define USIZE_MIN GEN_U32_MIN
# define USIZE_MAX GEN_U32_MAX
# define ISIZE_MIN GEN_S32_MIN
# define ISIZE_MAX GEN_S32_MAX
#elif defined( ARCH_64_BIT )
# define USIZE_MIN GEN_U64_MIN
# define USIZE_MAX GEN_U64_MAX
# define ISIZE_MIN GEN_I64_MIN
# define ISIZE_MAX GEN_I64_MAX
#else
# error Unknown architecture size. This library only supports 32 bit and 64 bit architectures.
#endif
#define F32_MIN 1.17549435e-38f
#define F32_MAX 3.40282347e+38f
#define F64_MIN 2.2250738585072014e-308
#define F64_MAX 1.7976931348623157e+308
#if defined( GEN_COMPILER_MSVC )
# if _MSC_VER < 1300
typedef unsigned char u8;
typedef signed char s8;
typedef unsigned short u16;
typedef signed short s16;
typedef unsigned int u32;
typedef signed int s32;
# else
typedef unsigned __int8 u8;
typedef signed __int8 s8;
typedef unsigned __int16 u16;
typedef signed __int16 s16;
typedef unsigned __int32 u32;
typedef signed __int32 s32;
# endif
typedef unsigned __int64 u64;
typedef signed __int64 s64;
#else
# include <stdint.h>
typedef uint8_t u8;
typedef int8_t s8;
typedef uint16_t u16;
typedef int16_t s16;
typedef uint32_t u32;
typedef int32_t s32;
typedef uint64_t u64;
typedef int64_t s64;
#endif
static_assert( sizeof( u8 ) == sizeof( s8 ), "sizeof(u8) != sizeof(s8)" );
static_assert( sizeof( u16 ) == sizeof( s16 ), "sizeof(u16) != sizeof(s16)" );
static_assert( sizeof( u32 ) == sizeof( s32 ), "sizeof(u32) != sizeof(s32)" );
static_assert( sizeof( u64 ) == sizeof( s64 ), "sizeof(u64) != sizeof(s64)" );
static_assert( sizeof( u8 ) == 1, "sizeof(u8) != 1" );
static_assert( sizeof( u16 ) == 2, "sizeof(u16) != 2" );
static_assert( sizeof( u32 ) == 4, "sizeof(u32) != 4" );
static_assert( sizeof( u64 ) == 8, "sizeof(u64) != 8" );
typedef size_t usize;
typedef ptrdiff_t ssize;
static_assert( sizeof( usize ) == sizeof( ssize ), "sizeof(usize) != sizeof(ssize)" );
// NOTE: (u)zpl_intptr is only here for semantic reasons really as this library will only support 32/64 bit OSes.
#if defined( _WIN64 )
typedef signed __int64 sptr;
typedef unsigned __int64 uptr;
#elif defined( _WIN32 )
// NOTE; To mark types changing their size, e.g. zpl_intptr
# ifndef _W64
# if ! defined( __midl ) && ( defined( _X86_ ) || defined( _M_IX86 ) ) && _MSC_VER >= 1300
# define _W64 __w64
# else
# define _W64
# endif
# endif
typedef _W64 signed int sptr;
typedef _W64 unsigned int uptr;
#else
typedef uintptr_t uptr;
typedef intptr_t sptr;
#endif
static_assert( sizeof( uptr ) == sizeof( sptr ), "sizeof(uptr) != sizeof(sptr)" );
typedef float f32;
typedef double f64;
static_assert( sizeof( f32 ) == 4, "sizeof(f32) != 4" );
static_assert( sizeof( f64 ) == 8, "sizeof(f64) != 8" );
typedef s8 b8;
typedef s16 b16;
typedef s32 b32;
typedef void* memptr;
typedef void const* memptr_const;
#pragma endregion Basic Types

63
source/base/debug.h Normal file
View File

@ -0,0 +1,63 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "basic_types.hpp"
#endif
#pragma region Debug
#if defined( _MSC_VER )
# if _MSC_VER < 1300
# define DEBUG_TRAP() __asm int 3 /* Trap to debugger! */
# else
# define debug_trap() __debugbreak()
# endif
#elif defined( GEN_COMPILER_TINYC )
# define DEBUG_TRAP() process_exit( 1 )
#else
# define DEBUG_TRAP() __builtin_trap()
#endif
#define ASSERT( cond ) ASSERT( cond, NULL )
#define ASSERT_MSG( cond, msg, ... ) \
do \
{ \
if ( ! ( cond ) ) \
{ \
assert_handler( #cond, __FILE__, scast( s64, __LINE__ ), msg, ##__VA_ARGS__ ); \
GEN_DEBUG_TRAP(); \
} \
} while ( 0 )
#define ASSERT_NOT_NULL( ptr ) ASSERT_MSG( ( ptr ) != NULL, #ptr " must not be NULL" )
// NOTE: Things that shouldn't happen with a message!
#define PANIC( msg, ... ) ASSERT_MSG( 0, msg, ##__VA_ARGS__ )
#if Build_Debug
#define FATAL( ... ) \
do \
{ \
local_persist thread_local \
char buf[GEN_PRINTF_MAXLEN] = { 0 }; \
\
str_fmt(buf, PRINTF_MAXLEN, __VA_ARGS__); \
PANIC(buf); \
} \
while (0)
#else
# define FATAL( ... ) \
do \
{ \
str_fmt_out_err( __VA_ARGS__ ); \
process_exit(1); \
} \
while (0)
#endif
void assert_handler( char const* condition, char const* file, s32 line, char const* msg, ... );
s32 assert_crash( char const* condition );
void process_exit( u32 code );
#pragma endregion Debug

183
source/base/macros.h Normal file
View File

@ -0,0 +1,183 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
#endif
#pragma region Macros
#ifndef global
#define global static // Global variables
#endif
#ifndef internal
#define internal static // Internal linkage
#endif
#ifndef local_persist
#define local_persist static // Local Persisting variables
#endif
#ifndef api_c
#define api_c extern "C"
#endif
#ifndef bit
#define bit( Value ) ( 1 << Value )
#define bitfield_is_equal( Type, Field, Mask ) ( (Type(Mask) & Type(Field)) == Type(Mask) )
#endif
#ifndef cast
#define cast( type, value ) ( (type)(value) )
#endif
#ifndef ccast
#define ccast( type, value ) ( const_cast< type >( (value) ) )
#endif
#ifndef pcast
#define pcast( type, value ) ( * reinterpret_cast< type* >( & ( value ) ) )
#endif
#ifndef rcast
#define rcast( type, value ) reinterpret_cast< type >( value )
#endif
#ifndef scast
#define scast( type, value ) static_cast< type >( value )
#endif
#ifndef stringize
#define stringize_va( ... ) #__VA_ARGS__
#define stringize( ... ) stringize_va( __VA_ARGS__ )
#endif
#ifndef do_once
#define do_once( statement ) for ( local_persist b32 once = true; once; once = false, (statement) )
#define do_once_start \
do \
{ \
local_persist \
bool done = false; \
if ( done ) \
break; \
done = true;
#define do_once_end \
} \
while(0);
#endif
#ifndef labeled_scope_start
#define labeled_scope_start if ( false ) {
#define labeled_scope_end }
#endif
#ifndef compiler_decorated_func_name
# ifdef COMPILER_CLANG
# define compiler_decorated_func_name __PRETTY_NAME__
# elif defined(COMPILER_MSVC)
# define compiler_decorated_func_name __FUNCDNAME__
# endif
#endif
#ifndef num_args_impl
#define num_args_impl( _0, \
_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
_11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
_21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
_31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
_41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
_51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \
_61, _62, _63, _64, _65, _66, _67, _68, _69, _70, \
_71, _72, _73, _74, _75, _76, _77, _78, _79, _80, \
_81, _82, _83, _84, _85, _86, _87, _88, _89, _90, \
_91, _92, _93, _94, _95, _96, _97, _98, _99, _100, \
N, ... \
) N
// ## deletes preceding comma if _VA_ARGS__ is empty (GCC, Clang)
#define num_args(...) \
num_args_impl(_, ## __VA_ARGS__, \
100, 99, 98, 97, 96, 95, 94, 93, 92, 91, \
90, 89, 88, 87, 86, 85, 84, 83, 82, 81, \
80, 79, 78, 77, 76, 75, 74, 73, 72, 71, \
70, 69, 68, 67, 66, 65, 64, 63, 62, 61, \
60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \
50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \
40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \
30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \
20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \
10, 9, 8, 7, 6, 5, 4, 3, 2, 1, \
0 \
)
#endif
#ifndef clamp
#define clamp( x, lower, upper ) min( max( ( x ), ( lower ) ), ( upper ) )
#endif
#ifndef count_of
#define count_of( x ) ( ( size_of( x ) / size_of( 0 [ x ] ) ) / ( ( ssize )( ! ( size_of( x ) % size_of( 0 [ x ] ) ) ) ) )
#endif
#ifndef is_between
#define is_between( x, lower, upper ) ( ( ( lower ) <= ( x ) ) && ( ( x ) <= ( upper ) ) )
#endif
#ifndef size_of
#define size_of( x ) ( ssize )( sizeof( x ) )
#endif
#ifndef max
#define max( a, b ) ( (a > b) ? (a) : (b) )
#endif
#ifndef min
#define min( a, b ) ( (a < b) ? (a) : (b) )
#endif
#if defined( _MSC_VER ) || defined( GEN_COMPILER_TINYC )
# define offset_of( Type, element ) ( ( GEN_NS( ssize ) ) & ( ( ( Type* )0 )->element ) )
#else
# define offset_of( Type, element ) __builtin_offsetof( Type, element )
#endif
#ifndef forceinline
# ifdef GEN_COMPILER_MSVC
# define forceinline __forceinline
# define neverinline __declspec( noinline )
# elif defined(GEN_COMPILER_GCC)
# define forceinline inline __attribute__((__always_inline__))
# define neverinline __attribute__( ( __noinline__ ) )
# elif defined(GEN_COMPILER_CLANG)
# if __has_attribute(__always_inline__)
# define forceinline inline __attribute__((__always_inline__))
# define neverinline __attribute__( ( __noinline__ ) )
# else
# define forceinline
# define neverinline
# endif
# else
# define forceinline
# define neverinline
# endif
#endif
#ifndef neverinline
# ifdef GEN_COMPILER_MSVC
# define neverinline __declspec( noinline )
# elif defined(GEN_COMPILER_GCC)
# define neverinline __attribute__( ( __noinline__ ) )
# elif defined(GEN_COMPILER_CLANG)
# if __has_attribute(__always_inline__)
# define neverinline __attribute__( ( __noinline__ ) )
# else
# define neverinline
# endif
# else
# define neverinline
# endif
#endif
#if !defined(typeof) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 202311L)
# if defined(_MSC_VER)
# define typeof(x) __typeof(x)
# elif defined(__GNUC__) || defined(__clang__)
# define typeof(x) __typeof__(x)
# else
# error "Compiler not supported"
# endif
#endif
#pragma endregion Macros

25
source/base/memory.h Normal file
View File

@ -0,0 +1,25 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "debug.h"
#endif
#pragma region Memory
#define kilobytes( x ) ( ( x ) * ( s64 )( 1024 ) )
#define megabytes( x ) ( kilobytes( x ) * ( s64 )( 1024 ) )
#define gigabytes( x ) ( megabytes( x ) * ( s64 )( 1024 ) )
#define terabytes( x ) ( gigabytes( x ) * ( s64 )( 1024 ) )
#define _ONES ( cast( usize, - 1) / U8_MAX )
#define _HIGHS ( GEN__ONES * ( U8_MAX / 2 + 1 ) )
#define _HAS_ZERO( x ) ( ( ( x ) - _ONES ) & ~( x ) & _HIGHS )
#define swap( a, b ) \
do { \
typeof(a) \
temp = (a); \
(a) = (b); \
(b) = temp; \
} while(0)
#pragma endregion Memory

115
source/base/platform.h Normal file
View File

@ -0,0 +1,115 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
#endif
#pragma region Platform Detection
/* Platform architecture */
#if defined( _WIN64 ) || defined( __x86_64__ ) || defined( _M_X64 ) || defined( __64BIT__ ) || defined( __powerpc64__ ) || defined( __ppc64__ ) || defined( __aarch64__ )
# ifndef ARCH_64_BIT
# define ARCH_64_BIT 1
# endif
#else
# ifndef ARCH_32_BItxt_StrCaT
# define ARCH_32_BIT 1
# endif
#endif
/* Platform OS */
#if defined( _WIN32 ) || defined( _WIN64 )
# ifndef SYSTEM_WINDOWS
# define SYSTEM_WINDOWS 1
# endif
#elif defined( __APPLE__ ) && defined( __MACH__ )
# ifndef SYSTEM_OSX
# define SYSTEM_OSX 1
# endif
# ifndef SYSTEM_MACOS
# define SYSTEM_MACOS 1
# endif
# include <TargetConditionals.h>
# if TARGET_IPHONE_SIMULATOR == 1 || TARGET_OS_IPHONE == 1
# ifndef SYSTEM_IOS
# define SYSTEM_IOS 1
# endif
# endif
#elif defined( __unix__ )
# ifndef SYSTEM_UNIX
# define SYSTEM_UNIX 1
# endif
# if defined( ANDROID ) || defined( __ANDROID__ )
# ifndef SYSTEM_ANDROID
# define SYSTEM_ANDROID 1
# endif
# ifndef SYSTEM_LINUX
# define SYSTEM_LINUX 1
# endif
# elif defined( __linux__ )
# ifndef SYSTEM_LINUX
# define SYSTEM_LINUX 1
# endif
# elif defined( __FreeBSD__ ) || defined( __FreeBSD_kernel__ )
# ifndef SYSTEM_FREEBSD
# define SYSTEM_FREEBSD 1
# endif
# elif defined( __OpenBSD__ )
# ifndef SYSTEM_OPENBSD
# define SYSTEM_OPENBSD 1
# endif
# elif defined( __EMSCRIPTEN__ )
# ifndef SYSTEM_EMSCRIPTEN
# define SYSTEM_EMSCRIPTEN 1
# endif
# elif defined( __CYGWIN__ )
# ifndef SYSTEM_CYGWIN
# define SYSTEM_CYGWIN 1
# endif
# else
# error This UNIX operating system is not supported
# endif
#else
# error This operating system is not supported
#endif
/* Platform compiler */
#if defined( _MSC_VER )
# define COMPILER_MSVC 1
#elif defined( __GNUC__ )
# define COMPILER_GCC 1
#elif defined( __clang__ )
# define COMPILER_CLANG 1
#elif defined( __MINGW32__ )
# define COMPILER_MINGW 1
# error Unknown compiler
#endif
#if defined( __has_attribute )
# define HAS_ATTRIBUTE( attribute ) __has_attribute( attribute )
#else
# define HAS_ATTRIBUTE( attribute ) ( 0 )
#endif
#if defined(GCC_VERSION_CHECK)
# undef GCC_VERSION_CHECK
#endif
#if defined(GCC_VERSION)
# define GCC_VERSION_CHECK(major,minor,patch) (GCC_VERSION >= VERSION_ENCODE(major, minor, patch))
#else
# define GCC_VERSION_CHECK(major,minor,patch) (0)
#endif
#pragma endregion Platform Detection
#pragma region Mandatory Includes
# include <stdarg.h>
# include <stddef.h>
# if defined( SYSTEM_WINDOWS )
# include <intrin.h>
# endif
#pragma endregion Mandatory Includes

View File

@ -0,0 +1,7 @@
#ifdef __clang__
# pragma clang diagnostic pop
#endif
#ifdef __GNUC__
# pragma GCC diagnostic pop
#endif

View File

@ -0,0 +1,18 @@
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunused-const-variable"
# pragma clang diagnostic ignored "-Wunused-but-set-variable"
# pragma clang diagnostic ignored "-Wswitch"
# pragma clang diagnostic ignored "-Wunused-variable"
# pragma clang diagnostic ignored "-Wunknown-pragmas"
# pragma clang diagnostic ignored "-Wvarargs"
# pragma clang diagnostic ignored "-Wunused-function"
#endif
#ifdef __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunknown-pragmas"
# pragma GCC diagnostic ignored "-Wcomment"
# pragma GCC diagnostic ignored "-Wswitch"
# pragma GCC diagnostic ignored "-Wunused-variable"
#endif

9
source/gen_asm.c Normal file
View File

@ -0,0 +1,9 @@
#include "base/push_ignores.inline.h"
#include "base/platform.h"
#include "base/macros.h"
#include "base/basic_types.h"
#include "base/debug.h"
#include "base/memory.h"
#include "base/pop_ignores.inline.h"

43
source_asm/hello.asm Normal file
View File

@ -0,0 +1,43 @@
; hello.asm - Hello World with debug symbols for NASM
BITS 64 ; Explicitly specify 64-bit mode
DEFAULT REL ; Use RIP-relative addressing by default
; Data section
section .data
message db "Hello, World!", 13, 10, 0 ; String with CRLF and null terminator
message_len equ $ - message ; Calculate string length
; Code section
section .text
global main ; Export main symbol for linker
extern ExitProcess ; Import Windows API functions
extern GetStdHandle
extern WriteConsoleA
main:
; Function prologue
push rbp
mov rbp, rsp
sub rsp, 32 ; Shadow space for Windows API calls
; Get stdout handle
mov ecx, -11 ; STD_OUTPUT_HANDLE
call GetStdHandle
mov rbx, rax ; Save handle for WriteConsole
; Write message
mov rcx, rbx ; Console handle
lea rdx, [message] ; Message buffer
mov r8d, message_len ; Message length
lea r9, [rsp+28] ; Written chars (unused)
mov qword [rsp+20], 0 ; Reserved (must be 0)
call WriteConsoleA
; Exit program
xor ecx, ecx ; Exit code 0
call ExitProcess
; Function epilogue (not reached due to ExitProcess)
leave
ret

26283
toolchain/gencpp/gen.hpp Normal file

File diff suppressed because it is too large Load Diff

1
toolchain/yasm Submodule

@ -0,0 +1 @@
Subproject commit 121ab150b3577b666c79a79f4a511798d7ad2432