Merge tag 'v0.9.14-alpha' into odin

# Conflicts:
#	src/df/core/df_core.mdesk
#	src/df/core/generated/df_core.meta.c
#	src/df/core/generated/df_core.meta.h
#	src/df/gfx/df_gfx.mdesk
#	src/df/gfx/df_view_rules.c
#	src/df/gfx/generated/df_gfx.meta.c
#	src/font_cache/font_cache.c
#	src/raddbg/generated/raddbg.meta.h

Need to redo the view rules
This commit is contained in:
ed
2024-11-24 19:12:20 -05:00
510 changed files with 316813 additions and 178608 deletions
+1
View File
@@ -0,0 +1 @@
*.sh text=auto eol=lf
+2
View File
@@ -28,3 +28,5 @@ jobs:
call build rdi_from_pdb clang debug || exit /b 1 call build rdi_from_pdb clang debug || exit /b 1
call build rdi_from_dwarf clang debug || exit /b 1 call build rdi_from_dwarf clang debug || exit /b 1
call build rdi_dump clang debug || exit /b 1 call build rdi_dump clang debug || exit /b 1
call build radlink msvc debug || exit /b 1
call build radlink clang debug || exit /b 1
+124 -59
View File
@@ -17,7 +17,7 @@ with any information you can gather, like dump files (along with the build you
used), instructions to reproduce, test executables, and so on. used), instructions to reproduce, test executables, and so on.
You can download pre-built binaries for the debugger You can download pre-built binaries for the debugger
[here](https://github.com/EpicGames/raddebugger/releases). [here](https://github.com/EpicGamesExt/raddebugger/releases).
The RAD Debugger project aims to simplify the debugger by simplifying and The RAD Debugger project aims to simplify the debugger by simplifying and
unifying the underlying debug info format. In that pursuit we've built the RAD unifying the underlying debug info format. In that pursuit we've built the RAD
@@ -90,13 +90,12 @@ You should see the following output:
``` ```
[debug mode] [debug mode]
[msvc compile] [msvc compile]
[default mode, assuming `raddbg` build]
metagen_main.c metagen_main.c
searching C:\devel\raddebugger/src... 299 files found searching C:\devel\raddebugger/src... 309 files found
parsing metadesk... 12 metadesk files parsed parsing metadesk... 15 metadesk files parsed
gathering tables... 37 tables found gathering tables... 96 tables found
generating layer code... generating layer code...
raddbg.cpp raddbg_main.c
``` ```
If everything worked correctly, there will be a `build` folder in the root If everything worked correctly, there will be a `build` folder in the root
@@ -159,6 +158,45 @@ like remote debugging, porting to different architectures, further improving
the debugger's features (like improving the visualization engine), and so on. the debugger's features (like improving the visualization engine), and so on.
But for now, we're mostly focused on those first two phases. But for now, we're mostly focused on those first two phases.
---
# The RAD Linker
The RAD Linker is a new performance linker for generating x64 PE/COFF binaries. It is designed to be very fast when creating gigantic executables. It generates standard PDB files for debugging, but it can also optionally create RAD Debugger debug info too (useful for huge executables that otherwise create broken PDBs that overflow internal 32-bit tables).
The RAD Linker is primarily optimized to handle huge linking projects - in our test cases (where debug info is multiple gigabytes), we see 50% faster link times.
The command line syntax is fully compatible with MSVC and you can get a full list of implemented switches from `/help`.
Our current designed-for use case for the linker is to help with the compile-debug cycle of huge projects. We don't yet have support for dead-code-elimination or link-time-optimizations, but these features are on the road map.
By default, the RAD linker spawns as many threads as there are cores, so if you plan to run multiple linkers in parallel, you can limit the number of thread workers via `/rad_workers`.
We also have support for large memory pages, which, when enabled, reduce link time by
another 25%. To link with large pages, you need to explicitly request them via `/rad_large_pages`. Large pages are off by default, since Windows support for large pages is a bit buggy - we recommend they only be used in Docker or VM images where the environment is reset after each link. In a standard Windows environment, using large pages otherwise will fragment memory quickly forcing a reboot. We are working on a Linux port of the linker that will be able to build with large pages robustly.
## Short Term Roadmap
- Porting linker to Linux (for Windows executables, just running on Linux).
- Debug info features
- Get DWARF debug info converter up-and-running.
- Smooth out rough edges in RADDBGI builder.
- Improve build speed further (especially for tiny and mid sizes projects).
- Other features to come
- Dead-code-elimination via `/opt:ref`.
- Link Time Optimizations with the help of clang (we won't support LTCG from MSVC compiler since it is undocumented).
## To build the RAD Linker
- Setup development environment, [see](#Development-Setup-Instructions)
- Run `build radlink release` or if you have clang installed `build radlink release clang`. We favor latter option for better code generation.
If build was successful linker executable is placed in `build` folder under `radlink.exe`.
## Benchmarks
![AMD Ryzen Threadripper PRO 3995WX 64-Cores, 256 GiB RAM (Windows x64)](https://github.com/user-attachments/assets/a95b382a-76b4-4a4c-b809-b61fe25e667a)
---
## Top-Level Directory Descriptions ## Top-Level Directory Descriptions
- `data`: Small binary files which are used when building, either to embed - `data`: Small binary files which are used when building, either to embed
@@ -169,7 +207,8 @@ After setting up the codebase and building, the following directories will
also exist: also exist:
- `build`: All build artifacts. Not checked in to version control. - `build`: All build artifacts. Not checked in to version control.
- `local`: Local files, used for local build configuration input files. - `local`: Local files, used for local build configuration input files. Not
checked in to version control.
## Codebase Introduction ## Codebase Introduction
@@ -202,6 +241,8 @@ not depend on any other layers in the codebase. The folders which contain these
layers are prefixed with `lib_`, like `lib_rdi_format`. layers are prefixed with `lib_`, like `lib_rdi_format`.
A list of the layers in the codebase and their associated namespaces is below: A list of the layers in the codebase and their associated namespaces is below:
- `async` (`ASYNC_`): Implements a system for asynchronous work to be queued
and executed on a thread pool.
- `base` (no namespace): Universal, codebase-wide constructs. Strings, math, - `base` (no namespace): Universal, codebase-wide constructs. Strings, math,
memory allocators, helper macros, command-line parsing, and so on. Depends memory allocators, helper macros, command-line parsing, and so on. Depends
on no other codebase layers. on no other codebase layers.
@@ -213,55 +254,70 @@ A list of the layers in the codebase and their associated namespaces is below:
processes. Runs in lockstep with attached processes. When it runs, attached processes. Runs in lockstep with attached processes. When it runs, attached
processes are halted. When attached processes are running, it is halted. processes are halted. When attached processes are running, it is halted.
Driven by a debugger frontend on another thread. Driven by a debugger frontend on another thread.
- `dasm` (`DASM_`): An asynchronous disassembly decoder and cache. Users ask for - `dasm_cache` (`DASM_`): An asynchronous disassembly decoder and cache. Users
disassembly for a particular virtual address range in a process, and threads ask for disassembly for some data, with a particular architecture, and other
implemented in this layer decode and cache the disassembly for that range. various parameters, and threads implemented in this layer decode and cache the
disassembly for that data with those parameters.
- `dbgi` (`DI_`): An asynchronous debug info loader and cache. Loads debug info - `dbgi` (`DI_`): An asynchronous debug info loader and cache. Loads debug info
stored in the RDI format. Users ask for debug info for a particular path, and stored in the RDI format. Users ask for debug info for a particular path, and
on separate threads, this layer loads the associated debug info file. If on separate threads, this layer loads the associated debug info file. If
necessary, it will launch a separate conversion process to convert original necessary, it will launch a separate conversion process to convert original
debug info into the RDI format. debug info into the RDI format.
- `demon` (`DEMON_`): An abstraction layer for local-machine, low-level process - `dbg_engine` (`D_`): Implements the core debugger system, without any
graphical components. This contains top-level logic for things like stepping,
launching, freezing threads, mid-run breakpoint addition, some caching layers,
and so on.
- `demon` (`DMN_`): An abstraction layer for local-machine, low-level process
control. The abstraction is used to provide a common interface for process control. The abstraction is used to provide a common interface for process
control on target platforms. Used to implement part of `ctrl`. control on target platforms. Used to implement part of `ctrl`.
- `df/core` (`DF_`): The debugger's non-graphical frontend. Implements a - `draw` (`DR_`): Implements a high-level graphics drawing API for the
debugger "entity cache" (where "entities" include processes, threads, modules, debugger's purposes, using the underlying `render` abstraction layer. Provides
breakpoints, source files, targets, and so on). Implements a command loop high-level APIs for various draw commands, but takes care of batching them,
for driving process control, which is used to implement stepping commands and and so on.
user breakpoints. Implements extractors and caches for various entity-related - `eval` (`E_`): Implements a compiler for an expression language built for
data, like full thread unwinds and local variable maps. Also implements core evaluation of variables, registers, types, and more, from debugger-attached
building blocks for evaluation and evaluation visualization. processes, debug info, debugger state, and files. Broken into several phases
- `df/gfx` (`DF_`): The debugger's graphical frontend. Builds on top of mostly corresponding to traditional compiler phases - lexer, parser,
`df/core` to provide all graphical features, including windows, panels, all type-checker, IR generation, and IR evaluation.
of the various debugger interfaces, and evaluation visualization. - `eval_visualization` (`EV_`): Implements the core non-graphical evaluation
- `draw` (`D_`): Implements a high-level graphics drawing API for the debugger's visualization engine, which can be used to visualize evaluations (provided by
purposes, using the underlying `render` abstraction layer. Provides high-level the `eval` layer) in a number of ways. Implements core data structures and
APIs for various draw commands, but takes care of batching them, and so on. transforms for the `Watch` view.
- `eval` (`EVAL_`): Implements a compiler for an expression language built for - `file_stream` (`FS_`): Provides asynchronous file loading, storing the
evaluation of variables, registers, and so on from debugger-attached processes artifacts inside of the cache implemented by the `hash_store` layer, and
and/or debug info. Broken into several phases mostly corresponding to hot-reloading the contents of files when they change. Allows callers to map
traditional compiler phases - lexer, parser, type-checker, IR generation, and file paths to data hashes, which can then be used to obtain the file's data.
IR evaluation. - `font_cache` (`FNT_`): Implements a cache of rasterized font data, both in
- `font_cache` (`F_`): Implements a cache of rasterized font data, both in CPU- CPU-side data for text shaping, and in GPU texture atlases for rasterized
side data for text shaping, and in GPU texture atlases for rasterized glyphs. glyphs. All cache information is sourced from the `font_provider` abstraction
All cache information is sourced from the `font_provider` abstraction layer. layer.
- `font_provider` (`FP_`): An abstraction layer for various font file decoding - `font_provider` (`FP_`): An abstraction layer for various font file decoding
and font rasterization backends. and font rasterization backends.
- `fuzzy_search` (`FZY_`): Provides a fuzzy searching engine for doing
large, asynchronous fuzzy searches. Used by the debugger for implementing
things like the symbol lister or the `Procedures` view, which search across
all loaded debug info records, using fuzzy matching rules.
- `geo_cache` (`GEO_`): Implements an asynchronously-filled cache for GPU - `geo_cache` (`GEO_`): Implements an asynchronously-filled cache for GPU
geometry data, filled by data sourced in the `hash_store` layer's cache. Used geometry data, filled by data sourced in the `hash_store` layer's cache. Used
for asynchronously preparing data for memory visualization in the debugger. for asynchronously preparing data for visualization.
- `hash_store` (`HS_`): Implements a cache for general data blobs, keyed by a - `hash_store` (`HS_`): Implements a cache for general data blobs, keyed by a
128-bit hash of the data. Used as a general data store by other layers. 128-bit hash of the data. Also implements a 128-bit key cache on top, where
the keys refer to a unique identity, associated with a 128-bit hash, where the
hash may change across time. Used as a general data store by other layers.
- `lib_raddbg_markup` (`RADDBG_`): Standalone library for marking up user - `lib_raddbg_markup` (`RADDBG_`): Standalone library for marking up user
programs to work with various features in the `raddbg` debugger. Does not programs to work with various features in the debugger. Does not depend on
depend on `base`, and can be independently relocated to other codebases. `base`, and can be independently relocated to other codebases.
- `lib_rdi_make` (`RDIM_`): Standalone library for constructing RDI debug info
data. Does not depend on `base`, and can be independently relocated
to other codebases.
- `lib_rdi_format` (`RDI_`): Standalone library which defines the core RDI types - `lib_rdi_format` (`RDI_`): Standalone library which defines the core RDI types
and helper functions for reading and writing the RDI debug info file format. and helper functions for reading and writing the RDI debug info file format.
Does not depend on `base`, and can be independently relocated to other Does not depend on `base`, and can be independently relocated to other
codebases. codebases.
- `lib_rdi_make` (`RDIM_`): Standalone library for constructing RDI debug info
data. Does not depend on `base`, and can be independently relocated
to other codebases.
- `mdesk` (`MD_`): Code for parsing Metadesk files (stored as `.mdesk`), which
is the JSON-like (technically a JSON superset) text format used for the
debugger's user and project configuration files, view rules, and metacode,
which is parsed and used to generate code with the `metagen` layer.
- `metagen` (`MG_`): A metaprogram which is used to generate primarily code and - `metagen` (`MG_`): A metaprogram which is used to generate primarily code and
data tables. Consumes Metadesk files, stored with the extension `.mdesk`, and data tables. Consumes Metadesk files, stored with the extension `.mdesk`, and
generates C code which is then included by hand-written C code. Currently, it generates C code which is then included by hand-written C code. Currently, it
@@ -279,6 +335,9 @@ A list of the layers in the codebase and their associated namespaces is below:
- `msf` (`MSF_`): Code for parsing and/or writing the MSF file format. - `msf` (`MSF_`): Code for parsing and/or writing the MSF file format.
- `mule` (no namespace): Test executables for battle testing debugger - `mule` (no namespace): Test executables for battle testing debugger
functionality. functionality.
- `mutable_text` (`MTX_`): Implements an asynchronously-filled-and-mutated
cache for text buffers which are mutated across time. In the debugger, this is
used to implement the `Output` view.
- `natvis` (no namespace): NatVis files for type visualization of the codebase's - `natvis` (no namespace): NatVis files for type visualization of the codebase's
types in other debuggers. types in other debuggers.
- `os/core` (`OS_`): An abstraction layer providing core, non-graphical - `os/core` (`OS_`): An abstraction layer providing core, non-graphical
@@ -287,20 +346,28 @@ A list of the layers in the codebase and their associated namespaces is below:
- `os/gfx` (`OS_`): An abstraction layer, building on `os/core`, providing - `os/gfx` (`OS_`): An abstraction layer, building on `os/core`, providing
graphical operating system features under an abstract API, which is graphical operating system features under an abstract API, which is
implemented per-target-operating-system. implemented per-target-operating-system.
- `os/socket` (`OS_`): An abstraction layer, building on `os/core`, providing - `path` (`PATH_`): Small helpers for manipulating file path strings.
networking operating system features under an abstract API, which is
implemented per-target-operating-system.
- `pdb` (`PDB_`): Code for parsing and/or writing the PDB file format. - `pdb` (`PDB_`): Code for parsing and/or writing the PDB file format.
- `pe` (`PE_`): Code for parsing and/or writing the PE (Portable Executable) - `pe` (`PE_`): Code for parsing and/or writing the PE (Portable Executable)
file format. file format.
- `raddbg` (no namespace): The layer which ties everything together for the main - `raddbg` (`RD_`): The layer which ties everything together for the main
graphical debugger. Not much "meat", just drives `df`, implements command line graphical debugger. Implements the debugger's graphical frontend, all of the
options, and so on. debugger-specific UI, the debugger executable's command line interface, and
- `rdi_from_pdb` (`P2R_`): Our implementation of PDB-to-RDI conversion. all of the built-in visualizers.
- `rdi_from_dwarf` (`D2R_`): Our in-progress implementation of DWARF-to-RDI - `rdi_breakpad_from_pdb` (`P2B_`): Our implementation, using the codebase's RDI
conversion. technology, for extracting information from PDBs and generating Breakpad text
dumps.
- `rdi_dump` (no namespace): A dumper utility program for dumping - `rdi_dump` (no namespace): A dumper utility program for dumping
textualizations of RDI debug info files. textualizations of RDI debug info files.
- `rdi_format` (no namespace): A layer which includes the `lib_rdi_format` layer
and bundles it with codebase-specific helpers, to easily include the library
in codebase programs, and have it be integrated with codebase constructs.
- `rdi_from_dwarf` (`D2R_`): Our in-progress implementation of DWARF-to-RDI
conversion.
- `rdi_from_pdb` (`P2R_`): Our implementation of PDB-to-RDI conversion.
- `rdi_make` (no namespace): A layer which includes the `lib_rdi_make` layer and
bundles it with codebase-specific helpers, to easily include the library in
codebase programs, and have it be integrated with codebase constructs.
- `regs` (`REGS_`): Types, helper functions, and metadata for registers on - `regs` (`REGS_`): Types, helper functions, and metadata for registers on
supported architectures. Used in reading/writing registers in `demon`, or in supported architectures. Used in reading/writing registers in `demon`, or in
looking up register metadata. looking up register metadata.
@@ -309,19 +376,17 @@ A list of the layers in the codebase and their associated namespaces is below:
level drawing API - this layer is strictly for minimally abstracting on an level drawing API - this layer is strictly for minimally abstracting on an
as-needed basis. Higher level drawing features are implemented in the `draw` as-needed basis. Higher level drawing features are implemented in the `draw`
layer. layer.
- `scratch` (no namespace): Scratch space for small and transient test or sample - `scratch` (no namespace): Scratch space for small and transient test programs.
programs.
- `texture_cache` (`TEX_`): Implements an asynchronously-filled cache for GPU - `texture_cache` (`TEX_`): Implements an asynchronously-filled cache for GPU
texture data, filled by data sourced in the `hash_store` layer's cache. Used texture data, filled by data sourced in the `hash_store` layer's cache. Used
for asynchronously preparing data for memory visualization in the debugger. for asynchronously preparing data for visualization.
- `txti` (`TXTI_`): Machinery for asynchronously-loaded, asynchronously hot- - `text_cache` (`TXT_`): Implements an asynchronously-filled cache for textual
reloaded, asynchronously parsed, and asynchronously mutated source code files. analysis data (tokens, line ranges, and so on), filled by data sourced in the
Used by the debugger to visualize source code files. Users ask for text lines, `hash_store` layer's cache. Used for asynchronously preparing data for
tokens, and metadata, and it is prepared on background threads. visualization (like for the source code viewer).
- `type_graph` (`TG_`): Code for analyzing and navigating type structures from - `third_party` (no namespace): External code from other projects, which some
RDI debug info files, with the additional capability of constructing layers in the codebase depend on. All external code is included and built
synthetic types *not* found in debug info. Used in `eval` and for various directly within the codebase.
visualization features.
- `ui` (`UI_`): Machinery for building graphical user interfaces. Provides a - `ui` (`UI_`): Machinery for building graphical user interfaces. Provides a
core immediate mode hierarchical user interface data structure building core immediate mode hierarchical user interface data structure building
API, and has helper layers for building some higher-level widgets. API, and has helper layers for building some higher-level widgets.
+36 -29
View File
@@ -1,14 +1,14 @@
@echo off @echo off
setlocal setlocal enabledelayedexpansion
cd /D "%~dp0" cd /D "%~dp0"
:: --- Usage Notes (2024/1/10) ------------------------------------------------ :: --- Usage Notes (2024/1/10) ------------------------------------------------
:: ::
:: This is a central build script for the RAD Debugger project. It takes a list :: This is a central build script for the RAD Debugger project, for use in
:: of simple alphanumeric-only arguments which control (a) what is built, (b) :: Windows development environments. It takes a list of simple alphanumeric-
:: which compiler & linker are used, and (c) extra high-level build options. By :: only arguments which control (a) what is built, (b) which compiler & linker
:: default, if no options are passed, then the main "raddbg" graphical debugger :: are used, and (c) extra high-level build options. By default, if no options
:: is built. :: are passed, then the main "raddbg" graphical debugger is built.
:: ::
:: Below is a non-exhaustive list of possible ways to use the script: :: Below is a non-exhaustive list of possible ways to use the script:
:: `build raddbg` :: `build raddbg`
@@ -43,18 +43,29 @@ if "%asan%"=="1" set auto_compile_flags=%auto_compile_flags% -fsanitize=add
:: --- Compile/Link Line Definitions ------------------------------------------ :: --- Compile/Link Line Definitions ------------------------------------------
set cl_common= /I..\src\ /I..\local\ /nologo /FC /Z7 set cl_common= /I..\src\ /I..\local\ /nologo /FC /Z7
set clang_common= -I..\src\ -I..\local\ -gcodeview -fdiagnostics-absolute-paths -Wall -Wno-unknown-warning-option -Wno-missing-braces -Wno-unused-function -Wno-writable-strings -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Wno-compare-distinct-pointer-types -Wno-initializer-overrides -Wno-incompatible-pointer-types-discards-qualifiers -Xclang -flto-visibility-public-std -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf set clang_common= -I..\src\ -I..\local\ -gcodeview -fdiagnostics-absolute-paths -Wall -Wno-unknown-warning-option -Wno-missing-braces -Wno-unused-function -Wno-writable-strings -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Wno-compare-distinct-pointer-types -Wno-initializer-overrides -Wno-incompatible-pointer-types-discards-qualifiers -Xclang -flto-visibility-public-std -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf -ferror-limit=10000
set cl_debug= call cl /Od /Ob1 /DBUILD_DEBUG=1 %cl_common% %auto_compile_flags% set cl_debug= call cl /Od /Ob1 /DBUILD_DEBUG=1 %cl_common% %auto_compile_flags%
set cl_release= call cl /O2 /DBUILD_DEBUG=0 %cl_common% %auto_compile_flags% set cl_release= call cl /O2 /DBUILD_DEBUG=0 %cl_common% %auto_compile_flags%
set clang_debug= call clang -g -O0 -DBUILD_DEBUG=1 %clang_common% %auto_compile_flags% set clang_debug= call clang -g -O0 -DBUILD_DEBUG=1 %clang_common% %auto_compile_flags%
set clang_release= call clang -g -O2 -DBUILD_DEBUG=0 %clang_common% %auto_compile_flags% set clang_release= call clang -g -O2 -DBUILD_DEBUG=0 %clang_common% %auto_compile_flags%
set cl_link= /link /MANIFEST:EMBED /INCREMENTAL:NO /natvis:"%~dp0\src\natvis\base.natvis" logo.res set cl_link= /link /MANIFEST:EMBED /INCREMENTAL:NO /pdbaltpath:%%%%_PDB%%%%
set clang_link= -fuse-ld=lld -Xlinker /MANIFEST:EMBED -Xlinker /natvis:"%~dp0\src\natvis\base.natvis" logo.res set clang_link= -fuse-ld=lld -Xlinker /MANIFEST:EMBED -Xlinker /pdbaltpath:%%%%_PDB%%%%
set cl_out= /out: set cl_out= /out:
set clang_out= -o set clang_out= -o
:: --- NATVIS -----------------------------------------------------------------
set natvis= /NATVIS:"%~dp0\src\natvis\base.natvis"
if "%radlink%"=="1" set natvis= %natvis% /NATVIS:"%~dp0\src\linker\linker.natvis"
if "%clang%"=="1" (
set result=
for %%n in (%natvis%) do set result= !result! -Xlinker %%n
set natvis= !result!
)
:: --- Per-Build Settings ----------------------------------------------------- :: --- Per-Build Settings -----------------------------------------------------
set link_dll=-DLL set link_dll=-DLL
set link_icon=logo.res
if "%msvc%"=="1" set only_compile=/c if "%msvc%"=="1" set only_compile=/c
if "%clang%"=="1" set only_compile=-c if "%clang%"=="1" set only_compile=-c
if "%msvc%"=="1" set EHsc=/EHsc if "%msvc%"=="1" set EHsc=/EHsc
@@ -76,6 +87,9 @@ if "%clang%"=="1" set out=%clang_out%
if "%debug%"=="1" set compile=%compile_debug% if "%debug%"=="1" set compile=%compile_debug%
if "%release%"=="1" set compile=%compile_release% if "%release%"=="1" set compile=%compile_release%
:: --- Append NATVIS to link line ---------------------------------------------
set compile_link= %compile_link% %natvis%
:: --- Prep Directories ------------------------------------------------------- :: --- Prep Directories -------------------------------------------------------
if not exist build mkdir build if not exist build mkdir build
if not exist local mkdir local if not exist local mkdir local
@@ -86,7 +100,8 @@ pushd build
popd popd
:: --- Get Current Git Commit Id ---------------------------------------------- :: --- Get Current Git Commit Id ----------------------------------------------
for /f %%i in ('call git describe --always --dirty') do set compile=%compile% -DBUILD_GIT_HASH=\"%%i\" for /f %%i in ('call git describe --always --dirty') do set compile=%compile% -DBUILD_GIT_HASH=\"%%i\"
for /f %%i in ('call git rev-parse HEAD') do set compile=%compile% -DBUILD_GIT_HASH_FULL=\"%%i\"
:: --- Build & Run Metaprogram ------------------------------------------------ :: --- Build & Run Metaprogram ------------------------------------------------
if "%no_meta%"=="1" echo [skipping metagen] if "%no_meta%"=="1" echo [skipping metagen]
@@ -99,16 +114,18 @@ if not "%no_meta%"=="1" (
:: --- Build Everything (@build_targets) -------------------------------------- :: --- Build Everything (@build_targets) --------------------------------------
pushd build pushd build
if "%raddbg%"=="1" set didbuild=1 && %compile% ..\src\raddbg\raddbg_main.c %compile_link% %out%raddbg.exe || exit /b 1 if "%raddbg%"=="1" set didbuild=1 && %compile% ..\src\raddbg\raddbg_main.c %compile_link% %link_icon% %out%raddbg.exe || exit /b 1
if "%rdi_from_pdb%"=="1" set didbuild=1 && %compile% ..\src\rdi_from_pdb\rdi_from_pdb_main.c %compile_link% %out%rdi_from_pdb.exe || exit /b 1 if "%radlink%"=="1" set didbuild=1 && %compile% ..\src\linker\lnk.c %compile_link% %out%radlink.exe || exit /b 1
if "%rdi_from_dwarf%"=="1" set didbuild=1 && %compile% ..\src\rdi_from_dwarf\rdi_from_dwarf.c %compile_link% %out%rdi_from_dwarf.exe || exit /b 1 if "%rdi_from_pdb%"=="1" set didbuild=1 && %compile% ..\src\rdi_from_pdb\rdi_from_pdb_main.c %compile_link% %out%rdi_from_pdb.exe || exit /b 1
if "%rdi_dump%"=="1" set didbuild=1 && %compile% ..\src\rdi_dump\rdi_dump_main.c %compile_link% %out%rdi_dump.exe || exit /b 1 if "%rdi_from_dwarf%"=="1" set didbuild=1 && %compile% ..\src\rdi_from_dwarf\rdi_from_dwarf.c %compile_link% %out%rdi_from_dwarf.exe || exit /b 1
if "%rdi_breakpad_from_pdb%"=="1" set didbuild=1 && %compile% ..\src\rdi_breakpad_from_pdb\rdi_breakpad_from_pdb_main.c %compile_link% %out%rdi_breakpad_from_pdb.exe || exit /b 1 if "%rdi_dump%"=="1" set didbuild=1 && %compile% ..\src\rdi_dump\rdi_dump_main.c %compile_link% %out%rdi_dump.exe || exit /b 1
if "%ryan_scratch%"=="1" set didbuild=1 && %compile% ..\src\scratch\ryan_scratch.c %compile_link% %out%ryan_scratch.exe || exit /b 1 if "%rdi_breakpad_from_pdb%"=="1" set didbuild=1 && %compile% ..\src\rdi_breakpad_from_pdb\rdi_breakpad_from_pdb_main.c %compile_link% %out%rdi_breakpad_from_pdb.exe || exit /b 1
if "%cpp_tests%"=="1" set didbuild=1 && %compile% ..\src\scratch\i_hate_c_plus_plus.cpp %compile_link% %out%cpp_tests.exe || exit /b 1 if "%tester%"=="1" set didbuild=1 && %compile% ..\src\tester\tester_main.c %compile_link% %out%tester.exe || exit /b 1
if "%look_at_raddbg%"=="1" set didbuild=1 && %compile% ..\src\scratch\look_at_raddbg.c %compile_link% %out%look_at_raddbg.exe || exit /b 1 if "%ryan_scratch%"=="1" set didbuild=1 && %compile% ..\src\scratch\ryan_scratch.c %compile_link% %out%ryan_scratch.exe || exit /b 1
if "%textperf%"=="1" set didbuild=1 && %compile% ..\src\scratch\textperf.c %compile_link% %out%textperf.exe || exit /b 1
if "%parse_inline_sites%"=="1" set didbuild=1 && %compile% ..\src\scratch\parse_inline_sites.c %compile_link% %out%parse_inline_sites.exe || exit /b 1
if "%mule_main%"=="1" set didbuild=1 && del vc*.pdb mule*.pdb && %compile_release% %only_compile% ..\src\mule\mule_inline.cpp && %compile_release% %only_compile% ..\src\mule\mule_o2.cpp && %compile_debug% %EHsc% ..\src\mule\mule_main.cpp ..\src\mule\mule_c.c mule_inline.obj mule_o2.obj %compile_link% %no_aslr% %out%mule_main.exe || exit /b 1 if "%mule_main%"=="1" set didbuild=1 && del vc*.pdb mule*.pdb && %compile_release% %only_compile% ..\src\mule\mule_inline.cpp && %compile_release% %only_compile% ..\src\mule\mule_o2.cpp && %compile_debug% %EHsc% ..\src\mule\mule_main.cpp ..\src\mule\mule_c.c mule_inline.obj mule_o2.obj %compile_link% %no_aslr% %out%mule_main.exe || exit /b 1
if "%mule_module%"=="1" set didbuild=1 && %compile% ..\src\mule\mule_module.cpp %compile_link% %link_dll% %out%mule_module.dll || exit /b 1 if "%mule_module%"=="1" set didbuild=1 && %compile% ..\src\mule\mule_module.cpp %compile_link% %link_dll% %out%mule_module.dll || exit /b 1
if "%mule_hotload%"=="1" set didbuild=1 && %compile% ..\src\mule\mule_hotload_main.c %compile_link% %out%mule_hotload.exe & %compile% ..\src\mule\mule_hotload_module_main.c %compile_link% %link_dll% %out%mule_hotload_module.dll || exit /b 1 if "%mule_hotload%"=="1" set didbuild=1 && %compile% ..\src\mule\mule_hotload_main.c %compile_link% %out%mule_hotload.exe & %compile% ..\src\mule\mule_hotload_module_main.c %compile_link% %link_dll% %out%mule_hotload_module.dll || exit /b 1
if "%mule_peb_trample%"=="1" ( if "%mule_peb_trample%"=="1" (
set didbuild=1 set didbuild=1
@@ -120,16 +137,6 @@ if "%mule_peb_trample%"=="1" (
) )
popd popd
:: --- Unset ------------------------------------------------------------------
for %%a in (%*) do set "%%a=0"
set raddbg=
set compile=
set compile_link=
set out=
set msvc=
set debug=
set release=
:: --- Warn On No Builds ------------------------------------------------------ :: --- Warn On No Builds ------------------------------------------------------
if "%didbuild%"=="" ( if "%didbuild%"=="" (
echo [WARNING] no valid build target specified; must use build target names as arguments to this script, like `build raddbg` or `build rdi_from_pdb`. echo [WARNING] no valid build target specified; must use build target names as arguments to this script, like `build raddbg` or `build rdi_from_pdb`.
+79
View File
@@ -0,0 +1,79 @@
#!/bin/bash
set -eu
cd "$(dirname "$0")"
# --- Unpack Arguments --------------------------------------------------------
for arg in "$@"; do declare $arg='1'; done
if [ ! -v gcc ]; then clang=1; fi
if [ ! -v release ]; then debug=1; fi
if [ -v debug ]; then echo "[debug mode]"; fi
if [ -v release ]; then echo "[release mode]"; fi
if [ -v clang ]; then compiler="${CC:-clang}"; echo "[clang compile]"; fi
if [ -v gcc ]; then compiler="${CC:-gcc}"; echo "[gcc compile]"; fi
# --- Unpack Command Line Build Arguments -------------------------------------
auto_compile_flags=''
# --- Get Current Git Commit Id -----------------------------------------------
git_hash=$(git rev-parse HEAD)
git_hash_full=$(git rev-parse HEAD)
# --- Compile/Link Line Definitions -------------------------------------------
clang_common="-I../src/ -I../local/ -g -DBUILD_GIT_HASH=\"$git_hash\" -DBUILD_GIT_HASH_FULL=\"$git_hash_full\" -Wno-unknown-warning-option -fdiagnostics-absolute-paths -Wall -Wno-missing-braces -Wno-unused-function -Wno-writable-strings -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Wno-compare-distinct-pointer-types -Wno-initializer-overrides -Wno-incompatible-pointer-types-discards-qualifiers -Wno-for-loop-analysis -Xclang -flto-visibility-public-std -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf"
clang_debug="$compiler -g -O0 -DBUILD_DEBUG=1 ${clang_common} ${auto_compile_flags}"
clang_release="$compiler -g -O2 -DBUILD_DEBUG=0 ${clang_common} ${auto_compile_flags}"
clang_link="-lpthread -lm -lrt -ldl"
clang_out="-o"
gcc_common="-I../src/ -I../local/ -g -DBUILD_GIT_HASH=\"$git_hash\" -DBUILD_GIT_HASH_FULL=\"$git_hash_full\" -Wno-unknown-warning-option -Wall -Wno-missing-braces -Wno-unused-function -Wno-attributes -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-compare-distinct-pointer-types -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf"
gcc_debug="$compiler -g -O0 -DBUILD_DEBUG=1 ${gcc_common} ${auto_compile_flags}"
gcc_release="$compiler -g -O2 -DBUILD_DEBUG=0 ${gcc_common} ${auto_compile_flags}"
gcc_link="-lpthread -lm -lrt -ldl"
gcc_out="-o"
# --- Per-Build Settings ------------------------------------------------------
link_dll="-fPIC"
link_os_gfx="-lX11 -lXext"
# --- Choose Compile/Link Lines -----------------------------------------------
if [ -v gcc ]; then compile_debug="$gcc_debug"; fi
if [ -v gcc ]; then compile_release="$gcc_release"; fi
if [ -v gcc ]; then compile_link="$gcc_link"; fi
if [ -v gcc ]; then out="$gcc_out"; fi
if [ -v clang ]; then compile_debug="$clang_debug"; fi
if [ -v clang ]; then compile_release="$clang_release"; fi
if [ -v clang ]; then compile_link="$clang_link"; fi
if [ -v clang ]; then out="$clang_out"; fi
if [ -v debug ]; then compile="$compile_debug"; fi
if [ -v release ]; then compile="$compile_release"; fi
# --- Prep Directories --------------------------------------------------------
mkdir -p build
mkdir -p local
# --- Build & Run Metaprogram -------------------------------------------------
if [ -v no_meta ]; then echo "[skipping metagen]"; fi
if [ ! -v no_meta ]
then
cd build
$compile_debug ../src/metagen/metagen_main.c $compile_link $out metagen
./metagen
cd ..
fi
# --- Build Everything (@build_targets) ---------------------------------------
cd build
if [ -v raddbg ]; then didbuild=1 && $compile ../src/raddbg/raddbg_main.c $compile_link $link_os_gfx $out raddbg; fi
if [ -v radlink ]; then didbuild=1 && $compile ../src/linker/lnk.c $compile_link $out radlink; fi
if [ -v rdi_from_pdb ]; then didbuild=1 && $compile ../src/rdi_from_pdb/rdi_from_pdb_main.c $compile_link $out rdi_from_pdb; fi
if [ -v rdi_from_dwarf ]; then didbuild=1 && $compile ../src/rdi_from_dwarf/rdi_from_dwarf.c $compile_link $out rdi_from_dwarf; fi
if [ -v rdi_dump ]; then didbuild=1 && $compile ../src/rdi_dump/rdi_dump_main.c $compile_link $out rdi_dump; fi
if [ -v rdi_breakpad_from_pdb ]; then didbuild=1 && $compile ../src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c $compile_link $out rdi_breakpad_from_pdb; fi
if [ -v ryan_scratch ]; then didbuild=1 && $compile ../src/scratch/ryan_scratch.c $compile_link $link_os_gfx $out ryan_scratch; fi
cd ..
# --- Warn On No Builds -------------------------------------------------------
if [ ! -v didbuild ]
then
echo "[WARNING] no valid build target specified; must use build target names as arguments to this script, like \`./build.sh raddbg\` or \`./build.sh rdi_from_pdb\`."
exit 1
fi
+39 -116
View File
@@ -45,131 +45,54 @@ load_paths =
commands = commands =
{ {
.rjf_f1 = //- rjf: fkey command slots (change locally but do not commit)
{ .f1 = { .win = "build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
//.win = "build rdi_from_pdb rdi_dump && pushd build && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main.rdi && rdi_dump mule_main.rdi > mule_main.dump && popd", .f2 = { .win = "build rdi_from_pdb", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.win = "build raddbg telemetry", .f3 = { .win = "pushd build && raddbg.exe --user:local_dev.raddbg_user --project:local_dev.raddbg_project --xuto_run && popd",.linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.linux = "", // .f1 = { .win = "build textperf release telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.out = "*compilation*", // .f3 = { .win = "pushd build && textperf.exe --capture && popd",.linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.footer_panel = true,
.save_dirty_files = true, //- rjf: local target builds
.cursor_at_end = false, .build_raddbg = { .win = "build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
}, .build_rdi_from_pdb = { .win = "build rdi_from_pdb", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.rjf_f2 = .build_rdi_from_dwarf = { .win = "build rdi_from_dwarf", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
{ .build_rdi_dump = { .win = "build rdi_dump", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.win = "build rdi_from_pdb rdi_dump && pushd build && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main.rdi && rdi_dump mule_main.rdi > mule_main.dump && popd", .build_rdi_breakpad_from_pdb = { .win = "build rdi_breakpad_from_pdb", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.linux = "", .build_ryan_scratch = { .win = "build ryan_scratch", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.out = "*compilation*", .build_mule_main = { .win = "build mule_main", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.footer_panel = true, .build_mule_module = { .win = "build mule_module", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.save_dirty_files = true, .build_mule_hotload = { .win = "build mule_hotload", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.cursor_at_end = false, .build_mule_peb_trample = { .win = "build mule_peb_trample", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
},
.rjf_f3 = //- rjf: wsl target builds
{ .build_raddbg_wsl = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.win = "pushd build && raddbg.exe --user:local_dev.raddbg_user --project:local_dev.raddbg_project && popd", .build_rdi_from_pdb_wsl = { .win = "wsl ./build.sh rdi_from_pdb", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.linux = "", .build_rdi_from_dwarf_wsl = { .win = "wsl ./build.sh rdi_from_dwarf", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.out = "*compilation*", .build_rdi_dump_wsl = { .win = "wsl ./build.sh rdi_dump", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.footer_panel = true, .build_rdi_breakpad_from_pdb_wsl = { .win = "wsl ./build.sh rdi_breakpad_from_pdb", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.save_dirty_files = true, .build_ryan_scratch_wsl = { .win = "wsl ./build.sh ryan_scratch", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.cursor_at_end = false, .build_mule_main_wsl = { .win = "wsl ./build.sh mule_main", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
}, .build_mule_module_wsl = { .win = "wsl ./build.sh mule_module", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.rjf_f4 = .build_mule_hotload_wsl = { .win = "wsl ./build.sh mule_hotload", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
{ .build_mule_peb_trample_wsl = { .win = "wsl ./build.sh mule_peb_trample", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.win = "build rdi_from_pdb release telemetry && pushd build && rdi_from_pdb.exe --pdb:UnrealEditorFortnite.pdb --out:profile.rdi --capture && popd",
.linux = "", //- rjf: local target runs
.out = "*compilation*", .run_raddbg = { .win = "pushd build && raddbg.exe && popd", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.footer_panel = true,
.save_dirty_files = true,
.cursor_at_end = false,
},
.rjf_f5 =
{
.win = "pushd build && rdi_from_pdb.exe --exe:raddbg.exe --pdb:raddbg.pdb --out:raddbg.rdi --capture && popd",
.linux = "",
.out = "*compilation*",
.footer_panel = true,
.save_dirty_files = true,
.cursor_at_end = false,
},
.build_raddbg =
{
.win = "build raddbg",
.linux = "",
.out = "*compilation*",
.footer_panel = true,
.save_dirty_files = true,
.cursor_at_end = false,
},
.build_raddbg_release_telemetry =
{
.win = "build raddbg release telemetry",
.linux = "",
.out = "*compilation*",
.footer_panel = true,
.save_dirty_files = true,
.cursor_at_end = false,
},
.build_rdi_from_pdb =
{
.win = "build rdi_from_pdb",
.linux = "",
.out = "*compilation*",
.footer_panel = true,
.save_dirty_files = true,
.cursor_at_end = false,
},
.build_rdi_dump =
{
.win = "build rdi_dump",
.linux = "",
.out = "*compilation*",
.footer_panel = true,
.save_dirty_files = true,
.cursor_at_end = false,
},
.build_mule_main =
{
.win = "build mule_main",
.linux = "",
.out = "*compilation*",
.footer_panel = true,
.save_dirty_files = true,
.cursor_at_end = false,
},
.build_ryan_scratch =
{
.win = "build ryan_scratch",
.linux = "",
.out = "*compilation*",
.footer_panel = true,
.save_dirty_files = true,
.cursor_at_end = false,
},
.run_raddbg =
{
.win = "pushd build && raddbg.exe && popd",
.linux = "",
.out = "*compilation*",
.footer_panel = true,
.save_dirty_files = true,
.cursor_at_end = false,
},
}; };
fkey_command = fkey_command =
{ {
.F1 = "build_raddbg", .F1 = "f1",
.F3 = "run_raddbg", .F2 = "f2",
.F3 = "f3",
}; };
fkey_command_override = fkey_command_override =
{ {
.rjf = .rjf =
{ {
.F1 = "rjf_f1", .F1 = "f1",
.F2 = "rjf_f2", .F2 = "f2",
.F3 = "rjf_f3", .F3 = "f3",
.F4 = "rjf_f4",
.F5 = "rjf_f5",
}, },
}; };
+21
View File
@@ -0,0 +1,21 @@
@echo off
setlocal
cd /D "%~dp0"
echo --- getting test data folder path ---------------------------------------------
if not exist .\local\test_data_path.txt (
echo error: You must first store the full path of your test data folder inside of `local/test_data_path.txt`.
goto :EOF
)
set /p test_data_folder=<.\local\test_data_path.txt
echo test data path: %test_data_folder%
echo:
echo --- building all testing executables ------------------------------------------
call build rdi_from_pdb rdi_dump raddbg radlink tester
echo:
echo --- running tests -------------------------------------------------------------
pushd build
call tester.exe --test_data:%test_data_folder%
popd
+240
View File
@@ -0,0 +1,240 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Top-Level Layer Initialization
internal void
async_init(void)
{
Arena *arena = arena_alloc();
async_shared = push_array(arena, ASYNC_Shared, 1);
async_shared->arena = arena;
for EachEnumVal(ASYNC_Priority, p)
{
ASYNC_Ring *ring = &async_shared->rings[p];
ring->ring_size = MB(8);
ring->ring_base = push_array_no_zero(arena, U8, ring->ring_size);
ring->ring_mutex = os_mutex_alloc();
ring->ring_cv = os_condition_variable_alloc();
}
async_shared->ring_mutex = os_mutex_alloc();
async_shared->ring_cv = os_condition_variable_alloc();
async_shared->work_threads_count = Max(1, os_get_system_info()->logical_processor_count-1);
async_shared->work_threads = push_array(arena, OS_Handle, async_shared->work_threads_count);
for EachIndex(idx, async_shared->work_threads_count)
{
async_shared->work_threads[idx] = os_thread_launch(async_work_thread__entry_point, (void *)idx, 0);
}
}
////////////////////////////////
//~ rjf: Top-Level Accessors
internal U64
async_thread_count(void)
{
return async_shared->work_threads_count;
}
////////////////////////////////
//~ rjf: Work Kickoffs
internal B32
async_push_work_(ASYNC_WorkFunctionType *work_function, ASYNC_WorkParams *params)
{
// rjf: choose ring
ASYNC_Ring *ring = &async_shared->rings[params->priority];
// rjf: build work package
ASYNC_Work work = {0};
work.work_function = work_function;
work.input = params->input;
work.output = params->output;
work.semaphore = params->semaphore;
work.completion_counter = params->completion_counter;
// rjf: loop; try to write into user -> writer ring buffer. if we're on a
// worker thread, determine if we need to execute this task locally on this
// thread, and skip ring buffer if so.
B32 queued_in_ring_buffer = 0;
B32 need_to_execute_on_this_thread = 0;
OS_MutexScope(ring->ring_mutex) for(;;)
{
U64 num_available_work_threads = (async_shared->work_threads_count - ins_atomic_u64_eval(&async_shared->work_threads_live_count));
if(num_available_work_threads == 0 && async_work_thread_depth > 0)
{
need_to_execute_on_this_thread = 1;
break;
}
U64 unconsumed_size = ring->ring_write_pos - ring->ring_read_pos;
U64 available_size = ring->ring_size - unconsumed_size;
if(available_size >= sizeof(work))
{
queued_in_ring_buffer = 1;
if(!os_handle_match(params->semaphore, os_handle_zero()))
{
os_semaphore_take(params->semaphore, max_U64);
}
ring->ring_write_pos += ring_write_struct(ring->ring_base, ring->ring_size, ring->ring_write_pos, &work);
break;
}
if(os_now_microseconds() >= params->endt_us)
{
break;
}
os_condition_variable_wait(ring->ring_cv, ring->ring_mutex, params->endt_us);
}
// rjf: broadcast ring buffer cv if we wrote successfully
if(queued_in_ring_buffer)
{
os_condition_variable_broadcast(ring->ring_cv);
os_condition_variable_broadcast(async_shared->ring_cv);
}
// rjf: if we did not queue successfully, and we have determined that
// we need to execute this work on the current thread, then execute the
// work before returning
if(need_to_execute_on_this_thread)
{
async_execute_work(work);
}
// rjf: return success signal
B32 result = (queued_in_ring_buffer || need_to_execute_on_this_thread);
return result;
}
////////////////////////////////
//~ rjf: Task-Based Work Helper
internal void
async_task_list_push(Arena *arena, ASYNC_TaskList *list, ASYNC_Task *t)
{
ASYNC_TaskNode *n = push_array(arena, ASYNC_TaskNode, 1);
SLLQueuePush(list->first, list->last, n);
n->v = t;
list->count += 1;
}
internal ASYNC_Task *
async_task_launch_(Arena *arena, ASYNC_WorkFunctionType *work_function, ASYNC_WorkParams *params)
{
ASYNC_Task *task = push_array(arena, ASYNC_Task, 1);
task->semaphore = os_semaphore_alloc(1, 1, str8_zero());
ASYNC_WorkParams params_refined = {0};
MemoryCopyStruct(&params_refined, params);
params_refined.endt_us = max_U64;
params_refined.semaphore = task->semaphore;
if(params_refined.output == 0)
{
params_refined.output = &task->output;
}
async_push_work_(work_function, &params_refined);
return task;
}
internal void *
async_task_join(ASYNC_Task *task)
{
void *result = 0;
if(task != 0 && !os_handle_match(task->semaphore, os_handle_zero()))
{
os_semaphore_take(task->semaphore, max_U64);
os_semaphore_release(task->semaphore);
MemoryZeroStruct(&task->semaphore);
result = (void *)ins_atomic_u64_eval(&task->output);
}
return result;
}
////////////////////////////////
//~ rjf: Work Execution
internal ASYNC_Work
async_pop_work(void)
{
ProfBeginFunction();
ASYNC_Work work = {0};
B32 done = 0;
ASYNC_Priority taken_priority = ASYNC_Priority_Low;
OS_MutexScope(async_shared->ring_mutex) for(;!done;)
{
for(ASYNC_Priority priority = ASYNC_Priority_High;; priority = (ASYNC_Priority)(priority - 1))
{
ASYNC_Ring *ring = &async_shared->rings[priority];
OS_MutexScope(ring->ring_mutex)
{
U64 unconsumed_size = ring->ring_write_pos - ring->ring_read_pos;
if(unconsumed_size >= sizeof(work))
{
ring->ring_read_pos += ring_read_struct(ring->ring_base, ring->ring_size, ring->ring_read_pos, &work);
done = 1;
taken_priority = priority;
}
}
if(done)
{
break;
}
if(priority == ASYNC_Priority_Low)
{
break;
}
}
if(!done)
{
os_condition_variable_wait(async_shared->ring_cv, async_shared->ring_mutex, max_U64);
}
}
os_condition_variable_broadcast(async_shared->ring_cv);
os_condition_variable_broadcast(async_shared->rings[taken_priority].ring_cv);
ProfEnd();
return work;
}
internal void
async_execute_work(ASYNC_Work work)
{
//- rjf: run work
async_work_thread_depth += 1;
void *work_out = work.work_function(async_work_thread_idx, work.input);
async_work_thread_depth -= 1;
//- rjf: store output
if(work.output != 0)
{
ins_atomic_u64_eval_assign((U64 *)work.output, (U64)work_out);
}
//- rjf: release semaphore
if(!os_handle_match(work.semaphore, os_handle_zero()))
{
os_semaphore_drop(work.semaphore);
}
//- rjf: increment completion counter
if(work.completion_counter != 0)
{
ins_atomic_u64_inc_eval(work.completion_counter);
}
}
////////////////////////////////
//~ rjf: Work Thread Entry Point
internal void
async_work_thread__entry_point(void *p)
{
U64 thread_idx = (U64)p;
ThreadNameF("[async] work thread #%I64u", thread_idx);
async_work_thread_idx = thread_idx;
for(;;)
{
ASYNC_Work work = async_pop_work();
ins_atomic_u64_inc_eval(&async_shared->work_threads_live_count);
async_execute_work(work);
ins_atomic_u64_dec_eval(&async_shared->work_threads_live_count);
}
}
+144
View File
@@ -0,0 +1,144 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef ASYNC_H
#define ASYNC_H
////////////////////////////////
//~ rjf: Work Function Type
#define ASYNC_WORK_SIG(name) void *name(U64 thread_idx, void *input)
#define ASYNC_WORK_DEF(name) internal ASYNC_WORK_SIG(name)
typedef ASYNC_WORK_SIG(ASYNC_WorkFunctionType);
////////////////////////////////
//~ rjf: Work Types
typedef enum ASYNC_Priority
{
ASYNC_Priority_Low,
ASYNC_Priority_High,
ASYNC_Priority_COUNT
}
ASYNC_Priority;
typedef struct ASYNC_WorkParams ASYNC_WorkParams;
struct ASYNC_WorkParams
{
void *input;
void **output;
OS_Handle semaphore;
U64 *completion_counter;
U64 endt_us;
ASYNC_Priority priority;
};
typedef struct ASYNC_Work ASYNC_Work;
struct ASYNC_Work
{
ASYNC_WorkFunctionType *work_function;
void *input;
void **output;
OS_Handle semaphore;
U64 *completion_counter;
};
////////////////////////////////
//~ rjf: Task-Based Work Types
typedef struct ASYNC_Task ASYNC_Task;
struct ASYNC_Task
{
OS_Handle semaphore;
void *output;
};
typedef struct ASYNC_TaskNode ASYNC_TaskNode;
struct ASYNC_TaskNode
{
ASYNC_TaskNode *next;
ASYNC_Task *v;
};
typedef struct ASYNC_TaskList ASYNC_TaskList;
struct ASYNC_TaskList
{
ASYNC_TaskNode *first;
ASYNC_TaskNode *last;
U64 count;
};
////////////////////////////////
//~ rjf: Shared State Bundle
typedef struct ASYNC_Ring ASYNC_Ring;
struct ASYNC_Ring
{
U64 ring_size;
U8 *ring_base;
U64 ring_write_pos;
U64 ring_read_pos;
OS_Handle ring_mutex;
OS_Handle ring_cv;
};
typedef struct ASYNC_Shared ASYNC_Shared;
struct ASYNC_Shared
{
Arena *arena;
// rjf: user -> work thread ring buffers
ASYNC_Ring rings[ASYNC_Priority_COUNT];
OS_Handle ring_mutex;
OS_Handle ring_cv;
// rjf: work threads
OS_Handle *work_threads;
U64 work_threads_count;
U64 work_threads_live_count;
};
////////////////////////////////
//~ rjf: Globals
thread_static B32 async_work_thread_depth = 0;
thread_static U64 async_work_thread_idx = 0;
global ASYNC_Shared *async_shared = 0;
////////////////////////////////
//~ rjf: Top-Level Layer Initialization
internal void async_init(void);
////////////////////////////////
//~ rjf: Top-Level Accessors
internal U64 async_thread_count(void);
////////////////////////////////
//~ rjf: Work Kickoffs
internal B32 async_push_work_(ASYNC_WorkFunctionType *work_function, ASYNC_WorkParams *params);
#define async_push_work(function, ...) async_push_work_((function), &(ASYNC_WorkParams){.endt_us = max_U64, .priority = ASYNC_Priority_High, __VA_ARGS__})
////////////////////////////////
//~ rjf: Task-Based Work Helper
internal void async_task_list_push(Arena *arena, ASYNC_TaskList *list, ASYNC_Task *t);
internal ASYNC_Task *async_task_launch_(Arena *arena, ASYNC_WorkFunctionType *work_function, ASYNC_WorkParams *params);
#define async_task_launch(arena, work_function, ...) async_task_launch_((arena), (work_function), &(ASYNC_WorkParams){.endt_us = max_U64, __VA_ARGS__})
internal void *async_task_join(ASYNC_Task *task);
#define async_task_join_struct(task, T) (T *)async_task_join(task)
////////////////////////////////
//~ rjf: Work Execution
internal ASYNC_Work async_pop_work(void);
internal void async_execute_work(ASYNC_Work work);
////////////////////////////////
//~ rjf: Work Thread Entry Point
internal void async_work_thread__entry_point(void *p);
#endif // ASYNC_H
+154 -208
View File
@@ -2,172 +2,176 @@
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
//////////////////////////////// ////////////////////////////////
// Implementation //~ rjf: Arena Functions
//- rjf: arena creation/destruction
internal Arena * internal Arena *
arena_alloc__sized(U64 init_res, U64 init_cmt) arena_alloc_(ArenaParams *params)
{ {
ProfBeginFunction(); // rjf: round up reserve/commit sizes
Assert(ARENA_HEADER_SIZE < init_cmt && init_cmt <= init_res); U64 reserve_size = params->reserve_size;
U64 commit_size = params->commit_size;
void *memory = 0; if(params->flags & ArenaFlag_LargePages)
U64 res = 0;
U64 cmt = 0;
B32 large_pages = os_large_pages_enabled();
if(large_pages)
{ {
U64 page_size = os_large_page_size(); reserve_size = AlignPow2(reserve_size, os_get_system_info()->large_page_size);
res = AlignPow2(init_res, page_size); commit_size = AlignPow2(commit_size, os_get_system_info()->large_page_size);
#if OS_WINDOWS
cmt = res;
#else
cmt = AlignPow2(init_cmt, page_size);
#endif
memory = os_reserve_large(res);
if(!os_commit_large(memory, cmt))
{
memory = 0;
os_release(memory, res);
}
} }
else else
{ {
U64 page_size = os_page_size(); reserve_size = AlignPow2(reserve_size, os_get_system_info()->page_size);
res = AlignPow2(init_res, page_size); commit_size = AlignPow2(commit_size, os_get_system_info()->page_size);
cmt = AlignPow2(init_cmt, page_size); }
memory = os_reserve(res);
if(!os_commit(memory, cmt)) // rjf: reserve/commit initial block
void *base = params->optional_backing_buffer;
if(base == 0)
{
if(params->flags & ArenaFlag_LargePages)
{ {
memory = 0; base = os_reserve_large(reserve_size);
os_release(memory, res); os_commit_large(base, commit_size);
}
else
{
base = os_reserve(reserve_size);
os_commit(base, commit_size);
} }
} }
Arena *arena = (Arena*)memory; // rjf: panic on arena creation failure
if(arena) #if OS_FEATURE_GRAPHICAL
if(Unlikely(base == 0))
{ {
AsanPoisonMemoryRegion(memory, cmt); os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
AsanUnpoisonMemoryRegion(memory, ARENA_HEADER_SIZE); os_abort(1);
arena->prev = 0;
arena->current = arena;
arena->base_pos = 0;
arena->pos = ARENA_HEADER_SIZE;
arena->cmt = cmt;
arena->res = res;
arena->align = 8;
arena->grow = 1;
arena->large_pages = large_pages;
} }
#endif
ProfEnd(); // rjf: extract arena header & fill
return arena; Arena *arena = (Arena *)base;
} arena->current = arena;
arena->flags = params->flags;
internal Arena * arena->cmt_size = params->commit_size;
arena_alloc(void) arena->res_size = params->reserve_size;
{ arena->base_pos = 0;
ProfBeginFunction(); arena->pos = ARENA_HEADER_SIZE;
arena->cmt = commit_size;
U64 init_res, init_cmt; arena->res = reserve_size;
if (os_large_pages_enabled()) { #if ARENA_FREE_LIST
init_res = ARENA_RESERVE_SIZE_LARGE_PAGES; arena->free_size = 0;
init_cmt = ARENA_COMMIT_SIZE_LARGE_PAGES; arena->free_last = 0;
} else { #endif
init_res = ARENA_RESERVE_SIZE; AsanPoisonMemoryRegion(base, commit_size);
init_cmt = ARENA_COMMIT_SIZE; AsanUnpoisonMemoryRegion(base, ARENA_HEADER_SIZE);
}
Arena *arena = arena_alloc__sized(init_res, init_cmt);
ProfEnd();
return arena; return arena;
} }
internal void internal void
arena_release(Arena *arena) arena_release(Arena *arena)
{ {
for (Arena *node = arena->current, *prev = 0; node != 0; node = prev) { for(Arena *n = arena->current, *prev = 0; n != 0; n = prev)
prev = node->prev; {
os_release(node, node->res); prev = n->prev;
os_release(n, n->res);
} }
} }
internal U64 //- rjf: arena push/pop core functions
arena_huge_push_threshold(void)
{
U64 reserve_size = os_large_pages_enabled() ? ARENA_RESERVE_SIZE_LARGE_PAGES : ARENA_RESERVE_SIZE;
U64 threshold = (reserve_size - ARENA_HEADER_SIZE) / 2 + 1;
return threshold;
}
internal void * internal void *
arena_push__impl(Arena *arena, U64 size) arena_push(Arena *arena, U64 size, U64 align)
{ {
Arena *current = arena->current; Arena *current = arena->current;
U64 pos_mem = AlignPow2(current->pos, arena->align); U64 pos_pre = AlignPow2(current->pos, align);
U64 pos_new = pos_mem + size; U64 pos_pst = pos_pre + size;
if (current->res < pos_new && arena->grow) { // rjf: chain, if needed
Arena *new_block; if(current->res < pos_pst && !(arena->flags & ArenaFlag_NoChain))
{
Arena *new_block = 0;
// normal growth path #if ARENA_FREE_LIST
if (size < arena_huge_push_threshold()) { Arena *prev_block;
new_block = arena_alloc(); for(new_block = arena->free_last, prev_block = 0; new_block != 0; prev_block = new_block, new_block = new_block->prev)
{
if(new_block->res >= AlignPow2(size, align))
{
if(prev_block)
{
prev_block->prev = new_block->prev;
}
else
{
arena->free_last = new_block->prev;
}
arena->free_size -= new_block->res_size;
AsanUnpoisonMemoryRegion((U8*)new_block + ARENA_HEADER_SIZE, new_block->res_size - ARENA_HEADER_SIZE);
break;
}
} }
// huge growth path #endif
else {
U64 new_block_size = size + ARENA_HEADER_SIZE; if(new_block == 0)
new_block = arena_alloc__sized(new_block_size, new_block_size); {
U64 res_size = current->res_size;
U64 cmt_size = current->cmt_size;
if(size + ARENA_HEADER_SIZE > res_size)
{
res_size = AlignPow2(size + ARENA_HEADER_SIZE, align);
cmt_size = AlignPow2(size + ARENA_HEADER_SIZE, align);
}
new_block = arena_alloc(.reserve_size = res_size,
.commit_size = cmt_size,
.flags = current->flags);
} }
if (new_block) { new_block->base_pos = current->base_pos + current->res;
new_block->base_pos = current->base_pos + current->res; SLLStackPush_N(arena->current, new_block, prev);
SLLStackPush_N(arena->current, new_block, prev);
current = new_block; current = new_block;
pos_mem = AlignPow2(current->pos, current->align); pos_pre = AlignPow2(current->pos, align);
pos_new = pos_mem + size; pos_pst = pos_pre + size;
}
} }
if (current->cmt < pos_new) { // rjf: commit new pages, if needed
U64 cmt_new_aligned, cmt_new_clamped, cmt_new_size; if(current->cmt < pos_pst)
B32 is_cmt_ok; {
U64 cmt_pst_aligned = pos_pst + current->cmt_size-1;
if (current->large_pages) { cmt_pst_aligned -= cmt_pst_aligned%current->cmt_size;
cmt_new_aligned = AlignPow2(pos_new, ARENA_COMMIT_SIZE_LARGE_PAGES); U64 cmt_pst_clamped = ClampTop(cmt_pst_aligned, current->res);
cmt_new_clamped = ClampTop(cmt_new_aligned, current->res); U64 cmt_size = cmt_pst_clamped - current->cmt;
cmt_new_size = cmt_new_clamped - current->cmt; U8 *cmt_ptr = (U8 *)current + current->cmt;
is_cmt_ok = os_commit_large((U8*)current + current->cmt, cmt_new_size); if(current->flags & ArenaFlag_LargePages)
} else { {
cmt_new_aligned = AlignPow2(pos_new, ARENA_COMMIT_SIZE); os_commit_large(cmt_ptr, cmt_size);
cmt_new_clamped = ClampTop(cmt_new_aligned, current->res);
cmt_new_size = cmt_new_clamped - current->cmt;
is_cmt_ok = os_commit((U8*)current + current->cmt, cmt_new_size);
} }
else
if (is_cmt_ok) { {
current->cmt = cmt_new_clamped; os_commit(cmt_ptr, cmt_size);
} }
current->cmt = cmt_pst_clamped;
} }
void *memory = 0; // rjf: push onto current block
void *result = 0;
if (current->cmt >= pos_new) { if(current->cmt >= pos_pst)
memory = (U8*)current + pos_mem; {
current->pos = pos_new; result = (U8 *)current+pos_pre;
AsanUnpoisonMemoryRegion(memory, size); current->pos = pos_pst;
AsanUnpoisonMemoryRegion(result, size);
} }
// rjf: panic on failure
#if OS_FEATURE_GRAPHICAL #if OS_FEATURE_GRAPHICAL
if(Unlikely(memory == 0)) if(Unlikely(result == 0))
{ {
os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure.")); os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
os_exit_process(1); os_abort(1);
} }
#endif #endif
return memory; return result;
} }
internal U64 internal U64
@@ -179,85 +183,35 @@ arena_pos(Arena *arena)
} }
internal void internal void
arena_pop_to(Arena *arena, U64 big_pos_unclamped) arena_pop_to(Arena *arena, U64 pos)
{ {
U64 big_pos = ClampBot(ARENA_HEADER_SIZE, big_pos_unclamped); U64 big_pos = ClampBot(ARENA_HEADER_SIZE, pos);
// unroll the chain
Arena *current = arena->current; Arena *current = arena->current;
for (Arena *prev = 0; current->base_pos >= big_pos; current = prev) {
#if ARENA_FREE_LIST
for(Arena *prev = 0; current->base_pos >= big_pos; current = prev)
{
prev = current->prev;
current->pos = ARENA_HEADER_SIZE;
arena->free_size += current->res_size;
SLLStackPush_N(arena->free_last, current, prev);
AsanPoisonMemoryRegion((U8*)current + ARENA_HEADER_SIZE, current->res_size - ARENA_HEADER_SIZE);
}
#else
for(Arena *prev = 0; current->base_pos >= big_pos; current = prev)
{
prev = current->prev; prev = current->prev;
os_release(current, current->res); os_release(current, current->res);
} }
AssertAlways(current); #endif
arena->current = current; arena->current = current;
// compute arena-relative position
U64 new_pos = big_pos - current->base_pos; U64 new_pos = big_pos - current->base_pos;
AssertAlways(new_pos <= current->pos); AssertAlways(new_pos <= current->pos);
// poison popped memory block
AsanPoisonMemoryRegion((U8*)current + new_pos, (current->pos - new_pos)); AsanPoisonMemoryRegion((U8*)current + new_pos, (current->pos - new_pos));
// update position
current->pos = new_pos; current->pos = new_pos;
} }
internal void //- rjf: arena push/pop helpers
arena_absorb(Arena *arena, Arena *sub)
{
// base adjustment
Arena *current = arena->current;
U64 base_adjust = current->base_pos + current->res;
for (Arena *node = sub->current; node != 0; node = node->prev) {
node->base_pos += base_adjust;
}
// attach sub to arena
sub->prev = arena->current;
arena->current = sub->current;
sub->current = sub;
}
////////////////////////////////
// Wrappers
internal void *
arena_push(Arena *arena, U64 size)
{
void *memory = arena_push__impl(arena, size);
return memory;
}
internal void *
arena_push_contiguous(Arena *arena, U64 size)
{
B32 restore = arena->grow;
arena->grow = 0;
void *memory = arena_push(arena, size);
arena->grow = restore;
return memory;
}
internal void
arena_push_align(Arena *arena, U64 align)
{
Assert(IsPow2(align));
U64 amt = AlignPadPow2(arena->pos, align);
void *ptr = arena_push(arena, amt);
MemoryZero(ptr, amt);
}
internal void
arena_put_back(Arena *arena, U64 amt)
{
U64 pos_old = arena_pos(arena);
U64 pos_new = pos_old;
if (amt < pos_old) {
pos_new = pos_old - amt;
}
arena_pop_to(arena, pos_new);
}
internal void internal void
arena_clear(Arena *arena) arena_clear(Arena *arena)
@@ -265,6 +219,20 @@ arena_clear(Arena *arena)
arena_pop_to(arena, 0); arena_pop_to(arena, 0);
} }
internal void
arena_pop(Arena *arena, U64 amt)
{
U64 pos_old = arena_pos(arena);
U64 pos_new = pos_old;
if(amt < pos_old)
{
pos_new = pos_old - amt;
}
arena_pop_to(arena, pos_new);
}
//- rjf: temporary arena scopes
internal Temp internal Temp
temp_begin(Arena *arena) temp_begin(Arena *arena)
{ {
@@ -278,25 +246,3 @@ temp_end(Temp temp)
{ {
arena_pop_to(temp.arena, temp.pos); arena_pop_to(temp.arena, temp.pos);
} }
////////////////////////////////
//~ NOTE(allen): "Mini-Arena" Helper
internal B32
ensure_commit(void **cmtptr, void *pos, U64 cmt_block_size){
B32 result = 0;
U8 *cmt = (U8*)*cmtptr;
if (cmt < (U8*)pos){
U64 cmt_size_raw = (U8*)pos - cmt;
U64 cmt_size = AlignPow2(cmt_size_raw, cmt_block_size);
if (os_commit(cmt, cmt_size)){
*cmtptr = cmt + cmt_size;
result = 1;
}
}
else{
result = 1;
}
return(result);
}
+51 -47
View File
@@ -9,36 +9,43 @@
#define ARENA_HEADER_SIZE 128 #define ARENA_HEADER_SIZE 128
#ifndef ARENA_RESERVE_SIZE
# define ARENA_RESERVE_SIZE MB(64)
#endif
#ifndef ARENA_COMMIT_SIZE
# define ARENA_COMMIT_SIZE KB(64)
#endif
#ifndef ARENA_RESERVE_SIZE_LARGE_PAGES
# define ARENA_RESERVE_SIZE_LARGE_PAGES MB(8)
#endif
#ifndef ARENA_COMMIT_SIZE_LARGE_PAGES
# define ARENA_COMMIT_SIZE_LARGE_PAGES MB(2)
#endif
//////////////////////////////// ////////////////////////////////
//~ rjf: Arena Types //~ rjf: Types
typedef U64 ArenaFlags;
enum
{
ArenaFlag_NoChain = (1<<0),
ArenaFlag_LargePages = (1<<1),
};
typedef struct ArenaParams ArenaParams;
struct ArenaParams
{
ArenaFlags flags;
U64 reserve_size;
U64 commit_size;
void *optional_backing_buffer;
};
typedef struct Arena Arena; typedef struct Arena Arena;
struct Arena struct Arena
{ {
struct Arena *prev; Arena *prev; // previous arena in chain
struct Arena *current; Arena *current; // current arena in chain
ArenaFlags flags;
U64 cmt_size;
U64 res_size;
U64 base_pos; U64 base_pos;
U64 pos; U64 pos;
U64 cmt; U64 cmt;
U64 res; U64 res;
U64 align; #if ARENA_FREE_LIST
B8 grow; U64 free_size;
B8 large_pages; Arena *free_last;
#endif
}; };
StaticAssert(sizeof(Arena) <= ARENA_HEADER_SIZE, arena_header_size_check);
typedef struct Temp Temp; typedef struct Temp Temp;
struct Temp struct Temp
@@ -48,40 +55,37 @@ struct Temp
}; };
//////////////////////////////// ////////////////////////////////
// Implementation //~ rjf: Global Defaults
internal Arena* arena_alloc__sized(U64 init_res, U64 init_cmt); global U64 arena_default_reserve_size = MB(64);
global U64 arena_default_commit_size = KB(64);
internal Arena* arena_alloc(void); global ArenaFlags arena_default_flags = 0;
internal void arena_release(Arena *arena);
internal void* arena_push__impl(Arena *arena, U64 size);
internal U64 arena_pos(Arena *arena);
internal void arena_pop_to(Arena *arena, U64 pos);
internal void arena_absorb(Arena *arena, Arena *sub);
//////////////////////////////// ////////////////////////////////
// Wrappers //~ rjf: Arena Functions
internal void* arena_push(Arena *arena, U64 size); //- rjf: arena creation/destruction
internal void* arena_push_contiguous(Arena *arena, U64 size); internal Arena *arena_alloc_(ArenaParams *params);
internal void arena_clear(Arena *arena); #define arena_alloc(...) arena_alloc_(&(ArenaParams){.reserve_size = arena_default_reserve_size, .commit_size = arena_default_commit_size, .flags = arena_default_flags, __VA_ARGS__})
internal void arena_push_align(Arena *arena, U64 align); internal void arena_release(Arena *arena);
internal void arena_put_back(Arena *arena, U64 amt);
internal Temp temp_begin(Arena *arena); //- rjf: arena push/pop/pos core functions
internal void temp_end(Temp temp); internal void *arena_push(Arena *arena, U64 size, U64 align);
internal U64 arena_pos(Arena *arena);
internal void arena_pop_to(Arena *arena, U64 pos);
//////////////////////////////// //- rjf: arena push/pop helpers
//~ NOTE(allen): "Mini-Arena" Helper internal void arena_clear(Arena *arena);
internal void arena_pop(Arena *arena, U64 amt);
internal B32 ensure_commit(void **cmt, void *pos, U64 cmt_block_size); //- rjf: temporary arena scopes
internal Temp temp_begin(Arena *arena);
internal void temp_end(Temp temp);
//////////////////////////////// //- rjf: push helper macros
//~ NOTE(allen): Main API Macros #define push_array_no_zero_aligned(a, T, c, align) (T *)arena_push((a), sizeof(T)*(c), (align))
#define push_array_aligned(a, T, c, align) (T *)MemoryZero(push_array_no_zero_aligned(a, T, c, align), sizeof(T)*(c))
#define push_array_no_zero(a,T,c) (T*)arena_push((a), sizeof(T)*(c)) #define push_array_no_zero(a, T, c) push_array_no_zero_aligned(a, T, c, Max(8, AlignOf(T)))
#define push_array(a,T,c) (T*)MemoryZero(push_array_no_zero(a,T,c), sizeof(T)*(c)) #define push_array(a, T, c) push_array_aligned(a, T, c, Max(8, AlignOf(T)))
#endif // BASE_ARENA_H #endif // BASE_ARENA_H
+21 -3
View File
@@ -98,9 +98,10 @@ cmd_line_from_string_list(Arena *arena, String8List command_line)
next = node->next; next = node->next;
String8 option_name = node->string; String8 option_name = node->string;
// NOTE(rjf): Look at -- or - at the start of an argument to determine if it's // NOTE(rjf): Look at --, -, or / (only on Windows) at the start of an
// a flag option. All arguments after a single "--" (with no trailing string // argument to determine if it's a flag option. All arguments after a
// on the command line will be considered as input files. // single "--" (with no trailing string on the command line will be
// considered as input files.
B32 is_option = 1; B32 is_option = 1;
if(after_passthrough_option == 0) if(after_passthrough_option == 0)
{ {
@@ -117,6 +118,11 @@ cmd_line_from_string_list(Arena *arena, String8List command_line)
{ {
option_name = str8_skip(option_name, 1); option_name = str8_skip(option_name, 1);
} }
else if(operating_system_from_context() == OperatingSystem_Windows &&
str8_match(str8_prefix(node->string, 1), str8_lit("/"), 0))
{
option_name = str8_skip(option_name, 1);
}
else else
{ {
is_option = 0; is_option = 0;
@@ -184,6 +190,18 @@ cmd_line_from_string_list(Arena *arena, String8List command_line)
} }
} }
// rjf: fill argc/argv
parsed.argc = command_line.node_count;
parsed.argv = push_array(arena, char *, parsed.argc);
{
U64 idx = 0;
for(String8Node *n = command_line.first; n != 0; n = n->next)
{
parsed.argv[idx] = (char *)push_str8_copy(arena, n->string).str;
idx += 1;
}
}
return parsed; return parsed;
} }
+2
View File
@@ -34,6 +34,8 @@ struct CmdLine
String8List inputs; String8List inputs;
U64 option_table_size; U64 option_table_size;
CmdLineOpt **option_table; CmdLineOpt **option_table;
U64 argc;
char **argv;
}; };
//////////////////////////////// ////////////////////////////////
+3 -3
View File
@@ -155,11 +155,11 @@
#endif #endif
#if !defined(BUILD_VERSION_MINOR) #if !defined(BUILD_VERSION_MINOR)
# define BUILD_VERSION_MINOR 0 # define BUILD_VERSION_MINOR 9
#endif #endif
#if !defined(BUILD_VERSION_PATCH) #if !defined(BUILD_VERSION_PATCH)
# define BUILD_VERSION_PATCH 0 # define BUILD_VERSION_PATCH 14
#endif #endif
#define BUILD_VERSION_STRING_LITERAL Stringify(BUILD_VERSION_MAJOR) "." Stringify(BUILD_VERSION_MINOR) "." Stringify(BUILD_VERSION_PATCH) #define BUILD_VERSION_STRING_LITERAL Stringify(BUILD_VERSION_MAJOR) "." Stringify(BUILD_VERSION_MINOR) "." Stringify(BUILD_VERSION_PATCH)
@@ -183,7 +183,7 @@
#endif #endif
#if !defined(BUILD_ISSUES_LINK_STRING_LITERAL) #if !defined(BUILD_ISSUES_LINK_STRING_LITERAL)
# define BUILD_ISSUES_LINK_STRING_LITERAL "https://github.com/EpicGames/raddebugger/issues" # define BUILD_ISSUES_LINK_STRING_LITERAL "https://github.com/EpicGamesExt/raddebugger/issues"
#endif #endif
#define BUILD_TITLE_STRING_LITERAL BUILD_TITLE " (" BUILD_VERSION_STRING_LITERAL " " BUILD_RELEASE_PHASE_STRING_LITERAL ") - " __DATE__ "" BUILD_GIT_HASH_STRING_LITERAL_APPEND BUILD_MODE_STRING_LITERAL_APPEND #define BUILD_TITLE_STRING_LITERAL BUILD_TITLE " (" BUILD_VERSION_STRING_LITERAL " " BUILD_RELEASE_PHASE_STRING_LITERAL ") - " __DATE__ "" BUILD_GIT_HASH_STRING_LITERAL_APPEND BUILD_MODE_STRING_LITERAL_APPEND
+24 -36
View File
@@ -143,12 +143,6 @@ bswap_u64(U64 x)
#if COMPILER_MSVC || (COMPILER_CLANG && OS_WINDOWS) #if COMPILER_MSVC || (COMPILER_CLANG && OS_WINDOWS)
internal U64
count_bits_set16(U16 val)
{
return __popcnt16(val);
}
internal U64 internal U64
count_bits_set32(U32 val) count_bits_set32(U32 val)
{ {
@@ -195,46 +189,40 @@ clz64(U64 mask)
#elif COMPILER_CLANG || COMPILER_GCC #elif COMPILER_CLANG || COMPILER_GCC
internal U64
count_bits_set16(U16 val)
{
NotImplemented;
return 0;
}
internal U64 internal U64
count_bits_set32(U32 val) count_bits_set32(U32 val)
{ {
NotImplemented; return __builtin_popcount(val);
return 0;
} }
internal U64 internal U64
count_bits_set64(U64 val) count_bits_set64(U64 val)
{ {
NotImplemented; return __builtin_popcountll(val);
return 0;
} }
internal U64 internal U64
ctz32(U32 val) ctz32(U32 val)
{ {
NotImplemented; return __builtin_ctz(val);
return 0;
} }
internal U64 internal U64
clz32(U32 val) clz32(U32 val)
{ {
NotImplemented; return __builtin_clz(val);
return 0; }
internal U64
ctz64(U64 val)
{
return __builtin_ctzll(val);
} }
internal U64 internal U64
clz64(U64 val) clz64(U64 val)
{ {
NotImplemented; return __builtin_clzll(val);
return 0;
} }
#else #else
@@ -399,23 +387,23 @@ txt_rng_contains(TxtRng r, TxtPt pt)
//~ rjf: Toolchain/Environment Enum Functions //~ rjf: Toolchain/Environment Enum Functions
internal U64 internal U64
bit_size_from_arch(Architecture arch) bit_size_from_arch(Arch arch)
{ {
// TODO(rjf): metacode // TODO(rjf): metacode
U64 arch_bitsize = 0; U64 arch_bitsize = 0;
switch(arch) switch(arch)
{ {
case Architecture_x64: arch_bitsize = 64; break; case Arch_x64: arch_bitsize = 64; break;
case Architecture_x86: arch_bitsize = 32; break; case Arch_x86: arch_bitsize = 32; break;
case Architecture_arm64: arch_bitsize = 64; break; case Arch_arm64: arch_bitsize = 64; break;
case Architecture_arm32: arch_bitsize = 32; break; case Arch_arm32: arch_bitsize = 32; break;
default: break; default: break;
} }
return arch_bitsize; return arch_bitsize;
} }
internal U64 internal U64
max_instruction_size_from_arch(Architecture arch) max_instruction_size_from_arch(Arch arch)
{ {
// TODO(rjf): make this real // TODO(rjf): make this real
return 64; return 64;
@@ -434,17 +422,17 @@ operating_system_from_context(void){
return os; return os;
} }
internal Architecture internal Arch
architecture_from_context(void){ arch_from_context(void){
Architecture arch = Architecture_Null; Arch arch = Arch_Null;
#if ARCH_X64 #if ARCH_X64
arch = Architecture_x64; arch = Arch_x64;
#elif ARCH_X86 #elif ARCH_X86
arch = Architecture_x86; arch = Arch_x86;
#elif ARCH_ARM64 #elif ARCH_ARM64
arch = Architecture_arm64; arch = Arch_arm64;
#elif ARCH_ARM32 #elif ARCH_ARM32
arch = Architecture_arm32; arch = Arch_arm32;
#endif #endif
return arch; return arch;
} }
+90 -37
View File
@@ -1,8 +1,8 @@
// Copyright (c) 2024 Epic Games Tools // Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef BASE_TYPES_H #ifndef BASE_CORE_H
#define BASE_TYPES_H #define BASE_CORE_H
//////////////////////////////// ////////////////////////////////
//~ rjf: Foreign Includes //~ rjf: Foreign Includes
@@ -40,6 +40,12 @@
# define thread_static __thread # define thread_static __thread
#endif #endif
#if COMPILER_MSVC
# define force_inline __forceinline
#elif COMPILER_CLANG || COMPILER_GCC
# define force_inline __attribute__((always_inline))
#endif
//////////////////////////////// ////////////////////////////////
//~ rjf: Linkage Keyword Macros //~ rjf: Linkage Keyword Macros
@@ -91,6 +97,19 @@
#define ClampBot(X,B) Max(X,B) #define ClampBot(X,B) Max(X,B)
#define Clamp(A,X,B) (((X)<(A))?(A):((X)>(B))?(B):(X)) #define Clamp(A,X,B) (((X)<(A))?(A):((X)>(B))?(B):(X))
////////////////////////////////
//~ rjf: Type -> Alignment
#if COMPILER_MSVC
# define AlignOf(T) __alignof(T)
#elif COMPILER_CLANG
# define AlignOf(T) __alignof(T)
#elif COMPILER_GCC
# define AlignOf(T) __alignof__(T)
#else
# error AlignOf not defined for this compiler.
#endif
//////////////////////////////// ////////////////////////////////
//~ rjf: Member Offsets //~ rjf: Member Offsets
@@ -105,8 +124,10 @@
#define DeferLoop(begin, end) for(int _i_ = ((begin), 0); !_i_; _i_ += 1, (end)) #define DeferLoop(begin, end) for(int _i_ = ((begin), 0); !_i_; _i_ += 1, (end))
#define DeferLoopChecked(begin, end) for(int _i_ = 2 * !(begin); (_i_ == 2 ? ((end), 0) : !_i_); _i_ += 1, (end)) #define DeferLoopChecked(begin, end) for(int _i_ = 2 * !(begin); (_i_ == 2 ? ((end), 0) : !_i_); _i_ += 1, (end))
#define EachEnumVal(type, it) type it = (type)0; it < type##_COUNT; it = (type)(it+1) #define EachIndex(it, count) (U64 it = 0; it < (count); it += 1)
#define EachNonZeroEnumVal(type, it) type it = (type)1; it < type##_COUNT; it = (type)(it+1) #define EachElement(it, array) (U64 it = 0; it < ArrayCount(array); it += 1)
#define EachEnumVal(type, it) (type it = (type)0; it < type##_COUNT; it = (type)(it+1))
#define EachNonZeroEnumVal(type, it) (type it = (type)1; it < type##_COUNT; it = (type)(it+1))
//////////////////////////////// ////////////////////////////////
//~ rjf: Memory Operation Macros //~ rjf: Memory Operation Macros
@@ -157,33 +178,49 @@
//////////////////////////////// ////////////////////////////////
//~ rjf: Atomic Operations //~ rjf: Atomic Operations
#if OS_WINDOWS #if COMPILER_MSVC
# include <windows.h>
# include <tmmintrin.h>
# include <wmmintrin.h>
# include <intrin.h> # include <intrin.h>
# if ARCH_X64 # if ARCH_X64
# define ins_atomic_u64_eval(x) InterlockedAdd64((volatile __int64 *)(x), 0) # define ins_atomic_u64_eval(x) *((volatile U64 *)(x))
# define ins_atomic_u64_inc_eval(x) InterlockedIncrement64((volatile __int64 *)(x)) # define ins_atomic_u64_inc_eval(x) InterlockedIncrement64((volatile __int64 *)(x))
# define ins_atomic_u64_dec_eval(x) InterlockedDecrement64((volatile __int64 *)(x)) # define ins_atomic_u64_dec_eval(x) InterlockedDecrement64((volatile __int64 *)(x))
# define ins_atomic_u64_eval_assign(x,c) InterlockedExchange64((volatile __int64 *)(x),(c)) # define ins_atomic_u64_eval_assign(x,c) InterlockedExchange64((volatile __int64 *)(x),(c))
# define ins_atomic_u64_add_eval(x,c) InterlockedAdd64((volatile __int64 *)(x), c) # define ins_atomic_u64_add_eval(x,c) InterlockedAdd64((volatile __int64 *)(x), c)
# define ins_atomic_u64_eval_cond_assign(x,k,c) InterlockedCompareExchange64((volatile __int64 *)(x),(k),(c)) # define ins_atomic_u64_eval_cond_assign(x,k,c) InterlockedCompareExchange64((volatile __int64 *)(x),(k),(c))
# define ins_atomic_u32_eval(x,c) InterlockedAdd((volatile LONG *)(x), 0) # define ins_atomic_u32_eval(x) *((volatile U32 *)(x))
# define ins_atomic_u32_eval_assign(x,c) InterlockedExchange((volatile LONG *)(x),(c)) # define ins_atomic_u32_inc_eval(x) InterlockedIncrement((volatile LONG *)x)
# define ins_atomic_u32_eval_assign(x,c) InterlockedExchange((volatile LONG *)(x),(c))
# define ins_atomic_u32_eval_cond_assign(x,k,c) InterlockedCompareExchange((volatile LONG *)(x),(k),(c)) # define ins_atomic_u32_eval_cond_assign(x,k,c) InterlockedCompareExchange((volatile LONG *)(x),(k),(c))
# define ins_atomic_ptr_eval_assign(x,c) (void*)ins_atomic_u64_eval_assign((volatile __int64 *)(x), (__int64)(c)) # define ins_atomic_u32_add_eval(x,c) InterlockedAdd((volatile LONG *)(x), c)
# else # else
# error Atomic intrinsics not defined for this operating system / architecture combination. # error Atomic intrinsics not defined for this compiler / architecture combination.
# endif
#elif OS_LINUX
# if ARCH_X64
# define ins_atomic_u64_inc_eval(x) __sync_fetch_and_add((volatile U64 *)(x), 1)
# else
# error Atomic intrinsics not defined for this operating system / architecture combination.
# endif # endif
#elif COMPILER_CLANG || COMPILER_GCC
# define ins_atomic_u64_eval(x) __atomic_load_n(x, __ATOMIC_SEQ_CST)
# define ins_atomic_u64_inc_eval(x) (__atomic_fetch_add((volatile U64 *)(x), 1, __ATOMIC_SEQ_CST) + 1)
# define ins_atomic_u64_dec_eval(x) (__atomic_fetch_sub((volatile U64 *)(x), 1, __ATOMIC_SEQ_CST) - 1)
# define ins_atomic_u64_eval_assign(x,c) __atomic_exchange_n(x, c, __ATOMIC_SEQ_CST)
# define ins_atomic_u64_add_eval(x,c) (__atomic_fetch_add((volatile U64 *)(x), c, __ATOMIC_SEQ_CST) + (c))
# define ins_atomic_u64_eval_cond_assign(x,k,c) ({ U64 _new = (c); __atomic_compare_exchange_n((volatile U64 *)(x),&_new,(k),0,__ATOMIC_SEQ_CST,__ATOMIC_SEQ_CST); _new; })
# define ins_atomic_u32_eval(x) __atomic_load_n(x, __ATOMIC_SEQ_CST)
# define ins_atomic_u32_inc_eval(x) (__atomic_fetch_add((volatile U32 *)(x), 1, __ATOMIC_SEQ_CST) + 1)
# define ins_atomic_u32_add_eval(x,c) (__atomic_fetch_add((volatile U32 *)(x), c, __ATOMIC_SEQ_CST) + (c))
# define ins_atomic_u32_eval_assign(x,c) __atomic_exchange_n(x, c, __ATOMIC_SEQ_CST)
# define ins_atomic_u32_eval_cond_assign(x,k,c) ({ U32 _new = (c); __atomic_compare_exchange_n((volatile U32 *)(x),&_new,(k),0,__ATOMIC_SEQ_CST,__ATOMIC_SEQ_CST); _new; })
#else #else
# error Atomic intrinsics not defined for this operating system. # error Atomic intrinsics not defined for this compiler / architecture.
#endif
#if ARCH_64BIT
# define ins_atomic_ptr_eval_cond_assign(x,k,c) (void*)ins_atomic_u64_eval_cond_assign((volatile U64 *)(x), (U64)(k), (U64)(c))
# define ins_atomic_ptr_eval_assign(x,c) (void*)ins_atomic_u64_eval_assign((volatile U64 *)(x), (U64)(c))
# define ins_atomic_ptr_eval(x) (void*)ins_atomic_u64_eval((volatile U64 *)x)
#elif ARCH_32BIT
# define ins_atomic_ptr_eval_cond_assign(x,k,c) (void*)ins_atomic_u32_eval_cond_assign((volatile U32 *)(x), (U32)(k), (U32)(c))
# define ins_atomic_ptr_eval_assign(x,c) (void*)ins_atomic_u32_eval_assign((volatile U32 *)(x), (U32)(c))
# define ins_atomic_ptr_eval(x) (void*)ins_atomic_u32_eval((volatile U32 *)x)
#else
# error Atomic intrinsics for pointers not defined for this architecture.
#endif #endif
//////////////////////////////// ////////////////////////////////
@@ -265,7 +302,7 @@ CheckNil(nil,p) ? \
# endif # endif
# define NO_ASAN __attribute__((no_sanitize("address"))) # define NO_ASAN __attribute__((no_sanitize("address")))
#else #else
# error "NO_ASAN is not defined for this compiler." # define NO_ASAN
#endif #endif
#if ASAN_ENABLED #if ASAN_ENABLED
@@ -417,16 +454,16 @@ typedef enum OperatingSystem
} }
OperatingSystem; OperatingSystem;
typedef enum Architecture typedef enum Arch
{ {
Architecture_Null, Arch_Null,
Architecture_x64, Arch_x64,
Architecture_x86, Arch_x86,
Architecture_arm64, Arch_arm64,
Architecture_arm32, Arch_arm32,
Architecture_COUNT, Arch_COUNT,
} }
Architecture; Arch;
typedef enum Compiler typedef enum Compiler
{ {
@@ -455,6 +492,23 @@ struct TxtRng
TxtPt max; TxtPt max;
}; };
////////////////////////////////
//~ Globally Unique Ids
typedef union Guid Guid;
union Guid
{
struct
{
U32 data1;
U16 data2;
U16 data3;
U8 data4[8];
};
U8 v[16];
};
StaticAssert(sizeof(Guid) == 16, g_guid_size_check);
//////////////////////////////// ////////////////////////////////
//~ NOTE(allen): Constants //~ NOTE(allen): Constants
@@ -721,7 +775,6 @@ internal U16 bswap_u16(U16 x);
internal U32 bswap_u32(U32 x); internal U32 bswap_u32(U32 x);
internal U64 bswap_u64(U64 x); internal U64 bswap_u64(U64 x);
internal U64 count_bits_set16(U16 val);
internal U64 count_bits_set32(U32 val); internal U64 count_bits_set32(U32 val);
internal U64 count_bits_set64(U64 val); internal U64 count_bits_set64(U64 val);
@@ -757,11 +810,11 @@ internal B32 txt_rng_contains(TxtRng r, TxtPt pt);
//////////////////////////////// ////////////////////////////////
//~ rjf: Toolchain/Environment Enum Functions //~ rjf: Toolchain/Environment Enum Functions
internal U64 bit_size_from_arch(Architecture arch); internal U64 bit_size_from_arch(Arch arch);
internal U64 max_instruction_size_from_arch(Architecture arch); internal U64 max_instruction_size_from_arch(Arch arch);
internal OperatingSystem operating_system_from_context(void); internal OperatingSystem operating_system_from_context(void);
internal Architecture architecture_from_context(void); internal Arch arch_from_context(void);
internal Compiler compiler_from_context(void); internal Compiler compiler_from_context(void);
//////////////////////////////// ////////////////////////////////
+61 -26
View File
@@ -1,28 +1,43 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
global U64 global_update_tick_idx = 0;
internal void internal void
main_thread_base_entry_point(void (*entry_point)(CmdLine *cmdline), char **arguments, U64 arguments_count) main_thread_base_entry_point(int arguments_count, char **arguments)
{ {
Temp scratch = scratch_begin(0, 0);
ThreadNameF("[main thread]");
//- rjf: set up telemetry
#if PROFILE_TELEMETRY #if PROFILE_TELEMETRY
local_persist U8 tm_data[MB(64)]; local_persist char tm_data[MB(64)];
tmLoadLibrary(TM_RELEASE); tmLoadLibrary(TM_RELEASE);
tmSetMaxThreadCount(256); tmSetMaxThreadCount(256);
tmInitialize(sizeof(tm_data), (char *)tm_data); tmInitialize(sizeof(tm_data), tm_data);
#endif #endif
TCTX tctx;
tctx_init_and_equip(&tctx); //- rjf: parse command line
ThreadNameF("[main thread]"); String8List command_line_argument_strings = os_string_list_from_argcv(scratch.arena, arguments_count, arguments);
Temp scratch = scratch_begin(0, 0);
String8List command_line_argument_strings = os_string_list_from_argcv(scratch.arena, (int)arguments_count, arguments);
CmdLine cmdline = cmd_line_from_string_list(scratch.arena, command_line_argument_strings); CmdLine cmdline = cmd_line_from_string_list(scratch.arena, command_line_argument_strings);
//- rjf: begin captures
B32 capture = cmd_line_has_flag(&cmdline, str8_lit("capture")); B32 capture = cmd_line_has_flag(&cmdline, str8_lit("capture"));
if(capture) if(capture)
{ {
ProfBeginCapture(arguments[0]); ProfBeginCapture(arguments[0]);
} }
#if defined(OS_CORE_H) && !defined(OS_INIT_MANUAL)
os_init(); #if PROFILE_TELEMETRY
tmMessage(0, TMMF_ICON_NOTE, BUILD_TITLE);
#endif #endif
#if defined(TASK_SYSTEM_H) && !defined(TS_INIT_MANUAL)
ts_init(); //- rjf: initialize all included layers
#if defined(ASYNC_H) && !defined(ASYNC_INIT_MANUAL)
async_init();
#endif
#if defined(RDI_FROM_PDB_H) && !defined(P2R_INIT_MANUAL)
p2r_init();
#endif #endif
#if defined(HASH_STORE_H) && !defined(HS_INIT_MANUAL) #if defined(HASH_STORE_H) && !defined(HS_INIT_MANUAL)
hs_init(); hs_init();
@@ -39,20 +54,17 @@ main_thread_base_entry_point(void (*entry_point)(CmdLine *cmdline), char **argum
#if defined(DASM_CACHE_H) && !defined(DASM_INIT_MANUAL) #if defined(DASM_CACHE_H) && !defined(DASM_INIT_MANUAL)
dasm_init(); dasm_init();
#endif #endif
#if defined(DI_H) && !defined(DI_INIT_MANUAL) #if defined(DBGI_H) && !defined(DI_INIT_MANUAL)
di_init(); di_init();
#endif #endif
#if defined(FUZZY_SEARCH_H) && !defined(FZY_INIT_MANUAL)
fzy_init();
#endif
#if defined(DEMON_CORE_H) && !defined(DMN_INIT_MANUAL) #if defined(DEMON_CORE_H) && !defined(DMN_INIT_MANUAL)
dmn_init(); dmn_init();
#endif #endif
#if defined(CTRL_CORE_H) && !defined(CTRL_INIT_MANUAL) #if defined(CTRL_CORE_H) && !defined(CTRL_INIT_MANUAL)
ctrl_init(); ctrl_init();
#endif #endif
#if defined(OS_GRAPHICAL_H) && !defined(OS_GFX_INIT_MANUAL) #if defined(OS_GFX_H) && !defined(OS_GFX_INIT_MANUAL)
os_graphical_init(); os_gfx_init();
#endif #endif
#if defined(FONT_PROVIDER_H) && !defined(FP_INIT_MANUAL) #if defined(FONT_PROVIDER_H) && !defined(FP_INIT_MANUAL)
fp_init(); fp_init();
@@ -66,23 +78,26 @@ main_thread_base_entry_point(void (*entry_point)(CmdLine *cmdline), char **argum
#if defined(GEO_CACHE_H) && !defined(GEO_INIT_MANUAL) #if defined(GEO_CACHE_H) && !defined(GEO_INIT_MANUAL)
geo_init(); geo_init();
#endif #endif
#if defined(FONT_CACHE_H) && !defined(F_INIT_MANUAL) #if defined(FONT_CACHE_H) && !defined(FNT_INIT_MANUAL)
f_init(); fnt_init();
#endif #endif
#if defined(DF_CORE_H) && !defined(DF_INIT_MANUAL) #if defined(DBG_ENGINE_CORE_H) && !defined(D_INIT_MANUAL)
DF_StateDeltaHistory *hist = df_state_delta_history_alloc(); d_init();
df_core_init(&cmdline, hist);
#endif #endif
#if defined(DF_GFX_H) && !defined(DF_GFX_INIT_MANUAL) #if defined(RADDBG_CORE_H) && !defined(RD_INIT_MANUAL)
df_gfx_init(update_and_render, df_state_delta_history()); rd_init(&cmdline);
#endif #endif
//- rjf: call into entry point
entry_point(&cmdline); entry_point(&cmdline);
//- rjf: end captures
if(capture) if(capture)
{ {
ProfEndCapture(); ProfEndCapture();
} }
scratch_end(scratch); scratch_end(scratch);
tctx_release();
} }
internal void internal void
@@ -93,3 +108,23 @@ supplement_thread_base_entry_point(void (*entry_point)(void *params), void *para
entry_point(params); entry_point(params);
tctx_release(); tctx_release();
} }
internal U64
update_tick_idx(void)
{
U64 result = ins_atomic_u64_eval(&global_update_tick_idx);
return result;
}
internal B32
update(void)
{
ProfTick(0);
ins_atomic_u64_inc_eval(&global_update_tick_idx);
#if OS_FEATURE_GRAPHICAL
B32 result = frame();
#else
B32 result = 0;
#endif
return result;
}
+3 -1
View File
@@ -4,7 +4,9 @@
#ifndef BASE_ENTRY_POINT_H #ifndef BASE_ENTRY_POINT_H
#define BASE_ENTRY_POINT_H #define BASE_ENTRY_POINT_H
internal void main_thread_base_entry_point(void (*entry_point)(CmdLine *cmdline), char **arguments, U64 arguments_count); internal void main_thread_base_entry_point(int argc, char **argv);
internal void supplement_thread_base_entry_point(void (*entry_point)(void *params), void *params); internal void supplement_thread_base_entry_point(void (*entry_point)(void *params), void *params);
internal U64 update_tick_idx(void);
internal B32 update(void);
#endif // BASE_ENTRY_POINT_H #endif // BASE_ENTRY_POINT_H
+3 -2
View File
@@ -4,8 +4,8 @@
//////////////////////////////// ////////////////////////////////
//~ rjf: Base Includes //~ rjf: Base Includes
#undef RADDBG_LAYER_COLOR #undef MARKUP_LAYER_COLOR
#define RADDBG_LAYER_COLOR 0.20f, 0.60f, 0.80f #define MARKUP_LAYER_COLOR 0.20f, 0.60f, 0.80f
#include "base_core.c" #include "base_core.c"
#include "base_profile.c" #include "base_profile.c"
@@ -15,5 +15,6 @@
#include "base_thread_context.c" #include "base_thread_context.c"
#include "base_command_line.c" #include "base_command_line.c"
#include "base_markup.c" #include "base_markup.c"
#include "base_meta.c"
#include "base_log.c" #include "base_log.c"
#include "base_entry_point.c" #include "base_entry_point.c"
+1
View File
@@ -17,6 +17,7 @@
#include "base_thread_context.h" #include "base_thread_context.h"
#include "base_command_line.h" #include "base_command_line.h"
#include "base_markup.h" #include "base_markup.h"
#include "base_meta.h"
#include "base_log.h" #include "base_log.h"
#include "base_entry_point.h" #include "base_entry_point.h"
+1 -1
View File
@@ -88,7 +88,7 @@ log_scope_end(Arena *arena)
SLLStackPop(log_active->top_scope); SLLStackPop(log_active->top_scope);
if(arena != 0) if(arena != 0)
{ {
for(EachEnumVal(LogMsgKind, kind)) for EachEnumVal(LogMsgKind, kind)
{ {
Temp scratch = scratch_begin(&arena, 1); Temp scratch = scratch_begin(&arena, 1);
String8 result_unindented = str8_list_join(scratch.arena, &scope->strings[kind], 0); String8 result_unindented = str8_list_join(scratch.arena, &scope->strings[kind], 0);
+422
View File
@@ -0,0 +1,422 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Type Info Lookups
internal Member *
member_from_name(Type *type, String8 name)
{
Member *member = &member_nil;
if(type->members != 0 && name.size != 0)
{
for(U64 idx = 0; idx < type->count; idx += 1)
{
if(str8_match(type->members[idx].name, name, 0))
{
member = &type->members[idx];
break;
}
}
}
return member;
}
////////////////////////////////
//~ rjf: Type Info * Instance Operations
internal void
typed_data_rebase_ptrs(Type *type, String8 data, void *base_ptr)
{
Temp scratch = scratch_begin(0, 0);
typedef struct RebaseTypeTask RebaseTypeTask;
struct RebaseTypeTask
{
RebaseTypeTask *next;
Type *type;
U8 *ptr;
};
RebaseTypeTask start_task = {0, type, data.str};
RebaseTypeTask *first_task = &start_task;
RebaseTypeTask *last_task = first_task;
for(RebaseTypeTask *t = first_task; t != 0; t = t->next)
{
switch(t->type->kind)
{
default:{}break;
case TypeKind_Ptr:
if(!(t->type->flags & TypeFlag_IsExternal))
{
*(U64 *)t->ptr = ((U64)(*(U8 **)t->ptr - (U8 *)base_ptr));
}break;
case TypeKind_Array:
{
for(U64 idx = 0; idx < t->type->count; idx += 1)
{
RebaseTypeTask *task = push_array(scratch.arena, RebaseTypeTask, 1);
task->type = t->type->direct;
task->ptr = t->ptr + t->type->direct->size * idx;
SLLQueuePush(first_task, last_task, task);
}
}break;
case TypeKind_Struct:
{
for(U64 idx = 0; idx < t->type->count; idx += 1)
{
Member *member = &t->type->members[idx];
RebaseTypeTask *task = push_array(scratch.arena, RebaseTypeTask, 1);
task->type = member->type;
task->ptr = t->ptr + member->value;
SLLQueuePush(first_task, last_task, task);
}
}break;
}
}
scratch_end(scratch);
}
internal String8
serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params)
{
Temp scratch = scratch_begin(&arena, 1);
String8List strings = {0};
str8_serial_begin(scratch.arena, &strings);
{
typedef struct SerializeTypeTask SerializeTypeTask;
struct SerializeTypeTask
{
SerializeTypeTask *next;
Type *type;
U64 count;
U8 *src;
Type *containing_type;
U8 *containing_ptr;
B32 is_post_header;
};
SerializeTypeTask start_task = {0, type, 1, data.str};
SerializeTypeTask *first_task = &start_task;
SerializeTypeTask *last_task = first_task;
for(SerializeTypeTask *t = first_task; t != 0; t = t->next)
{
switch(t->type->kind)
{
//- rjf: leaf -> just copy the data directly
default:
if(TypeKind_FirstLeaf <= t->type->kind && t->type->kind <= TypeKind_LastLeaf)
{
str8_serial_push_string(scratch.arena, &strings, str8(t->src, t->type->size*t->count));
}break;
//- rjf: pointers -> try to interpret/understand pointer & read/write, otherwise just write as plain data
case TypeKind_Ptr:
{
// rjf: unpack info about this pointer
TypeSerializePtrRefInfo *ptr_ref_info = 0;
for(U64 idx = 0; idx < params->ptr_ref_infos_count; idx += 1)
{
if(params->ptr_ref_infos[idx].type == t->type->direct)
{
ptr_ref_info = &params->ptr_ref_infos[idx];
break;
}
}
// rjf: indexification -> subtract base, divide direct size, write index
if(ptr_ref_info != 0 && ptr_ref_info->indexify_base != 0)
{
U64 ptr_value = 0;
MemoryCopy(&ptr_value, t->src, sizeof(ptr_value));
U64 ptr_write_value = ((U64)((U8 *)ptr_value - (U8 *)ptr_ref_info->indexify_base)/t->type->direct->size);
str8_serial_push_struct(scratch.arena, &strings, &ptr_write_value);
}
// rjf: offsetification -> subtract base, write offsets
else if(ptr_ref_info != 0 && ptr_ref_info->offsetify_base != 0)
{
U64 ptr_value = 0;
MemoryCopy(&ptr_value, t->src, sizeof(ptr_value));
U64 ptr_write_value = (U64)((U8 *)ptr_value - (U8 *)ptr_ref_info->offsetify_base);
str8_serial_push_struct(scratch.arena, &strings, &ptr_write_value);
}
// rjf: size-by-member (pre-header): still potentially dependent on other members which
// delimit our size, so push a new post-header task for pointer.
else if(t->type->count_delimiter_name.size != 0 && !t->is_post_header)
{
SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1);
task->type = t->type;
task->count = t->count;
task->src = t->src;
task->containing_type = t->containing_type;
task->containing_ptr = t->containing_ptr;
task->is_post_header = 1;
SLLQueuePush(first_task, last_task, task);
}
// rjf: size-by-member (post-header): all flat parts of containing struct have been
// iterated, so now we can read the size, & descend to new task to read pointer
// destination contents
else if(t->type->count_delimiter_name.size != 0 && t->is_post_header)
{
// rjf: determine count of this pointer
U64 count = 0;
{
Member *count_member = member_from_name(t->containing_type, t->type->count_delimiter_name);
MemoryCopy(&count, t->containing_ptr + count_member->value, count_member->type->size);
}
// rjf: push task
SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1);
task->type = t->type->direct;
task->count = count;
task->src = *(void **)t->src;
task->containing_type = t->containing_type;
task->containing_ptr = t->containing_ptr;
SLLQueuePush(first_task, last_task, task);
}
// rjf: catch-all: write pointer value
else
{
str8_serial_push_string(scratch.arena, &strings, str8(t->src, t->type->size*t->count));
}
}break;
//- rjf: arrays -> descend to underlying type, + count
case TypeKind_Array:
{
SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1);
task->type = t->type->direct;
task->count = t->type->count;
task->src = t->src;
task->containing_type = t->containing_type;
task->containing_ptr = t->containing_ptr;
SLLQueuePush(first_task, last_task, task);
}break;
//- rjf: struct -> descend to members
case TypeKind_Struct:
{
U64 off = 0;
for(U64 idx = 0; idx < t->count; idx += 1)
{
for(U64 member_idx = 0; member_idx < t->type->count; member_idx += 1)
{
if(t->type->members[member_idx].flags & MemberFlag_DoNotSerialize)
{
continue;
}
SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1);
task->type = t->type->members[member_idx].type;
task->count = 1;
task->src = t->src + idx*t->type->size + t->type->members[member_idx].value;
task->containing_type = t->type;
task->containing_ptr = t->src;
SLLQueuePush(first_task, last_task, task);
}
}
}break;
//- rjf: enum -> descend to basic type interpretation
case TypeKind_Enum:
{
SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1);
task->type = t->type->direct;
task->count = t->count;
task->src = t->src;
task->containing_type = t->containing_type;
task->containing_ptr = t->containing_ptr;
SLLQueuePush(first_task, last_task, task);
}break;
}
}
}
String8 result = str8_serial_end(arena, &strings);
scratch_end(scratch);
return result;
}
internal String8
deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params)
{
String8 result = {0};
result.size = type->size;
result.str = push_array(arena, U8, result.size);
{
Temp scratch = scratch_begin(&arena, 1);
typedef struct DeserializeTypeTask DeserializeTypeTask;
struct DeserializeTypeTask
{
DeserializeTypeTask *next;
Type *type;
U64 count;
U8 *dst;
Type *containing_type;
U8 *containing_ptr;
B32 is_post_header;
};
U64 read_off = 0;
DeserializeTypeTask start_task = {0, type, 1, result.str};
DeserializeTypeTask *first_task = &start_task;
DeserializeTypeTask *last_task = first_task;
for(DeserializeTypeTask *t = first_task; t != 0; t = t->next)
{
U8 *t_src = data.str + read_off;
switch(t->type->kind)
{
//- rjf: leaf -> copy the data directly
default:
if(TypeKind_FirstLeaf <= t->type->kind && t->type->kind <= TypeKind_LastLeaf)
{
MemoryCopy(t->dst, t_src, t->type->size*t->count);
read_off += t->type->size*t->count;
}break;
//- rjf: pointers -> try to interpret/understand pointer & read/write, otherwise skip
case TypeKind_Ptr:
{
// rjf: unpack info about this pointer
TypeSerializePtrRefInfo *ptr_ref_info = 0;
for(U64 idx = 0; idx < params->ptr_ref_infos_count; idx += 1)
{
if(params->ptr_ref_infos[idx].type == t->type->direct)
{
ptr_ref_info = &params->ptr_ref_infos[idx];
break;
}
}
// rjf: indexification -> add base, multiply direct size
if(ptr_ref_info != 0 && ptr_ref_info->indexify_base != 0)
{
U64 ptr_value = 0;
MemoryCopy(&ptr_value, t_src, sizeof(ptr_value));
U64 ptr_write_value = (ptr_value + (U64)ptr_ref_info->indexify_base) * t->type->direct->size;
MemoryCopy(t->dst, &ptr_write_value, sizeof(ptr_write_value));
read_off += sizeof(ptr_value);
}
// rjf: offsetification -> subtract base, write offsets
else if(ptr_ref_info != 0 && ptr_ref_info->offsetify_base != 0)
{
U64 ptr_value = 0;
MemoryCopy(&ptr_value, t_src, sizeof(ptr_value));
U64 ptr_write_value = ptr_value + (U64)ptr_ref_info->offsetify_base;
MemoryCopy(t->dst, &ptr_write_value, sizeof(ptr_write_value));
read_off += sizeof(ptr_value);
}
// rjf: size-by-member (pre-header): still potentially dependent on other members which
// delimit our size, so push a new post-header task for pointer.
else if(t->type->count_delimiter_name.size != 0 && !t->is_post_header)
{
DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1);
task->type = t->type;
task->count = t->count;
task->dst = t->dst;
task->containing_type = t->containing_type;
task->containing_ptr = t->containing_ptr;
task->is_post_header = 1;
SLLQueuePush(first_task, last_task, task);
}
// rjf: size-by-member (post-header): all flat parts of containing struct have been
// iterated, so now we can read the size, & descend to new task to read pointer
// destination contents
else if(t->type->count_delimiter_name.size != 0 && t->is_post_header)
{
// rjf: determine count of this pointer
U64 count = 0;
{
Member *count_member = member_from_name(t->containing_type, t->type->count_delimiter_name);
MemoryCopy(&count, t->containing_ptr + count_member->value, count_member->type->size);
}
// rjf: allocate buffer for pointer destination; write address into pointer value slot
U64 ptr_dest_buffer_size = (count+1)*t->type->direct->size;
U8 *ptr_dest_buffer = push_array(arena, U8, ptr_dest_buffer_size);
MemoryCopy(t->dst, &ptr_dest_buffer, sizeof(ptr_dest_buffer));
// rjf: push task
DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1);
task->type = t->type->direct;
task->count = count;
task->dst = ptr_dest_buffer;
task->containing_type = t->containing_type;
task->containing_ptr = t->containing_ptr;
SLLQueuePush(first_task, last_task, task);
}
// rjf: catch-all: read pointer value
else
{
MemoryCopy(t->dst, t_src, t->type->size*t->count);
read_off += t->type->size*t->count;
}
}break;
//- rjf: arrays -> descend to underlying type, + count
case TypeKind_Array:
{
DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1);
task->type = t->type->direct;
task->count = t->type->count;
task->dst = t->dst;
task->containing_type = t->containing_type;
task->containing_ptr = t->containing_ptr;
SLLQueuePush(first_task, last_task, task);
}break;
//- rjf: struct -> descend to members
case TypeKind_Struct:
{
for(U64 idx = 0; idx < t->count; idx += 1)
{
for(U64 member_idx = 0; member_idx < t->type->count; member_idx += 1)
{
if(t->type->members[member_idx].flags & MemberFlag_DoNotSerialize)
{
continue;
}
DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1);
task->type = t->type->members[member_idx].type;
task->count = 1;
task->dst = t->dst + idx*t->type->size + t->type->members[member_idx].value;
task->containing_type = t->type;
task->containing_ptr = t->dst;
SLLQueuePush(first_task, last_task, task);
}
}
}break;
//- rjf: enum -> descend to basic type interpretation
case TypeKind_Enum:
{
DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1);
task->type = t->type->direct;
task->count = t->count;
task->dst = t->dst;
task->containing_type = t->containing_type;
task->containing_ptr = t->containing_ptr;
SLLQueuePush(first_task, last_task, task);
}break;
}
}
if(params->advance_out != 0)
{
params->advance_out[0] = read_off;
}
scratch_end(scratch);
}
return result;
}
internal String8
deep_copy_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params)
{
Temp scratch = scratch_begin(&arena, 1);
String8 data_srlz = serialized_from_typed_data(scratch.arena, type, data, params);
String8 data_copy = deserialized_from_typed_data(arena, type, data_srlz, params);
scratch_end(scratch);
return data_copy;
}
+298
View File
@@ -0,0 +1,298 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef BASE_META_H
#define BASE_META_H
////////////////////////////////
//~ rjf: Meta Markup Features
#define EmbedFile(name, path)
#define TweakB32(name, default) (TWEAK_##name)
#define TweakF32(name, default, min, max) (TWEAK_##name)
////////////////////////////////
//~ rjf: Tweak Info Tables
typedef struct TweakB32Info TweakB32Info;
struct TweakB32Info
{
String8 name;
B32 default_value;
B32 *value_ptr;
};
typedef struct TweakF32Info TweakF32Info;
struct TweakF32Info
{
String8 name;
F32 default_value;
Rng1F32 value_range;
F32 *value_ptr;
};
typedef struct TweakB32InfoTable TweakB32InfoTable;
struct TweakB32InfoTable
{
TweakB32Info *v;
U64 count;
};
typedef struct TweakF32InfoTable TweakF32InfoTable;
struct TweakF32InfoTable
{
TweakF32Info *v;
U64 count;
};
typedef struct EmbedInfo EmbedInfo;
struct EmbedInfo
{
String8 name;
String8 *data;
U128 *hash;
};
typedef struct EmbedInfoTable EmbedInfoTable;
struct EmbedInfoTable
{
EmbedInfo *v;
U64 count;
};
////////////////////////////////
//~ rjf: Type Info Types
typedef enum TypeKind
{
TypeKind_Null,
// rjf: leaves
TypeKind_Void, TypeKind_FirstLeaf = TypeKind_Void,
TypeKind_U8,
TypeKind_U16,
TypeKind_U32,
TypeKind_U64,
TypeKind_S8,
TypeKind_S16,
TypeKind_S32,
TypeKind_S64,
TypeKind_B8,
TypeKind_B16,
TypeKind_B32,
TypeKind_B64,
TypeKind_F32,
TypeKind_F64, TypeKind_LastLeaf = TypeKind_F64,
// rjf: operators
TypeKind_Ptr,
TypeKind_Array,
// rjf: user-defined-types
TypeKind_Struct,
TypeKind_Union,
TypeKind_Enum,
TypeKind_COUNT
}
TypeKind;
typedef U32 TypeFlags;
enum
{
TypeFlag_IsExternal = (1<<0),
TypeFlag_IsPlainText = (1<<1),
TypeFlag_IsCodeText = (1<<2),
TypeFlag_IsPathText = (1<<3),
};
typedef U32 MemberFlags;
enum
{
MemberFlag_DoNotSerialize = (1<<0),
};
typedef struct Type Type;
typedef struct Member Member;
struct Member
{
String8 name;
String8 pretty_name;
Type *type;
U64 value;
MemberFlags flags;
};
typedef struct Type Type;
struct Type
{
TypeKind kind;
TypeFlags flags;
U64 size;
Type *direct;
String8 name;
String8 count_delimiter_name; // gathered from surrounding members, turns *->[1] into *->[N]
U64 count;
Member *members;
};
////////////////////////////////
//~ rjf: Type Serialization Parameters
typedef struct TypeSerializePtrRefInfo TypeSerializePtrRefInfo;
struct TypeSerializePtrRefInfo
{
Type *type; // pointers to this
void *indexify_base; // can be indexified using this
void *offsetify_base; // can be offsetified using this
void *nil_ptr; // is terminal if matching 0 or this
};
typedef struct TypeSerializeParams TypeSerializeParams;
struct TypeSerializeParams
{
U64 *advance_out;
TypeSerializePtrRefInfo *ptr_ref_infos;
U64 ptr_ref_infos_count;
};
////////////////////////////////
//~ rjf: Type Name -> Type Info
#define type(T) (&T##__type)
////////////////////////////////
//~ rjf: Type Info Table Initializer Helpers
#define member_lit_comp(S, ti, m, ...) {str8_lit_comp(#m), {0}, (ti), OffsetOf(S, m), __VA_ARGS__}
#define struct_members(S) read_only global Member S##__members[] =
#define struct_type(S, ...) read_only global Type S##__type = {TypeKind_Struct, 0, sizeof(S), &type_nil, str8_lit_comp(#S), {0}, ArrayCount(S##__members), S##__members, __VA_ARGS__}
#define named_struct_type(name, S, ...) read_only global Type name##__type = {TypeKind_Struct, 0, sizeof(S), &type_nil, str8_lit_comp(#name), {0}, ArrayCount(name##__members), name##__members, __VA_ARGS__}
#define ptr_type(name, ti, ...) read_only global Type name = {TypeKind_Ptr, 0, sizeof(void *), (ti), __VA_ARGS__}
////////////////////////////////
//~ rjf: Globals
read_only global Type type_nil = {TypeKind_Null, 0, 0, &type_nil};
read_only global Member member_nil = {{0}, {0}, &type_nil};
////////////////////////////////
//~ rjf: Built-In Types
//- rjf: leaves
read_only global Type void__type = {TypeKind_Void, 0, 0, &type_nil, str8_lit_comp("void")};
read_only global Type U8__type = {TypeKind_U8, 0, sizeof(U8), &type_nil, str8_lit_comp("U8")};
read_only global Type U16__type = {TypeKind_U16, 0, sizeof(U16), &type_nil, str8_lit_comp("U16")};
read_only global Type U32__type = {TypeKind_U32, 0, sizeof(U32), &type_nil, str8_lit_comp("U32")};
read_only global Type U64__type = {TypeKind_U64, 0, sizeof(U64), &type_nil, str8_lit_comp("U64")};
read_only global Type S8__type = {TypeKind_S8, 0, sizeof(S8), &type_nil, str8_lit_comp("S8")};
read_only global Type S16__type = {TypeKind_S16, 0, sizeof(S16), &type_nil, str8_lit_comp("S16")};
read_only global Type S32__type = {TypeKind_S32, 0, sizeof(S32), &type_nil, str8_lit_comp("S32")};
read_only global Type S64__type = {TypeKind_S64, 0, sizeof(S64), &type_nil, str8_lit_comp("S64")};
read_only global Type B8__type = {TypeKind_B8, 0, sizeof(B8), &type_nil, str8_lit_comp("B8")};
read_only global Type B16__type = {TypeKind_B16, 0, sizeof(B16), &type_nil, str8_lit_comp("B16")};
read_only global Type B32__type = {TypeKind_B32, 0, sizeof(B32), &type_nil, str8_lit_comp("B32")};
read_only global Type B64__type = {TypeKind_B64, 0, sizeof(B64), &type_nil, str8_lit_comp("B64")};
read_only global Type F32__type = {TypeKind_F32, 0, sizeof(F32), &type_nil, str8_lit_comp("F32")};
read_only global Type F64__type = {TypeKind_F64, 0, sizeof(F64), &type_nil, str8_lit_comp("F64")};
read_only global Type *type_kind_type_table[] =
{
&type_nil,
type(void),
type(U8),
type(U16),
type(U32),
type(U64),
type(S8),
type(S16),
type(S32),
type(S64),
type(B8),
type(B16),
type(B32),
type(B64),
type(F32),
type(F64),
&type_nil,
&type_nil,
&type_nil,
&type_nil,
&type_nil,
};
//- rjf: Rng1U64
struct_members(Rng1U64)
{
member_lit_comp(Rng1U64, type(U64), min),
member_lit_comp(Rng1U64, type(U64), max),
};
struct_type(Rng1U64);
//- rjf: String8
ptr_type(String8__str_ptr_type, type(U8), str8_lit_comp("size"));
struct_members(String8)
{
member_lit_comp(String8, &String8__str_ptr_type, str),
member_lit_comp(String8, type(U64), size),
};
struct_type(String8);
//- rjf: String8Node
extern Type String8Node__type;
Type String8Node__ptr_type = {TypeKind_Ptr, 0, sizeof(void *), &String8Node__type};
Member String8Node__members[] =
{
{str8_lit_comp("next"), {0}, &String8Node__ptr_type, OffsetOf(String8Node, next)},
{str8_lit_comp("string"), {0}, type(String8), OffsetOf(String8Node, string)},
};
Type String8Node__type =
{
TypeKind_Struct,
0,
sizeof(String8Node),
&type_nil,
str8_lit_comp("String8Node"),
{0},
ArrayCount(String8Node__members),
String8Node__members,
};
//- rjf: String8List
Member String8List__members[] =
{
{str8_lit_comp("first"), {0}, &String8Node__ptr_type, OffsetOf(String8List, first)},
{str8_lit_comp("last"), {0}, &String8Node__ptr_type, OffsetOf(String8List, last), MemberFlag_DoNotSerialize},
{str8_lit_comp("node_count"), {0}, type(U64), OffsetOf(String8List, node_count)},
{str8_lit_comp("total_size"), {0}, type(U64), OffsetOf(String8List, total_size)},
};
Type String8List__type =
{
TypeKind_Struct,
0,
sizeof(String8List),
&type_nil,
str8_lit_comp("String8List"),
{0},
ArrayCount(String8List__members),
String8List__members,
};
////////////////////////////////
//~ rjf: Type Info Lookups
internal Member *member_from_name(Type *type, String8 name);
#define EachMember(T, it) (Member *it = (type(T))->members; it != 0 && it < (type(T))->members + (type(T))->count; it += 1)
////////////////////////////////
//~ rjf: Type Info * Instance Operations
internal void typed_data_rebase_ptrs(Type *type, String8 data, void *base_ptr);
internal String8 serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params);
internal String8 deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params);
internal String8 deep_copy_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params);
#define struct_rebase_ptrs(T, ptr, base) typed_data_rebase_ptrs(type(T), str8_struct(ptr), (base))
#define serialized_from_struct(arena, T, ptr, ...) serialized_from_typed_data((arena), type(T), str8_struct(ptr), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__})
#define struct_from_serialized(arena, T, string, ...) (T *)deserialized_from_typed_data((arena), type(T), (string), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__}).str
#define deep_copy_from_struct(arena, T, ptr, ...) (T *)deep_copy_from_typed_data((arena), type(T), str8_struct(ptr), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__}).str
#endif // BASE_META_H
+36 -14
View File
@@ -43,26 +43,48 @@
# define ProfLockTake(...) tmAcquiredLock(0, 0, __VA_ARGS__) # define ProfLockTake(...) tmAcquiredLock(0, 0, __VA_ARGS__)
# define ProfLockDrop(...) tmReleasedLock(0, __VA_ARGS__) # define ProfLockDrop(...) tmReleasedLock(0, __VA_ARGS__)
# define ProfColor(color) tmZoneColorSticky(color) # define ProfColor(color) tmZoneColorSticky(color)
# define ProfBeginV(...) \
if (TM_API_PTR) { \
static tm_uint64 file_id = 0; TM_API_PTR->_tmStaticString(&file_id, __FILE__); \
Temp scratch = scratch_begin(0,0); \
String8 string = push_str8f(scratch.arena, __VA_ARGS__); \
tm_uint64 hash = TM_API_PTR->_tmHash((char*)string.str, string.size); \
hash = TM_API_PTR->_tmSendDynamicString(hash, (char*)string.str); \
TM_API_PTR->_tmEnterZoneFast_Core(0, 0, file_id, __LINE__, hash); \
scratch_end(scratch); \
}
# define ProfNoteV(...) \
if (TM_API_PTR) { \
static tm_uint64 file_id = 0; TM_API_PTR->_tmStaticString(&file_id, __FILE__); \
Temp scratch = scratch_begin(0,0); \
String8 string = push_str8f(scratch.arena, __VA_ARGS__); \
tm_uint64 hash = TM_API_PTR->_tmHash((char*)string.str, string.size); \
hash = TM_API_PTR->_tmSendDynamicString(hash, (char*)string.str); \
TM_API_PTR->_tmMessageFast_Core(0, TMMF_ICON_NOTE, file_id, __LINE__, hash); \
scratch_end(scratch); \
}
#endif #endif
//////////////////////////////// ////////////////////////////////
//~ rjf: Zeroify Undefined Defines //~ rjf: Zeroify Undefined Defines
#if !defined(ProfBegin) #if !defined(ProfBegin)
# define ProfBegin(...) (0) # define ProfBegin(...) (0)
# define ProfBeginDynamic(...) (0) # define ProfBeginDynamic(...) (0)
# define ProfEnd(...) (0) # define ProfEnd(...) (0)
# define ProfTick(...) (0) # define ProfTick(...) (0)
# define ProfIsCapturing(...) (0) # define ProfIsCapturing(...) (0)
# define ProfBeginCapture(...) (0) # define ProfBeginCapture(...) (0)
# define ProfEndCapture(...) (0) # define ProfEndCapture(...) (0)
# define ProfThreadName(...) (0) # define ProfThreadName(...) (0)
# define ProfMsg(...) (0) # define ProfMsg(...) (0)
# define ProfBeginLockWait(...) (0) # define ProfBeginLockWait(...) (0)
# define ProfEndLockWait(...) (0) # define ProfEndLockWait(...) (0)
# define ProfLockTake(...) (0) # define ProfLockTake(...) (0)
# define ProfLockDrop(...) (0) # define ProfLockDrop(...) (0)
# define ProfColor(...) (0) # define ProfColor(...) (0)
# define ProfBeginV(...) (0)
# define ProfNoteV(...) (0)
#endif #endif
//////////////////////////////// ////////////////////////////////
+402 -49
View File
@@ -215,12 +215,42 @@ str32_cstring(U32 *c){
internal String8 internal String8
str8_cstring_capped(void *cstr, void *cap) str8_cstring_capped(void *cstr, void *cap)
{ {
char *ptr = (char*)cstr; char *ptr = (char *)cstr;
char *opl = (char*)cap; char *opl = (char *)cap;
for (;ptr < opl && *ptr != 0; ptr += 1); for (;ptr < opl && *ptr != 0; ptr += 1);
U64 size = (U64)(ptr - (char *)cstr); U64 size = (U64)(ptr - (char *)cstr);
String8 result = {(U8*)cstr, size}; String8 result = str8((U8*)cstr, size);
return(result); return result;
}
internal String16
str16_cstring_capped(void *cstr, void *cap)
{
U16 *ptr = (U16 *)cstr;
U16 *opl = (U16 *)cap;
for (;ptr < opl && *ptr != 0; ptr += 1);
U64 size = (U64)(ptr - (U16 *)cstr);
String16 result = str16(cstr, size);
return result;
}
internal String8
str8_cstring_capped_reverse(void *raw_start, void *raw_cap)
{
U8 *start = raw_start;
U8 *ptr = raw_cap;
for(; ptr > start; )
{
ptr -= 1;
if (*ptr == '\0')
{
break;
}
}
U64 size = (U64)(ptr - start);
String8 result = str8(start, size);
return result;
} }
//////////////////////////////// ////////////////////////////////
@@ -263,31 +293,41 @@ backslashed_from_str8(Arena *arena, String8 string)
//~ rjf: String Matching //~ rjf: String Matching
internal B32 internal B32
str8_match(String8 a, String8 b, StringMatchFlags flags){ str8_match(String8 a, String8 b, StringMatchFlags flags)
{
B32 result = 0; B32 result = 0;
if (a.size == b.size || (flags & StringMatchFlag_RightSideSloppy)){ if(a.size == b.size && flags == 0)
B32 case_insensitive = (flags & StringMatchFlag_CaseInsensitive); {
result = MemoryMatch(a.str, b.str, b.size);
}
else if(a.size == b.size || (flags & StringMatchFlag_RightSideSloppy))
{
B32 case_insensitive = (flags & StringMatchFlag_CaseInsensitive);
B32 slash_insensitive = (flags & StringMatchFlag_SlashInsensitive); B32 slash_insensitive = (flags & StringMatchFlag_SlashInsensitive);
U64 size = Min(a.size, b.size); U64 size = Min(a.size, b.size);
result = 1; result = 1;
for (U64 i = 0; i < size; i += 1){ for(U64 i = 0; i < size; i += 1)
{
U8 at = a.str[i]; U8 at = a.str[i];
U8 bt = b.str[i]; U8 bt = b.str[i];
if (case_insensitive){ if(case_insensitive)
{
at = char_to_upper(at); at = char_to_upper(at);
bt = char_to_upper(bt); bt = char_to_upper(bt);
} }
if (slash_insensitive){ if(slash_insensitive)
{
at = char_to_correct_slash(at); at = char_to_correct_slash(at);
bt = char_to_correct_slash(bt); bt = char_to_correct_slash(bt);
} }
if (at != bt){ if(at != bt)
{
result = 0; result = 0;
break; break;
} }
} }
} }
return(result); return result;
} }
internal U64 internal U64
@@ -322,6 +362,22 @@ str8_find_needle(String8 string, U64 start_pos, String8 needle, StringMatchFlags
return(result); return(result);
} }
internal U64
str8_find_needle_reverse(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags)
{
U64 result = 0;
for(S64 i = string.size - start_pos - needle.size; i >= 0; --i)
{
String8 haystack = str8_substr(string, rng_1u64(i, i + needle.size));
if(str8_match(haystack, needle, flags))
{
result = (U64)i + needle.size;
break;
}
}
return result;
}
internal B32 internal B32
str8_ends_with(String8 string, String8 end, StringMatchFlags flags){ str8_ends_with(String8 string, String8 end, StringMatchFlags flags){
String8 postfix = str8_postfix(string, end.size); String8 postfix = str8_postfix(string, end.size);
@@ -544,21 +600,121 @@ try_s64_from_str8_c_rules(String8 string, S64 *x){
//- rjf: integer -> string //- rjf: integer -> string
internal String8 internal String8
str8_from_memory_size(Arena *arena, U64 z){ str8_from_memory_size(Arena *arena, U64 size)
String8 result = {0}; {
if (z < KB(1)){ String8 result;
result = push_str8f(arena, "%llu b", z);
if(size < KB(1))
{
result = push_str8f(arena, "%llu Bytes", size);
} }
else if (z < MB(1)){ else if(size < MB(1))
result = push_str8f(arena, "%llu.%02llu Kb", z/KB(1), ((100*z)/KB(1))%100); {
result = push_str8f(arena, "%llu.%02llu KiB", size / KB(1), ((size * 100) / KB(1)) % 100);
} }
else if (z < GB(1)){ else if(size < GB(1))
result = push_str8f(arena, "%llu.%02llu Mb", z/MB(1), ((100*z)/MB(1))%100); {
result = push_str8f(arena, "%llu.%02llu MiB", size / MB(1), ((size * 100) / MB(1)) % 100);
} }
else{ else if(size < TB(1))
result = push_str8f(arena, "%llu.%02llu Gb", z/GB(1), ((100*z)/GB(1))%100); {
result = push_str8f(arena, "%llu.%02llu GiB", size / GB(1), ((size * 100) / GB(1)) % 100);
} }
return(result); else
{
result = push_str8f(arena, "%llu.%02llu TiB", size / TB(1), ((size * 100) / TB(1)) % 100);
}
return result;
}
internal String8
str8_from_count(Arena *arena, U64 count)
{
String8 result;
if(count < 1 * 1000)
{
result = push_str8f(arena, "%llu", count);
}
else if(count < 1000000)
{
U64 frac = ((count * 100) / 1000) % 100;
if(frac > 0)
{
result = push_str8f(arena, "%llu.%02lluK", count / 1000, frac);
}
else
{
result = push_str8f(arena, "%lluK", count / 1000);
}
}
else if(count < 1000000000)
{
U64 frac = ((count * 100) / 1000000) % 100;
if(frac > 0)
{
result = push_str8f(arena, "%llu.%02lluM", count / 1000000, frac);
}
else
{
result = push_str8f(arena, "%lluM", count / 1000000);
}
}
else
{
U64 frac = ((count * 100) * 1000000000) % 100;
if(frac > 0)
{
result = push_str8f(arena, "%llu.%02lluB", count / 1000000000, frac);
}
else
{
result = push_str8f(arena, "%lluB", count / 1000000000, frac);
}
}
return result;
}
internal String8
str8_from_bits_u32(Arena *arena, U32 x)
{
U8 c0 = 'a' + ((x >> 28) & 0xf);
U8 c1 = 'a' + ((x >> 24) & 0xf);
U8 c2 = 'a' + ((x >> 20) & 0xf);
U8 c3 = 'a' + ((x >> 16) & 0xf);
U8 c4 = 'a' + ((x >> 12) & 0xf);
U8 c5 = 'a' + ((x >> 8) & 0xf);
U8 c6 = 'a' + ((x >> 4) & 0xf);
U8 c7 = 'a' + ((x >> 0) & 0xf);
String8 result = push_str8f(arena, "%c%c%c%c%c%c%c%c", c0, c1, c2, c3, c4, c5, c6, c7);
return result;
}
internal String8
str8_from_bits_u64(Arena *arena, U64 x)
{
U8 c0 = 'a' + ((x >> 60) & 0xf);
U8 c1 = 'a' + ((x >> 56) & 0xf);
U8 c2 = 'a' + ((x >> 52) & 0xf);
U8 c3 = 'a' + ((x >> 48) & 0xf);
U8 c4 = 'a' + ((x >> 44) & 0xf);
U8 c5 = 'a' + ((x >> 40) & 0xf);
U8 c6 = 'a' + ((x >> 36) & 0xf);
U8 c7 = 'a' + ((x >> 32) & 0xf);
U8 c8 = 'a' + ((x >> 28) & 0xf);
U8 c9 = 'a' + ((x >> 24) & 0xf);
U8 ca = 'a' + ((x >> 20) & 0xf);
U8 cb = 'a' + ((x >> 16) & 0xf);
U8 cc = 'a' + ((x >> 12) & 0xf);
U8 cd = 'a' + ((x >> 8) & 0xf);
U8 ce = 'a' + ((x >> 4) & 0xf);
U8 cf = 'a' + ((x >> 0) & 0xf);
String8 result = push_str8f(arena,
"%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf);
return result;
} }
internal String8 internal String8
@@ -685,27 +841,28 @@ f64_from_str8(String8 string)
{ {
// rjf: find starting pos of numeric string, as well as sign // rjf: find starting pos of numeric string, as well as sign
F64 sign = +1.0; F64 sign = +1.0;
//U64 first_numeric = 0;
if(string.str[0] == '-') if(string.str[0] == '-')
{ {
//first_numeric = 1;
sign = -1.0; sign = -1.0;
} }
else if(string.str[0] == '+') else if(string.str[0] == '+')
{ {
//first_numeric = 1;
sign = 1.0; sign = 1.0;
} }
// rjf: gather numerics // rjf: gather numerics
U64 num_valid_chars = 0; U64 num_valid_chars = 0;
char buffer[64]; char buffer[64];
B32 exp = 0;
for(U64 idx = 0; idx < string.size && num_valid_chars < sizeof(buffer)-1; idx += 1) for(U64 idx = 0; idx < string.size && num_valid_chars < sizeof(buffer)-1; idx += 1)
{ {
if(char_is_digit(string.str[idx], 10) || string.str[idx] == '.') if(char_is_digit(string.str[idx], 10) || string.str[idx] == '.' || string.str[idx] == 'e' ||
(exp && (string.str[idx] == '+' || string.str[idx] == '-')))
{ {
buffer[num_valid_chars] = string.str[idx]; buffer[num_valid_chars] = string.str[idx];
num_valid_chars += 1; num_valid_chars += 1;
exp = 0;
exp = (string.str[idx] == 'e');
} }
} }
@@ -1138,7 +1295,9 @@ str8_path_list_resolve_dots_in_place(String8List *path, PathStyle style){
internal String8 internal String8
str8_path_list_join_by_style(Arena *arena, String8List *path, PathStyle style){ str8_path_list_join_by_style(Arena *arena, String8List *path, PathStyle style){
StringJoin params = {0}; StringJoin params = {0};
switch (style){ switch(style)
{
case PathStyle_Null:{}break;
case PathStyle_Relative: case PathStyle_Relative:
case PathStyle_WindowsAbsolute: case PathStyle_WindowsAbsolute:
{ {
@@ -1151,9 +1310,8 @@ str8_path_list_join_by_style(Arena *arena, String8List *path, PathStyle style){
params.sep = str8_lit("/"); params.sep = str8_lit("/");
}break; }break;
} }
String8 result = str8_list_join(arena, path, &params); String8 result = str8_list_join(arena, path, &params);
return(result); return result;
} }
internal String8TxtPtPair internal String8TxtPtPair
@@ -1281,7 +1439,7 @@ utf16_decode(U16 *str, U64 max){
result.codepoint = str[0]; result.codepoint = str[0];
result.inc = 1; result.inc = 1;
if (max > 1 && 0xD800 <= str[0] && str[0] < 0xDC00 && 0xDC00 <= str[1] && str[1] < 0xE000){ if (max > 1 && 0xD800 <= str[0] && str[0] < 0xDC00 && 0xDC00 <= str[1] && str[1] < 0xE000){
result.codepoint = ((str[0] - 0xD800) << 10) | (str[1] - 0xDC00) + 0x10000; result.codepoint = ((str[0] - 0xD800) << 10) | ((str[1] - 0xDC00) + 0x10000);
result.inc = 2; result.inc = 2;
} }
return(result); return(result);
@@ -1358,7 +1516,7 @@ str8_from_16(Arena *arena, String16 in){
size += utf8_encode(str + size, consume.codepoint); size += utf8_encode(str + size, consume.codepoint);
} }
str[size] = 0; str[size] = 0;
arena_put_back(arena, (cap - size)); arena_pop(arena, (cap - size));
return(str8(str, size)); return(str8(str, size));
} }
@@ -1375,7 +1533,7 @@ str16_from_8(Arena *arena, String8 in){
size += utf16_encode(str + size, consume.codepoint); size += utf16_encode(str + size, consume.codepoint);
} }
str[size] = 0; str[size] = 0;
arena_put_back(arena, (cap - size)*2); arena_pop(arena, (cap - size)*2);
return(str16(str, size)); return(str16(str, size));
} }
@@ -1390,7 +1548,7 @@ str8_from_32(Arena *arena, String32 in){
size += utf8_encode(str + size, *ptr); size += utf8_encode(str + size, *ptr);
} }
str[size] = 0; str[size] = 0;
arena_put_back(arena, (cap - size)); arena_pop(arena, (cap - size));
return(str8(str, size)); return(str8(str, size));
} }
@@ -1408,10 +1566,39 @@ str32_from_8(Arena *arena, String8 in){
size += 1; size += 1;
} }
str[size] = 0; str[size] = 0;
arena_put_back(arena, (cap - size)*4); arena_pop(arena, (cap - size)*4);
return(str32(str, size)); return(str32(str, size));
} }
////////////////////////////////
//~ String -> Enum Conversions
read_only global struct
{
String8 string;
OperatingSystem os;
} g_os_enum_map[] =
{
{ str8_lit_comp(""), OperatingSystem_Null },
{ str8_lit_comp("Windows"), OperatingSystem_Windows, },
{ str8_lit_comp("Linux"), OperatingSystem_Linux, },
{ str8_lit_comp("Mac"), OperatingSystem_Mac, },
};
StaticAssert(ArrayCount(g_os_enum_map) == OperatingSystem_COUNT, g_os_enum_map_count_check);
internal OperatingSystem
operating_system_from_string(String8 string)
{
for(U64 i = 0; i < ArrayCount(g_os_enum_map); ++i)
{
if(str8_match(g_os_enum_map[i].string, string, StringMatchFlag_CaseInsensitive))
{
return g_os_enum_map[i].os;
}
}
return OperatingSystem_Null;
}
//////////////////////////////// ////////////////////////////////
//~ rjf: Basic Types & Space Enum -> String Conversions //~ rjf: Basic Types & Space Enum -> String Conversions
@@ -1444,22 +1631,18 @@ string_from_side(Side side){
} }
internal String8 internal String8
string_from_operating_system(OperatingSystem os){ string_from_operating_system(OperatingSystem os)
local_persist String8 strings[] = { {
str8_lit_comp("Null"), String8 result = g_os_enum_map[OperatingSystem_Null].string;
str8_lit_comp("Windows"), if(os < ArrayCount(g_os_enum_map))
str8_lit_comp("Linux"), {
str8_lit_comp("Mac"), result = g_os_enum_map[os].string;
};
String8 result = str8_lit("error");
if (os < OperatingSystem_COUNT){
result = strings[os];
} }
return(result); return result;
} }
internal String8 internal String8
string_from_architecture(Architecture arch){ string_from_arch(Arch arch){
local_persist String8 strings[] = { local_persist String8 strings[] = {
str8_lit_comp("Null"), str8_lit_comp("Null"),
str8_lit_comp("x64"), str8_lit_comp("x64"),
@@ -1468,7 +1651,7 @@ string_from_architecture(Architecture arch){
str8_lit_comp("arm32"), str8_lit_comp("arm32"),
}; };
String8 result = str8_lit("error"); String8 result = str8_lit("error");
if (arch < Architecture_COUNT){ if (arch < Arch_COUNT){
result = strings[arch]; result = strings[arch];
} }
return(result); return(result);
@@ -1565,6 +1748,78 @@ string_from_elapsed_time(Arena *arena, DateTime dt){
return(result); return(result);
} }
////////////////////////////////
//~ Globally UNique Ids
internal String8
string_from_guid(Arena *arena, Guid guid)
{
String8 result = push_str8f(arena, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
guid.data1,
guid.data2,
guid.data3,
guid.data4[0],
guid.data4[1],
guid.data4[2],
guid.data4[3],
guid.data4[4],
guid.data4[5],
guid.data4[6],
guid.data4[7]);
return result;
}
internal B32
try_guid_from_string(String8 string, Guid *guid_out)
{
Temp scratch = scratch_begin(0,0);
B32 is_parsed = 0;
String8List list = str8_split_by_string_chars(scratch.arena, string, str8_lit("-"), StringSplitFlag_KeepEmpties);
if(list.node_count == 5)
{
String8 data1_str = list.first->string;
String8 data2_str = list.first->next->string;
String8 data3_str = list.first->next->next->string;
String8 data4_hi_str = list.first->next->next->next->string;
String8 data4_lo_str = list.first->next->next->next->next->string;
if(str8_is_integer(data1_str, 16) &&
str8_is_integer(data2_str, 16) &&
str8_is_integer(data3_str, 16) &&
str8_is_integer(data4_hi_str, 16) &&
str8_is_integer(data4_lo_str, 16))
{
U64 data1 = u64_from_str8(data1_str, 16);
U64 data2 = u64_from_str8(data2_str, 16);
U64 data3 = u64_from_str8(data3_str, 16);
U64 data4_hi = u64_from_str8(data4_hi_str, 16);
U64 data4_lo = u64_from_str8(data4_lo_str, 16);
if(data1 <= max_U32 &&
data2 <= max_U16 &&
data3 <= max_U16 &&
data4_hi <= max_U16 &&
data4_lo <= 0xffffffffffff)
{
guid_out->data1 = (U32)data1;
guid_out->data2 = (U16)data2;
guid_out->data3 = (U16)data3;
U64 data4 = (data4_hi << 48) | data4_lo;
MemoryCopy(&guid_out->data4[0], &data4, sizeof(data4));
is_parsed = 1;
}
}
}
scratch_end(scratch);
return is_parsed;
}
internal Guid
guid_from_string(String8 string)
{
Guid guid = {0};
try_guid_from_string(string, &guid);
return guid;
}
//////////////////////////////// ////////////////////////////////
//~ rjf: Basic Text Indentation //~ rjf: Basic Text Indentation
@@ -1593,6 +1848,10 @@ indented_from_string(Arena *arena, String8 string)
{ {
str8_list_pushf(scratch.arena, &indented_strings, "%.*s%S\n", (int)depth*2, indentation_bytes, line); str8_list_pushf(scratch.arena, &indented_strings, "%.*s%S\n", (int)depth*2, indentation_bytes, line);
} }
if(line.size == 0 && indented_strings.node_count != 0 && off < string.size)
{
str8_list_pushf(scratch.arena, &indented_strings, "\n");
}
line_begin_off = off+1; line_begin_off = off+1;
depth = next_depth; depth = next_depth;
}break; }break;
@@ -1603,6 +1862,100 @@ indented_from_string(Arena *arena, String8 string)
return result; return result;
} }
////////////////////////////////
//~ rjf: Text Escaping
internal String8
escaped_from_raw_str8(Arena *arena, String8 string)
{
Temp scratch = scratch_begin(&arena, 1);
String8List parts = {0};
U64 start_split_idx = 0;
for(U64 idx = 0; idx <= string.size; idx += 1)
{
U8 byte = (idx < string.size) ? string.str[idx] : 0;
B32 split = 1;
String8 separator_replace = {0};
switch(byte)
{
default:{split = 0;}break;
case 0: {}break;
case '\a': {separator_replace = str8_lit("\\a");}break;
case '\b': {separator_replace = str8_lit("\\b");}break;
case '\f': {separator_replace = str8_lit("\\f");}break;
case '\n': {separator_replace = str8_lit("\\n");}break;
case '\r': {separator_replace = str8_lit("\\r");}break;
case '\t': {separator_replace = str8_lit("\\t");}break;
case '\v': {separator_replace = str8_lit("\\v");}break;
case '\\': {separator_replace = str8_lit("\\\\");}break;
case '"': {separator_replace = str8_lit("\\\"");}break;
case '?': {separator_replace = str8_lit("\\?");}break;
}
if(split)
{
String8 substr = str8_substr(string, r1u64(start_split_idx, idx));
start_split_idx = idx+1;
str8_list_push(scratch.arena, &parts, substr);
if(separator_replace.size != 0)
{
str8_list_push(scratch.arena, &parts, separator_replace);
}
}
}
StringJoin join = {0};
String8 result = str8_list_join(arena, &parts, &join);
scratch_end(scratch);
return result;
}
internal String8
raw_from_escaped_str8(Arena *arena, String8 string)
{
Temp scratch = scratch_begin(&arena, 1);
String8List strs = {0};
U64 start = 0;
for(U64 idx = 0; idx <= string.size; idx += 1)
{
if(idx == string.size || string.str[idx] == '\\' || string.str[idx] == '\r')
{
String8 str = str8_substr(string, r1u64(start, idx));
if(str.size != 0)
{
str8_list_push(scratch.arena, &strs, str);
}
start = idx+1;
}
if(idx < string.size && string.str[idx] == '\\')
{
U8 next_char = string.str[idx+1];
U8 replace_byte = 0;
switch(next_char)
{
default:{}break;
case 'a': replace_byte = 0x07; break;
case 'b': replace_byte = 0x08; break;
case 'e': replace_byte = 0x1b; break;
case 'f': replace_byte = 0x0c; break;
case 'n': replace_byte = 0x0a; break;
case 'r': replace_byte = 0x0d; break;
case 't': replace_byte = 0x09; break;
case 'v': replace_byte = 0x0b; break;
case '\\':replace_byte = '\\'; break;
case '\'':replace_byte = '\''; break;
case '"': replace_byte = '"'; break;
case '?': replace_byte = '?'; break;
}
String8 replace_string = push_str8_copy(scratch.arena, str8(&replace_byte, 1));
str8_list_push(scratch.arena, &strs, replace_string);
idx += 1;
start += 1;
}
}
String8 result = str8_list_join(arena, &strs, 0);
scratch_end(scratch);
return result;
}
//////////////////////////////// ////////////////////////////////
//~ rjf: Text Wrapping //~ rjf: Text Wrapping
+27 -2
View File
@@ -86,6 +86,7 @@ enum
typedef enum PathStyle typedef enum PathStyle
{ {
PathStyle_Null,
PathStyle_Relative, PathStyle_Relative,
PathStyle_WindowsAbsolute, PathStyle_WindowsAbsolute,
PathStyle_UnixAbsolute, PathStyle_UnixAbsolute,
@@ -192,6 +193,8 @@ internal String8 str8_cstring(char *c);
internal String16 str16_cstring(U16 *c); internal String16 str16_cstring(U16 *c);
internal String32 str32_cstring(U32 *c); internal String32 str32_cstring(U32 *c);
internal String8 str8_cstring_capped(void *cstr, void *cap); internal String8 str8_cstring_capped(void *cstr, void *cap);
internal String16 str16_cstring_capped(void *cstr, void *cap);
internal String8 str8_cstring_capped_reverse(void *raw_start, void *raw_cap);
//////////////////////////////// ////////////////////////////////
//~ rjf: String Stylization //~ rjf: String Stylization
@@ -205,6 +208,7 @@ internal String8 backslashed_from_str8(Arena *arena, String8 string);
internal B32 str8_match(String8 a, String8 b, StringMatchFlags flags); internal B32 str8_match(String8 a, String8 b, StringMatchFlags flags);
internal U64 str8_find_needle(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags); internal U64 str8_find_needle(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags);
internal U64 str8_find_needle_reverse(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags);
internal B32 str8_ends_with(String8 string, String8 end, StringMatchFlags flags); internal B32 str8_ends_with(String8 string, String8 end, StringMatchFlags flags);
//////////////////////////////// ////////////////////////////////
@@ -237,7 +241,10 @@ internal B32 try_u64_from_str8_c_rules(String8 string, U64 *x);
internal B32 try_s64_from_str8_c_rules(String8 string, S64 *x); internal B32 try_s64_from_str8_c_rules(String8 string, S64 *x);
//- rjf: integer -> string //- rjf: integer -> string
internal String8 str8_from_memory_size(Arena *arena, U64 z); internal String8 str8_from_memory_size(Arena *arena, U64 size);
internal String8 str8_from_count(Arena *arena, U64 count);
internal String8 str8_from_bits_u32(Arena *arena, U32 x);
internal String8 str8_from_bits_u64(Arena *arena, U64 x);
internal String8 str8_from_u64(Arena *arena, U64 u64, U32 radix, U8 min_digits, U8 digit_group_separator); internal String8 str8_from_u64(Arena *arena, U64 u64, U32 radix, U8 min_digits, U8 digit_group_separator);
internal String8 str8_from_s64(Arena *arena, S64 s64, U32 radix, U8 min_digits, U8 digit_group_separator); internal String8 str8_from_s64(Arena *arena, S64 s64, U32 radix, U8 min_digits, U8 digit_group_separator);
@@ -309,13 +316,18 @@ internal String16 str16_from_8(Arena *arena, String8 in);
internal String8 str8_from_32(Arena *arena, String32 in); internal String8 str8_from_32(Arena *arena, String32 in);
internal String32 str32_from_8(Arena *arena, String8 in); internal String32 str32_from_8(Arena *arena, String8 in);
////////////////////////////////
//~ String -> Enum Conversions
internal OperatingSystem operating_system_from_string(String8 string);
//////////////////////////////// ////////////////////////////////
//~ rjf: Basic Types & Space Enum -> String Conversions //~ rjf: Basic Types & Space Enum -> String Conversions
internal String8 string_from_dimension(Dimension dimension); internal String8 string_from_dimension(Dimension dimension);
internal String8 string_from_side(Side side); internal String8 string_from_side(Side side);
internal String8 string_from_operating_system(OperatingSystem os); internal String8 string_from_operating_system(OperatingSystem os);
internal String8 string_from_architecture(Architecture arch); internal String8 string_from_arch(Arch arch);
//////////////////////////////// ////////////////////////////////
//~ rjf: Time Types -> String //~ rjf: Time Types -> String
@@ -326,11 +338,24 @@ internal String8 push_date_time_string(Arena *arena, DateTime *date_time);
internal String8 push_file_name_date_time_string(Arena *arena, DateTime *date_time); internal String8 push_file_name_date_time_string(Arena *arena, DateTime *date_time);
internal String8 string_from_elapsed_time(Arena *arena, DateTime dt); internal String8 string_from_elapsed_time(Arena *arena, DateTime dt);
////////////////////////////////
//~ Globally Unique Ids
internal String8 string_from_guid(Arena *arena, Guid guid);
internal B32 try_guid_from_string(String8 string, Guid *guid_out);
internal Guid guid_from_string(String8 string);
//////////////////////////////// ////////////////////////////////
//~ rjf: Basic Text Indentation //~ rjf: Basic Text Indentation
internal String8 indented_from_string(Arena *arena, String8 string); internal String8 indented_from_string(Arena *arena, String8 string);
////////////////////////////////
//~ rjf: Text Escaping
internal String8 escaped_from_raw_str8(Arena *arena, String8 string);
internal String8 raw_from_escaped_str8(Arena *arena, String8 string);
//////////////////////////////// ////////////////////////////////
//~ rjf: Text Wrapping //~ rjf: Text Wrapping
+2 -2
View File
@@ -26,7 +26,7 @@ internal void tctx_init_and_equip(TCTX *tctx);
internal void tctx_release(void); internal void tctx_release(void);
internal TCTX* tctx_get_equipped(void); internal TCTX* tctx_get_equipped(void);
internal Arena* tctx_get_scratch(Arena **conflicts, U64 count); internal Arena* tctx_get_scratch(Arena **conflicts, U64 countt);
internal void tctx_set_thread_name(String8 name); internal void tctx_set_thread_name(String8 name);
internal String8 tctx_get_thread_name(void); internal String8 tctx_get_thread_name(void);
@@ -38,4 +38,4 @@ internal void tctx_read_srcloc(char **file_name, U64 *line_number);
#define scratch_begin(conflicts, count) temp_begin(tctx_get_scratch((conflicts), (count))) #define scratch_begin(conflicts, count) temp_begin(tctx_get_scratch((conflicts), (count)))
#define scratch_end(scratch) temp_end(scratch) #define scratch_end(scratch) temp_end(scratch)
#endif //BASE_THREAD_CONTEXT_H #endif // BASE_THREAD_CONTEXT_H
+24 -13
View File
@@ -80,6 +80,13 @@ cv_numeric_from_data_range(U8 *first, U8 *opl)
return result; return result;
} }
internal U64
cv_read_numeric(String8 data, U64 offset, CV_NumericParsed *out)
{
*out = cv_numeric_from_data_range(data.str + offset, data.str + data.size);
return out->encoded_size;
}
internal B32 internal B32
cv_numeric_fits_in_u64(CV_NumericParsed *num) cv_numeric_fits_in_u64(CV_NumericParsed *num)
{ {
@@ -186,7 +193,7 @@ cv_decode_inline_annot_u32(String8 data, U64 offset, U32 *out_value)
} }
// 2 bytes // 2 bytes
else if((header & 0xC0) == 0x80 && cursor+2 <= data.size) else if((header & 0xC0) == 0x80 && cursor+1 <= data.size)
{ {
U8 second_byte; U8 second_byte;
cursor += str8_deserial_read_struct(data, cursor, &second_byte); cursor += str8_deserial_read_struct(data, cursor, &second_byte);
@@ -268,8 +275,7 @@ cv_rec_range_stream_from_data(Arena *arena, String8 sym_data, U64 sym_align)
for(;cursor + sizeof(CV_RecHeader) <= cap;) for(;cursor + sizeof(CV_RecHeader) <= cap;)
{ {
// setup a new chunk // setup a new chunk
arena_push_align(arena, 64); CV_RecRangeChunk *cur_chunk = push_array_aligned(arena, CV_RecRangeChunk, 1, 64);
CV_RecRangeChunk *cur_chunk = push_array_no_zero(arena, CV_RecRangeChunk, 1);
SLLQueuePush(result->first_chunk, result->last_chunk, cur_chunk); SLLQueuePush(result->first_chunk, result->last_chunk, cur_chunk);
U64 partial_count = 0; U64 partial_count = 0;
for(;partial_count < CV_REC_RANGE_CHUNK_SIZE && cursor + sizeof(CV_RecHeader) <= cap; partial_count += 1) for(;partial_count < CV_REC_RANGE_CHUNK_SIZE && cursor + sizeof(CV_RecHeader) <= cap; partial_count += 1)
@@ -296,7 +302,7 @@ internal CV_RecRangeArray
cv_rec_range_array_from_stream(Arena *arena, CV_RecRangeStream *stream) cv_rec_range_array_from_stream(Arena *arena, CV_RecRangeStream *stream)
{ {
U64 total_count = stream->total_count; U64 total_count = stream->total_count;
CV_RecRange *ranges = push_array_no_zero(arena, CV_RecRange, total_count); CV_RecRange *ranges = push_array_no_zero_aligned(arena, CV_RecRange, total_count, 8);
U64 idx = 0; U64 idx = 0;
for(CV_RecRangeChunk *chunk = stream->first_chunk; chunk != 0; chunk = chunk->next) for(CV_RecRangeChunk *chunk = stream->first_chunk; chunk != 0; chunk = chunk->next)
{ {
@@ -412,7 +418,7 @@ cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId itype_first)
//~ CodeView C13 Parser Functions //~ CodeView C13 Parser Functions
internal CV_C13Parsed * internal CV_C13Parsed *
cv_c13_parsed_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_CoffSectionArray *sections) cv_c13_parsed_from_data(Arena *arena, String8 c13_data, String8 strtbl, COFF_SectionHeaderArray sections)
{ {
ProfBeginFunction(); ProfBeginFunction();
@@ -484,19 +490,21 @@ cv_c13_parsed_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_
CV_C13SubSecLinesHeader *hdr = (CV_C13SubSecLinesHeader*)(first + read_off); CV_C13SubSecLinesHeader *hdr = (CV_C13SubSecLinesHeader*)(first + read_off);
read_off += sizeof(*hdr); read_off += sizeof(*hdr);
// extract top level info // rjf: extract section index
U32 sec_idx = hdr->sec; U32 sec_idx = hdr->sec;
B32 has_cols = !!(hdr->flags & CV_C13SubSecLinesFlag_HasColumns);
U64 secrel_off = hdr->sec_off;
U64 secrel_opl = secrel_off + hdr->len;
U64 sec_base_off = sections->sections[sec_idx - 1].voff;
// rjf: bad section index -> skip // rjf: bad section index -> skip
if(sec_idx < 1 || sections->count < sec_idx) if(sec_idx < 1 || sections.count < sec_idx)
{ {
continue; continue;
} }
// extract top level info
B32 has_cols = !!(hdr->flags & CV_C13SubSecLinesFlag_HasColumns);
U64 secrel_off = hdr->sec_off;
U64 secrel_opl = secrel_off + hdr->len;
U64 sec_base_off = sections.v[sec_idx - 1].voff;
// read files // read files
for(;read_off+sizeof(CV_C13File) <= read_off_opl;) for(;read_off+sizeof(CV_C13File) <= read_off_opl;)
{ {
@@ -512,7 +520,8 @@ cv_c13_parsed_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_
{ {
CV_C13Checksum *checksum = (CV_C13Checksum*)(c13_data.str + file_chksms->off + file_off); CV_C13Checksum *checksum = (CV_C13Checksum*)(c13_data.str + file_chksms->off + file_off);
U32 name_off = checksum->name_off; U32 name_off = checksum->name_off;
file_name = pdb_strtbl_string_from_off(strtbl, name_off); file_name = str8_cstring_capped((char*)(strtbl.str + name_off),
(char*)(strtbl.str + strtbl.size));
} }
// array layouts // array layouts
@@ -588,7 +597,8 @@ cv_c13_parsed_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_
{ {
CV_C13Checksum *checksum = (CV_C13Checksum*)(c13_data.str + file_chksms->off + hdr->file_off); CV_C13Checksum *checksum = (CV_C13Checksum*)(c13_data.str + file_chksms->off + hdr->file_off);
U32 name_off = checksum->name_off; U32 name_off = checksum->name_off;
file_name = pdb_strtbl_string_from_off(strtbl, name_off); file_name = str8_cstring_capped((char*)(strtbl.str + name_off),
(char*)(strtbl.str + strtbl.size));
} }
// rjf: parse extra files // rjf: parse extra files
@@ -609,6 +619,7 @@ cv_c13_parsed_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_
SLLQueuePush(node->inlinee_lines_first, node->inlinee_lines_last, n); SLLQueuePush(node->inlinee_lines_first, node->inlinee_lines_last, n);
n->v.inlinee = hdr->inlinee; n->v.inlinee = hdr->inlinee;
n->v.file_name = file_name; n->v.file_name = file_name;
n->v.file_off = hdr->file_off;
n->v.first_source_ln = hdr->first_source_ln; n->v.first_source_ln = hdr->first_source_ln;
n->v.extra_file_count = extra_file_count; n->v.extra_file_count = extra_file_count;
n->v.extra_files = extra_files; n->v.extra_files = extra_files;
+603 -499
View File
File diff suppressed because it is too large Load Diff
+9 -1
View File
@@ -246,7 +246,7 @@ cv_string_from_arch:
{MANTYPREF - 0x1028} {MANTYPREF - 0x1028}
{UNAMESPACE_ST - 0x1029} {UNAMESPACE_ST - 0x1029}
{ST_MAX - 0x1100} {ST_MAX - 0x1100}
{OBJNAME Objname 0x1101} {OBJNAME ObjName 0x1101}
{THUNK32 Thunk32 0x1102} {THUNK32 Thunk32 0x1102}
{BLOCK32 Block32 0x1103} {BLOCK32 Block32 0x1103}
{WITH32 - 0x1104} {WITH32 - 0x1104}
@@ -462,6 +462,7 @@ CV_BasicTypeTable:
@table(name header_type_name val) @table(name header_type_name val)
CV_LeafKindTable: CV_LeafKindTable:
{ {
{NOTYPE - 0x0000}
{MODIFIER_16t - 0x0001} {MODIFIER_16t - 0x0001}
{POINTER_16t - 0x0002} {POINTER_16t - 0x0002}
{ARRAY_16t - 0x0003} {ARRAY_16t - 0x0003}
@@ -586,6 +587,13 @@ CV_LeafKindTable:
{VECTOR - 0x151b} {VECTOR - 0x151b}
{MATRIX - 0x151c} {MATRIX - 0x151c}
{VFTABLE - 0x151d} {VFTABLE - 0x151d}
{FUNC_ID FuncId 0x1601}
{MFUNC_ID MFuncId 0x1602}
{BUILDINFO BuildInfo 0x1603}
{SUBSTR_LIST SubstrList 0x1604}
{STRING_ID StringId 0x1605}
{UDT_SRC_LINE UDTSrcLine 0x1606}
{UDT_MOD_SRC_LINE UDTModSrcLine 0x1607}
{CLASS2 Struct2 0x1608} {CLASS2 Struct2 0x1608}
{STRUCT2 Struct2 0x1609} {STRUCT2 Struct2 0x1609}
} }
+26 -14
View File
@@ -408,11 +408,11 @@ cv_stringize_sym_range(Arena *arena, String8List *out,
case CV_SymKind_OBJNAME: case CV_SymKind_OBJNAME:
{ {
if (sizeof(CV_SymObjname) > cap){ if (sizeof(CV_SymObjName) > cap){
str8_list_push(arena, out, str8_lit(" bad symbol range\n")); str8_list_push(arena, out, str8_lit(" bad symbol range\n"));
} }
else{ else{
CV_SymObjname *objname = (CV_SymObjname*)first; CV_SymObjName *objname = (CV_SymObjName*)first;
// sig // sig
str8_list_pushf(arena, out, " sig=%u\n", objname->sig); str8_list_pushf(arena, out, " sig=%u\n", objname->sig);
@@ -568,22 +568,22 @@ cv_stringize_sym_range(Arena *arena, String8List *out,
CV_SymPub32 *pub32 = (CV_SymPub32*)first; CV_SymPub32 *pub32 = (CV_SymPub32*)first;
// flags // flags
CV_PubFlags flags = pub32->flags; CV_Pub32Flags flags = pub32->flags;
str8_list_push(arena, out, str8_lit(" flags=")); str8_list_push(arena, out, str8_lit(" flags="));
if (flags == 0){ if (flags == 0){
str8_list_push(arena, out, str8_lit("0|")); str8_list_push(arena, out, str8_lit("0|"));
} }
else{ else{
if (flags&CV_PubFlag_Code){ if (flags&CV_Pub32Flag_Code){
str8_list_push(arena, out, str8_lit("Code|")); str8_list_push(arena, out, str8_lit("Code|"));
} }
if (flags&CV_PubFlag_Function){ if (flags&CV_Pub32Flag_Function){
str8_list_push(arena, out, str8_lit("Function|")); str8_list_push(arena, out, str8_lit("Function|"));
} }
if (flags&CV_PubFlag_ManagedCode){ if (flags&CV_Pub32Flag_ManagedCode){
str8_list_push(arena, out, str8_lit("ManagedCode|")); str8_list_push(arena, out, str8_lit("ManagedCode|"));
} }
if (flags&CV_PubFlag_MSIL){ if (flags&CV_Pub32Flag_MSIL){
str8_list_push(arena, out, str8_lit("MSIL|")); str8_list_push(arena, out, str8_lit("MSIL|"));
} }
} }
@@ -2004,7 +2004,7 @@ cv_stringize_leaf_range(Arena *arena, String8List *out,
} }
}break; }break;
case CV_LeafIDKind_FUNC_ID: case CV_LeafKind_FUNC_ID:
{ {
if (sizeof(CV_LeafFuncId) > cap){ if (sizeof(CV_LeafFuncId) > cap){
str8_list_push(arena, out, str8_lit(" bad leaf range\n")); str8_list_push(arena, out, str8_lit(" bad leaf range\n"));
@@ -2020,7 +2020,7 @@ cv_stringize_leaf_range(Arena *arena, String8List *out,
} }
}break; }break;
case CV_LeafIDKind_MFUNC_ID: case CV_LeafKind_MFUNC_ID:
{ {
if (sizeof(CV_LeafMFuncId) > cap){ if (sizeof(CV_LeafMFuncId) > cap){
str8_list_push(arena, out, str8_lit(" bad leaf range\n")); str8_list_push(arena, out, str8_lit(" bad leaf range\n"));
@@ -2036,7 +2036,7 @@ cv_stringize_leaf_range(Arena *arena, String8List *out,
} }
}break; }break;
case CV_LeafIDKind_BUILDINFO: case CV_LeafKind_BUILDINFO:
{ {
if (sizeof(CV_LeafBuildInfo) > cap){ if (sizeof(CV_LeafBuildInfo) > cap){
str8_list_push(arena, out, str8_lit(" bad leaf range\n")); str8_list_push(arena, out, str8_lit(" bad leaf range\n"));
@@ -2057,7 +2057,7 @@ cv_stringize_leaf_range(Arena *arena, String8List *out,
} }
}break; }break;
case CV_LeafIDKind_SUBSTR_LIST: case CV_LeafKind_SUBSTR_LIST:
{ {
if (sizeof(CV_LeafSubstrList) > cap){ if (sizeof(CV_LeafSubstrList) > cap){
str8_list_push(arena, out, str8_lit(" bad leaf range\n")); str8_list_push(arena, out, str8_lit(" bad leaf range\n"));
@@ -2078,7 +2078,7 @@ cv_stringize_leaf_range(Arena *arena, String8List *out,
} }
}break; }break;
case CV_LeafIDKind_STRING_ID: case CV_LeafKind_STRING_ID:
{ {
if (sizeof(CV_LeafStringId) > cap){ if (sizeof(CV_LeafStringId) > cap){
str8_list_push(arena, out, str8_lit(" bad leaf range\n")); str8_list_push(arena, out, str8_lit(" bad leaf range\n"));
@@ -2093,7 +2093,7 @@ cv_stringize_leaf_range(Arena *arena, String8List *out,
} }
}break; }break;
case CV_LeafIDKind_UDT_SRC_LINE: case CV_LeafKind_UDT_SRC_LINE:
{ {
if (sizeof(CV_LeafUDTSrcLine) > cap){ if (sizeof(CV_LeafUDTSrcLine) > cap){
str8_list_push(arena, out, str8_lit(" bad leaf range\n")); str8_list_push(arena, out, str8_lit(" bad leaf range\n"));
@@ -2243,7 +2243,7 @@ cv_stringize_leaf_range(Arena *arena, String8List *out,
//case CV_LeafIDKind_SUBSTR_LIST: //case CV_LeafIDKind_SUBSTR_LIST:
//case CV_LeafIDKind_STRING_ID: //case CV_LeafIDKind_STRING_ID:
//case CV_LeafIDKind_UDT_SRC_LINE: //case CV_LeafIDKind_UDT_SRC_LINE:
case CV_LeafIDKind_UDT_MOD_SRC_LINE: case CV_LeafKind_UDT_MOD_SRC_LINE:
{ {
str8_list_push(arena, out, str8_lit(" no stringizer path\n")); str8_list_push(arena, out, str8_lit(" no stringizer path\n"));
@@ -2328,3 +2328,15 @@ cv_stringize_c13_parsed(Arena *arena, String8List *out, CV_C13Parsed *c13){
str8_list_push(arena, out, str8_lit("\n")); str8_list_push(arena, out, str8_lit("\n"));
} }
} }
internal String8
cv_string_from_inline_range_kind(CV_InlineRangeKind kind)
{
String8 result = str8_zero();
switch (kind) {
case CV_InlineRangeKind_Expr: result = str8_lit("Expr"); break;
case CV_InlineRangeKind_Stmt: result = str8_lit("Stmt"); break;
}
return result;
}
+2
View File
@@ -79,4 +79,6 @@ internal void cv_stringize_leaf_array(Arena *arena, String8List *out,
internal void cv_stringize_c13_parsed(Arena *arena, String8List *out, CV_C13Parsed *c13); internal void cv_stringize_c13_parsed(Arena *arena, String8List *out, CV_C13Parsed *c13);
internal String8 cv_string_from_inline_range_kind(CV_InlineRangeKind kind);
#endif // CODEVIEW_STRINGIZE_H #endif // CODEVIEW_STRINGIZE_H
+16 -1
View File
@@ -447,6 +447,7 @@ String8 result = str8_lit("<Unknown CV_LeafKind>");
switch(v) switch(v)
{ {
default:{}break; default:{}break;
case CV_LeafKind_NOTYPE:{result = str8_lit("NOTYPE");}break;
case CV_LeafKind_MODIFIER_16t:{result = str8_lit("MODIFIER_16t");}break; case CV_LeafKind_MODIFIER_16t:{result = str8_lit("MODIFIER_16t");}break;
case CV_LeafKind_POINTER_16t:{result = str8_lit("POINTER_16t");}break; case CV_LeafKind_POINTER_16t:{result = str8_lit("POINTER_16t");}break;
case CV_LeafKind_ARRAY_16t:{result = str8_lit("ARRAY_16t");}break; case CV_LeafKind_ARRAY_16t:{result = str8_lit("ARRAY_16t");}break;
@@ -571,6 +572,13 @@ case CV_LeafKind_BINTERFACE:{result = str8_lit("BINTERFACE");}break;
case CV_LeafKind_VECTOR:{result = str8_lit("VECTOR");}break; case CV_LeafKind_VECTOR:{result = str8_lit("VECTOR");}break;
case CV_LeafKind_MATRIX:{result = str8_lit("MATRIX");}break; case CV_LeafKind_MATRIX:{result = str8_lit("MATRIX");}break;
case CV_LeafKind_VFTABLE:{result = str8_lit("VFTABLE");}break; case CV_LeafKind_VFTABLE:{result = str8_lit("VFTABLE");}break;
case CV_LeafKind_FUNC_ID:{result = str8_lit("FUNC_ID");}break;
case CV_LeafKind_MFUNC_ID:{result = str8_lit("MFUNC_ID");}break;
case CV_LeafKind_BUILDINFO:{result = str8_lit("BUILDINFO");}break;
case CV_LeafKind_SUBSTR_LIST:{result = str8_lit("SUBSTR_LIST");}break;
case CV_LeafKind_STRING_ID:{result = str8_lit("STRING_ID");}break;
case CV_LeafKind_UDT_SRC_LINE:{result = str8_lit("UDT_SRC_LINE");}break;
case CV_LeafKind_UDT_MOD_SRC_LINE:{result = str8_lit("UDT_MOD_SRC_LINE");}break;
case CV_LeafKind_CLASS2:{result = str8_lit("CLASS2");}break; case CV_LeafKind_CLASS2:{result = str8_lit("CLASS2");}break;
case CV_LeafKind_STRUCT2:{result = str8_lit("STRUCT2");}break; case CV_LeafKind_STRUCT2:{result = str8_lit("STRUCT2");}break;
} }
@@ -592,7 +600,7 @@ case CV_SymKind_OEM:{result = sizeof(CV_SymOEM);}break;
case CV_SymKind_VFTABLE32:{result = sizeof(CV_SymVPath32);}break; case CV_SymKind_VFTABLE32:{result = sizeof(CV_SymVPath32);}break;
case CV_SymKind_FRAMEPROC:{result = sizeof(CV_SymFrameproc);}break; case CV_SymKind_FRAMEPROC:{result = sizeof(CV_SymFrameproc);}break;
case CV_SymKind_ANNOTATION:{result = sizeof(CV_SymAnnotation);}break; case CV_SymKind_ANNOTATION:{result = sizeof(CV_SymAnnotation);}break;
case CV_SymKind_OBJNAME:{result = sizeof(CV_SymObjname);}break; case CV_SymKind_OBJNAME:{result = sizeof(CV_SymObjName);}break;
case CV_SymKind_THUNK32:{result = sizeof(CV_SymThunk32);}break; case CV_SymKind_THUNK32:{result = sizeof(CV_SymThunk32);}break;
case CV_SymKind_BLOCK32:{result = sizeof(CV_SymBlock32);}break; case CV_SymKind_BLOCK32:{result = sizeof(CV_SymBlock32);}break;
case CV_SymKind_LABEL32:{result = sizeof(CV_SymLabel32);}break; case CV_SymKind_LABEL32:{result = sizeof(CV_SymLabel32);}break;
@@ -696,6 +704,13 @@ case CV_LeafKind_ONEMETHOD:{result = sizeof(CV_LeafOneMethod);}break;
case CV_LeafKind_NESTTYPEEX:{result = sizeof(CV_LeafNestTypeEx);}break; case CV_LeafKind_NESTTYPEEX:{result = sizeof(CV_LeafNestTypeEx);}break;
case CV_LeafKind_TYPESERVER2:{result = sizeof(CV_LeafTypeServer2);}break; case CV_LeafKind_TYPESERVER2:{result = sizeof(CV_LeafTypeServer2);}break;
case CV_LeafKind_INTERFACE:{result = sizeof(CV_LeafStruct);}break; case CV_LeafKind_INTERFACE:{result = sizeof(CV_LeafStruct);}break;
case CV_LeafKind_FUNC_ID:{result = sizeof(CV_LeafFuncId);}break;
case CV_LeafKind_MFUNC_ID:{result = sizeof(CV_LeafMFuncId);}break;
case CV_LeafKind_BUILDINFO:{result = sizeof(CV_LeafBuildInfo);}break;
case CV_LeafKind_SUBSTR_LIST:{result = sizeof(CV_LeafSubstrList);}break;
case CV_LeafKind_STRING_ID:{result = sizeof(CV_LeafStringId);}break;
case CV_LeafKind_UDT_SRC_LINE:{result = sizeof(CV_LeafUDTSrcLine);}break;
case CV_LeafKind_UDT_MOD_SRC_LINE:{result = sizeof(CV_LeafUDTModSrcLine);}break;
case CV_LeafKind_CLASS2:{result = sizeof(CV_LeafStruct2);}break; case CV_LeafKind_CLASS2:{result = sizeof(CV_LeafStruct2);}break;
case CV_LeafKind_STRUCT2:{result = sizeof(CV_LeafStruct2);}break; case CV_LeafKind_STRUCT2:{result = sizeof(CV_LeafStruct2);}break;
} }
+8
View File
@@ -381,6 +381,7 @@ CV_BasicType_PTR = 0xf0,
typedef U16 CV_LeafKind; typedef U16 CV_LeafKind;
typedef enum CV_LeafKindEnum typedef enum CV_LeafKindEnum
{ {
CV_LeafKind_NOTYPE = 0x0000,
CV_LeafKind_MODIFIER_16t = 0x0001, CV_LeafKind_MODIFIER_16t = 0x0001,
CV_LeafKind_POINTER_16t = 0x0002, CV_LeafKind_POINTER_16t = 0x0002,
CV_LeafKind_ARRAY_16t = 0x0003, CV_LeafKind_ARRAY_16t = 0x0003,
@@ -505,6 +506,13 @@ CV_LeafKind_BINTERFACE = 0x151a,
CV_LeafKind_VECTOR = 0x151b, CV_LeafKind_VECTOR = 0x151b,
CV_LeafKind_MATRIX = 0x151c, CV_LeafKind_MATRIX = 0x151c,
CV_LeafKind_VFTABLE = 0x151d, CV_LeafKind_VFTABLE = 0x151d,
CV_LeafKind_FUNC_ID = 0x1601,
CV_LeafKind_MFUNC_ID = 0x1602,
CV_LeafKind_BUILDINFO = 0x1603,
CV_LeafKind_SUBSTR_LIST = 0x1604,
CV_LeafKind_STRING_ID = 0x1605,
CV_LeafKind_UDT_SRC_LINE = 0x1606,
CV_LeafKind_UDT_MOD_SRC_LINE = 0x1607,
CV_LeafKind_CLASS2 = 0x1608, CV_LeafKind_CLASS2 = 0x1608,
CV_LeafKind_STRUCT2 = 0x1609, CV_LeafKind_STRUCT2 = 0x1609,
} CV_LeafKindEnum; } CV_LeafKindEnum;
+410 -134
View File
@@ -28,7 +28,7 @@ coff_is_obj(String8 data)
switch (header->machine) { switch (header->machine) {
case COFF_MachineType_UNKNOWN: case COFF_MachineType_UNKNOWN:
case COFF_MachineType_X86: case COFF_MachineType_X64: case COFF_MachineType_X86: case COFF_MachineType_X64:
case COFF_MachineType_ARM33: case COFF_MachineType_ARM: case COFF_MachineType_AM33: case COFF_MachineType_ARM:
case COFF_MachineType_ARM64: case COFF_MachineType_ARMNT: case COFF_MachineType_ARM64: case COFF_MachineType_ARMNT:
case COFF_MachineType_EBC: case COFF_MachineType_IA64: case COFF_MachineType_EBC: case COFF_MachineType_IA64:
case COFF_MachineType_M32R: case COFF_MachineType_MIPS16: case COFF_MachineType_M32R: case COFF_MachineType_MIPS16:
@@ -97,15 +97,17 @@ coff_header_info_from_data(String8 data)
COFF_HeaderInfo info = {0}; COFF_HeaderInfo info = {0};
if (coff_is_big_obj(data)) { if (coff_is_big_obj(data)) {
COFF_HeaderBigObj *big_header = (COFF_HeaderBigObj*)data.str; COFF_HeaderBigObj *big_header = (COFF_HeaderBigObj*)data.str;
info.machine = big_header->machine; info.type = COFF_DataType_BIG_OBJ;
info.section_array_off = sizeof(COFF_HeaderBigObj); info.machine = big_header->machine;
info.section_count_no_null = big_header->section_count; info.section_array_off = sizeof(COFF_HeaderBigObj);
info.string_table_off = big_header->pointer_to_symbol_table + sizeof(COFF_Symbol32) * big_header->number_of_symbols; info.section_count_no_null = big_header->section_count;
info.symbol_size = sizeof(COFF_Symbol32); info.string_table_off = big_header->pointer_to_symbol_table + sizeof(COFF_Symbol32) * big_header->number_of_symbols;
info.symbol_off = big_header->pointer_to_symbol_table; info.symbol_size = sizeof(COFF_Symbol32);
info.symbol_count = big_header->number_of_symbols; info.symbol_off = big_header->pointer_to_symbol_table;
info.symbol_count = big_header->number_of_symbols;
} else if (coff_is_obj(data)) { } else if (coff_is_obj(data)) {
COFF_Header *header = (COFF_Header*)data.str; COFF_Header *header = (COFF_Header*)data.str;
info.type = COFF_DataType_OBJ;
info.machine = header->machine; info.machine = header->machine;
info.section_array_off = sizeof(COFF_Header); info.section_array_off = sizeof(COFF_Header);
info.section_count_no_null = header->section_count; info.section_count_no_null = header->section_count;
@@ -143,6 +145,30 @@ coff_align_size_from_section_flags(COFF_SectionFlags flags)
return align; return align;
} }
internal COFF_SectionFlags
coff_section_flag_from_align_size(U64 align)
{
COFF_SectionFlags flags = 0;
switch (align) {
case 1: flags = COFF_SectionAlign_1BYTES; break;
case 2: flags = COFF_SectionAlign_2BYTES; break;
case 4: flags = COFF_SectionAlign_4BYTES; break;
case 8: flags = COFF_SectionAlign_8BYTES; break;
case 16: flags = COFF_SectionAlign_16BYTES; break;
case 32: flags = COFF_SectionAlign_32BYTES; break;
case 64: flags = COFF_SectionAlign_64BYTES; break;
case 128: flags = COFF_SectionAlign_128BYTES; break;
case 256: flags = COFF_SectionAlign_256BYTES; break;
case 512: flags = COFF_SectionAlign_512BYTES; break;
case 1024: flags = COFF_SectionAlign_1024BYTES; break;
case 2048: flags = COFF_SectionAlign_2048BYTES; break;
case 4096: flags = COFF_SectionAlign_4096BYTES; break;
case 8192: flags = COFF_SectionAlign_8192BYTES; break;
}
flags <<= COFF_SectionFlag_ALIGN_SHIFT;
return flags;
}
internal COFF_SymbolValueInterpType internal COFF_SymbolValueInterpType
coff_interp_symbol(COFF_Symbol32 *symbol) coff_interp_symbol(COFF_Symbol32 *symbol)
{ {
@@ -304,7 +330,7 @@ coff_symbol_array_from_data_16(Arena *arena, String8 data, U64 symbol_array_off,
{ {
COFF_Symbol32Array result; COFF_Symbol32Array result;
result.count = symbol_count; result.count = symbol_count;
result.v = push_array_no_zero(arena, COFF_Symbol32, result.count); result.v = push_array_no_zero_aligned(arena, COFF_Symbol32, result.count, 8);
COFF_Symbol16 *sym16_arr = (COFF_Symbol16 *)(data.str + symbol_array_off); COFF_Symbol16 *sym16_arr = (COFF_Symbol16 *)(data.str + symbol_array_off);
for (U64 isymbol = 0; isymbol < symbol_count; isymbol += 1) { for (U64 isymbol = 0; isymbol < symbol_count; isymbol += 1) {
@@ -387,12 +413,34 @@ coff_word_size_from_machine(COFF_MachineType machine)
{ {
U64 result = 0; U64 result = 0;
switch (machine) { switch (machine) {
case COFF_MachineType_X64: result = 8; break; case COFF_MachineType_X64: result = 8; break;
case COFF_MachineType_X86: result = 4; break; case COFF_MachineType_X86: result = 4; break;
} }
return result; return result;
} }
internal U64
coff_default_exe_base_from_machine(COFF_MachineType machine)
{
U64 exe_base = 0;
switch (coff_word_size_from_machine(machine)) {
case 4: exe_base = 0x400000; break;
case 8: exe_base = 0x140000000; break;
}
return exe_base;
}
internal U64
coff_default_dll_base_from_machine(COFF_MachineType machine)
{
U64 dll_base = 0;
switch (coff_word_size_from_machine(machine)) {
case 4: dll_base = 0x10000000; break;
case 8: dll_base = 0x180000000; break;
}
return dll_base;
}
internal String8 internal String8
coff_make_import_lookup(Arena *arena, U16 hint, String8 name) coff_make_import_lookup(Arena *arena, U16 hint, String8 name)
{ {
@@ -421,6 +469,147 @@ coff_make_ordinal_64(U16 hint)
//////////////////////////////// ////////////////////////////////
internal String8
coff_make_import_header_by_name(Arena *arena,
String8 dll_name,
COFF_MachineType machine,
COFF_TimeStamp time_stamp,
String8 name,
U16 hint,
COFF_ImportHeaderType type)
{
struct {
U16 sig1;
U16 sig2;
U16 version;
COFF_MachineType machine;
COFF_TimeStamp time_stamp;
U32 sizeof_data;
U16 hint_ordinal;
U16 flags;
} import_header = {
COFF_MachineType_UNKNOWN, // sig1
max_U16, // sig2
0, // version
machine,
time_stamp,
safe_cast_u32(name.size + dll_name.size + 2), // sizeof_data
0, // hint_ordinal
0, // flags
};
import_header.flags |= (U16)(type & COFF_IMPORT_HEADER_TYPE_MASK) << COFF_IMPORT_HEADER_TYPE_SHIFT;
import_header.flags |= COFF_ImportHeaderNameType_NAME << COFF_IMPORT_HEADER_NAME_TYPE_SHIFT;
import_header.hint_ordinal = hint;
// alloc memory
U64 buffer_size = sizeof(import_header) + import_header.sizeof_data;
U8 *buffer = push_array_no_zero(arena, U8, buffer_size);
// copy header
MemoryCopy(buffer, &import_header, sizeof(import_header));
// copy function name
U8 *func_name = buffer + sizeof(import_header);
MemoryCopy(func_name, name.str, name.size);
func_name[name.size] = 0;
// copy dll name
U8 *dll_name_buffer = buffer + sizeof(import_header) + name.size + 1;
MemoryCopy(dll_name_buffer, dll_name.str, dll_name.size);
dll_name_buffer[dll_name.size] = 0;
String8 import_data = str8(buffer, buffer_size);
return import_data;
}
internal String8
coff_make_import_header_by_ordinal(Arena *arena,
String8 dll_name,
COFF_MachineType machine,
COFF_TimeStamp time_stamp,
U16 ordinal,
COFF_ImportHeaderType type)
{
struct {
U16 sig1;
U16 sig2;
U16 version;
COFF_MachineType machine;
COFF_TimeStamp time_stamp;
U32 sizeof_data;
U16 hint_ordinal;
U16 flags;
} import_header = {
COFF_MachineType_UNKNOWN, // sig1
max_U16, // sig2
0, // version
machine,
time_stamp,
safe_cast_u32(/* name.size + */ dll_name.size + 2), // sizeof_data
0, // hint_ordinal
0, // flags
};
import_header.flags |= (U16)(type & COFF_IMPORT_HEADER_TYPE_MASK) << COFF_IMPORT_HEADER_TYPE_SHIFT;
import_header.flags |= COFF_ImportHeaderNameType_ORDINAL << COFF_IMPORT_HEADER_NAME_TYPE_SHIFT;
import_header.hint_ordinal = ordinal;
// alloc memory
U64 buffer_size = sizeof(import_header) + import_header.sizeof_data;
U8 *buffer = push_array_no_zero(arena, U8, buffer_size);
// copy header
MemoryCopyStruct(buffer, &import_header);
// no function name write zero
U8 *func_name = buffer + sizeof(import_header);
func_name[0] = 0;
// copy dll name
U8 *dll_name_buffer = buffer + sizeof(import_header) + /* name.size */ + 1;
MemoryCopy(dll_name_buffer, dll_name.str, dll_name.size);
dll_name_buffer[dll_name.size] = 0;
String8 import_data = str8(buffer, buffer_size);
return import_data;
}
////////////////////////////////
//~ Resources
internal String8
coff_resource_string_from_str16(Arena *arena, String16 string)
{
AssertAlways(string.size <= max_U16);
U16 size16 = (U16)string.size;
U16 *buffer = push_array_no_zero(arena, U16, size16 + 1);
MemoryCopy(buffer + 0, &size16, sizeof(size16));
MemoryCopy(buffer + 1, string.str, size16 * sizeof(string.str[0]));
return str8_array(buffer, size16 + 1);
}
internal String8
coff_resource_string_from_str8(Arena *arena, String8 string)
{
Temp scratch = scratch_begin(&arena, 1);
String16 string16 = str16_from_8(scratch.arena, string);
String8 result = coff_resource_string_from_str16(arena, string16);
scratch_end(scratch);
return result;
}
internal String8
coff_resource_number_from_u16(Arena *arena, U16 number)
{
U16 *buffer = push_array_no_zero(arena, U16, 2);
buffer[0] = max_U16;
buffer[1] = number;
return str8_array(buffer, 2);
}
internal B32 internal B32
coff_resource_id_is_equal(COFF_ResourceID a, COFF_ResourceID b) coff_resource_id_is_equal(COFF_ResourceID a, COFF_ResourceID b)
{ {
@@ -437,28 +626,9 @@ coff_resource_id_is_equal(COFF_ResourceID a, COFF_ResourceID b)
} }
internal COFF_ResourceID internal COFF_ResourceID
coff_resource_id_copy(Arena *arena, COFF_ResourceID id) coff_utf8_resource_id_from_utf16(Arena *arena, COFF_ResourceID_16 *id_16)
{ {
COFF_ResourceID result = zero_struct; COFF_ResourceID id = {0};
switch (id.type) {
case COFF_ResourceIDType_NULL: break;
case COFF_ResourceIDType_NUMBER: {
result.type = COFF_ResourceIDType_NUMBER;
result.u.number = id.u.number;
} break;
case COFF_ResourceIDType_STRING: {
result.type = COFF_ResourceIDType_STRING;
result.u.string = id.u.string;
} break;
default: Assert(!"invalid resource id type");
}
return result;
}
internal COFF_ResourceID
coff_convert_resource_id(Arena *arena, COFF_ResourceID_16 *id_16)
{
COFF_ResourceID id;
id.type = id_16->type; id.type = id_16->type;
switch (id_16->type) { switch (id_16->type) {
case COFF_ResourceIDType_NULL: break; case COFF_ResourceIDType_NULL: break;
@@ -468,23 +638,22 @@ coff_convert_resource_id(Arena *arena, COFF_ResourceID_16 *id_16)
case COFF_ResourceIDType_STRING: { case COFF_ResourceIDType_STRING: {
id.u.string = str8_from_16(arena, id_16->u.string); id.u.string = str8_from_16(arena, id_16->u.string);
} break; } break;
default: Assert(!"invalid resource id type"); default: InvalidPath;
} }
return id; return id;
} }
internal U64 internal U64
coff_read_resource_id(String8 data, U64 off, COFF_ResourceID_16 *id_out) coff_read_resource_id_utf16(String8 data, U64 off, COFF_ResourceID_16 *id_out)
{ {
U64 cursor = off; U64 cursor = off;
U16 flag = 0; U16 flag = 0;
str8_deserial_read_struct(data, cursor, &flag); str8_deserial_read_struct(data, cursor, &flag);
B32 is_number = flag == max_U16; if (flag == max_U16) {
if (is_number) {
cursor += sizeof(flag);
id_out->type = COFF_ResourceIDType_NUMBER; id_out->type = COFF_ResourceIDType_NUMBER;
cursor += sizeof(flag);
cursor += str8_deserial_read_struct(data, cursor, &id_out->u.number); cursor += str8_deserial_read_struct(data, cursor, &id_out->u.number);
} else { } else {
id_out->type = COFF_ResourceIDType_STRING; id_out->type = COFF_ResourceIDType_STRING;
@@ -492,72 +661,130 @@ coff_read_resource_id(String8 data, U64 off, COFF_ResourceID_16 *id_out)
} }
U64 read_size = cursor - off; U64 read_size = cursor - off;
read_size = AlignPow2(read_size, COFF_RES_ALIGN);
return read_size; return read_size;
} }
internal U64 internal U64
coff_read_resource(String8 raw_res, U64 off, Arena *arena, COFF_Resource *res_out) coff_read_resource(String8 raw_res, U64 off, Arena *arena, COFF_Resource *res_out)
{ {
// parse header String8 raw_header = str8_skip(raw_res, off);
COFF_ResourceHeaderPrefix prefix; MemoryZeroStruct(&prefix); U64 header_cursor = 0;
U64 cursor = str8_deserial_read_struct(raw_res, off, &prefix);
String8 header_data = str8_substr(raw_res, rng_1u64(off, off + prefix.header_size));
COFF_ResourceID_16 type_16; MemoryZeroStruct(&type_16); // prefix
cursor += coff_read_resource_id(header_data, cursor, &type_16); COFF_ResourceHeaderPrefix prefix = {0};
cursor = AlignPow2(cursor, COFF_RES_ALIGN); header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &prefix);
COFF_ResourceID_16 name_16; MemoryZeroStruct(&name_16); Assert(prefix.header_size >= sizeof(COFF_ResourceHeaderPrefix));
cursor += coff_read_resource_id(header_data, cursor, &name_16); raw_header = str8_prefix(raw_header, prefix.header_size);
cursor = AlignPow2(cursor, COFF_RES_ALIGN);
U32 data_version = 0; // header
cursor += str8_deserial_read_struct(header_data, cursor, &data_version); COFF_ResourceID_16 type_16 = {0};
COFF_ResourceID_16 name_16 = {0};
header_cursor += coff_read_resource_id_utf16(raw_header, header_cursor, &type_16);
header_cursor += coff_read_resource_id_utf16(raw_header, header_cursor, &name_16);
header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->data_version);
header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->memory_flags);
header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->language_id);
header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->version);
header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->characteristics);
Assert(prefix.header_size == header_cursor);
COFF_ResourceMemoryFlags memory_flags = 0; // convert utf-16 resource ids to utf-8
cursor += str8_deserial_read_struct(header_data, cursor, &memory_flags); res_out->type = coff_utf8_resource_id_from_utf16(arena, &type_16);
res_out->name = coff_utf8_resource_id_from_utf16(arena, &name_16);
U16 language_id = 0; // read data
cursor += str8_deserial_read_struct(header_data, cursor, &language_id); U64 data_read_size = str8_deserial_read_block(raw_res, off + prefix.header_size, prefix.data_size, &res_out->data);
Assert(prefix.data_size == data_read_size);
U32 version = 0; // compute read size
cursor += str8_deserial_read_struct(header_data, cursor, &version); U64 read_size = Max(prefix.header_size, sizeof(prefix)) + AlignPow2(prefix.data_size, COFF_RES_ALIGN);
return read_size;
U32 characteristics = 0;
cursor += str8_deserial_read_struct(header_data, cursor, &characteristics);
String8 data;
cursor += str8_deserial_read_block(raw_res, off + prefix.header_size, prefix.data_size, &data);
// was resource parsed?
Assert(cursor >= prefix.data_size + prefix.header_size);
// fill out result
res_out->type = coff_convert_resource_id(arena, &type_16);
res_out->name = coff_convert_resource_id(arena, &name_16);
res_out->language_id = language_id;
res_out->data_version = data_version;
res_out->version = version;
res_out->memory_flags = memory_flags;
res_out->data = data;
U64 resource_size = AlignPow2(prefix.data_size + prefix.header_size, COFF_RES_ALIGN);
return resource_size;
} }
internal COFF_ResourceList internal COFF_ResourceList
coff_resource_list_from_data(Arena *arena, String8 data) coff_resource_list_from_data(Arena *arena, String8 data)
{ {
COFF_ResourceList list; MemoryZeroStruct(&list); COFF_ResourceList list = {0};
for (U64 cursor = 0, stride; cursor < data.size; cursor += stride) { U64 cursor;
for (cursor = 0 ; cursor < data.size; ) {
COFF_ResourceNode *node = push_array(arena, COFF_ResourceNode, 1); COFF_ResourceNode *node = push_array(arena, COFF_ResourceNode, 1);
stride = coff_read_resource(data, cursor, arena, &node->data); cursor += coff_read_resource(data, cursor, arena, &node->data);
list.count += 1;
SLLQueuePush(list.first, list.last, node); SLLQueuePush(list.first, list.last, node);
++list.count;
} }
Assert(cursor == data.size);
return list; return list;
} }
internal String8
coff_write_resource_id(Arena *arena, COFF_ResourceID id)
{
String8 result = str8_zero();
switch (id.type) {
case COFF_ResourceIDType_NULL: break;
case COFF_ResourceIDType_NUMBER: {
result = coff_resource_number_from_u16(arena, id.u.number);
} break;
case COFF_ResourceIDType_STRING: {
result = coff_resource_string_from_str8(arena, id.u.string);
} break;
default: InvalidPath;
}
return result;
}
internal String8
coff_write_resource(Arena *arena,
COFF_ResourceID type,
COFF_ResourceID name,
U32 data_version,
COFF_ResourceMemoryFlags memory_flags,
U16 language_id,
U32 version,
U32 characteristics,
String8 data)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
COFF_ResourceHeaderPrefix *prefix = push_array(scratch.arena, COFF_ResourceHeaderPrefix, 1);
String8 packed_type = coff_write_resource_id(scratch.arena, type);
String8 packed_name = coff_write_resource_id(scratch.arena, name);
// prefix + header
str8_list_push(scratch.arena, &list, str8_struct(prefix));
str8_list_push(scratch.arena, &list, packed_type);
str8_list_push(scratch.arena, &list, packed_name);
str8_list_push(scratch.arena, &list, str8_struct(&data_version));
str8_list_push(scratch.arena, &list, str8_struct(&memory_flags));
str8_list_push(scratch.arena, &list, str8_struct(&language_id));
str8_list_push(scratch.arena, &list, str8_struct(&version));
str8_list_push(scratch.arena, &list, str8_struct(&characteristics));
prefix->data_size = safe_cast_u32(data.size);
prefix->header_size = safe_cast_u32(list.total_size);
// data
str8_list_push(scratch.arena, &list, data);
// magic
str8_list_push_front(scratch.arena, &list, str8_array_fixed(g_coff_res_magic));
// align
U64 align_size = AlignPow2(list.total_size, COFF_RES_ALIGN) - list.total_size;
U8 *align = push_array(scratch.arena, U8, align_size);
str8_list_push(scratch.arena, &list, str8(align, align_size));
// join
String8 res = str8_list_join(arena, &list, 0);
scratch_end(scratch);
return res;
}
//////////////////////////////// ////////////////////////////////
internal COFF_DataType internal COFF_DataType
@@ -567,12 +794,10 @@ coff_data_type_from_data(String8 data)
if (is_big_obj) { if (is_big_obj) {
return COFF_DataType_BIG_OBJ; return COFF_DataType_BIG_OBJ;
} }
B32 is_import = coff_is_import(data); B32 is_import = coff_is_import(data);
if (is_import) { if (is_import) {
return COFF_DataType_IMPORT; return COFF_DataType_IMPORT;
} }
return COFF_DataType_OBJ; return COFF_DataType_OBJ;
} }
@@ -591,18 +816,22 @@ coff_is_import(String8 data)
internal B32 internal B32
coff_is_archive(String8 data) coff_is_archive(String8 data)
{ {
U64 sig = 0; B32 is_archive = 0;
str8_deserial_read_struct(data, 0, &sig); U8 sig[sizeof(g_coff_archive_sig)];
B32 is_archive = sig == COFF_ARCHIVE_SIG; if (str8_deserial_read_struct(data, 0, &sig) == sizeof(sig)) {
is_archive = MemoryCompare(&sig[0], &g_coff_archive_sig[0], sizeof(g_coff_archive_sig)) == 0;
}
return is_archive; return is_archive;
} }
internal B32 internal B32
coff_is_thin_archive(String8 data) coff_is_thin_archive(String8 data)
{ {
U64 sig = 0; B32 is_archive = 0;
str8_deserial_read_struct(data, 0, &sig); U8 sig[sizeof(g_coff_thin_archive_sig)];
B32 is_archive = sig == COFF_THIN_ARCHIVE_SIG; if (str8_deserial_read_struct(data, 0, &sig) == sizeof(sig)) {
is_archive = MemoryCompare(&sig[0], &g_coff_thin_archive_sig[0], sizeof(g_coff_thin_archive_sig)) == 0;
}
return is_archive; return is_archive;
} }
@@ -751,11 +980,9 @@ coff_read_archive_long_name(String8 long_names, String8 name)
internal U64 internal U64
coff_archive_member_iter_init(String8 data) coff_archive_member_iter_init(String8 data)
{ {
U64 cursor = 0; U64 cursor = data.size;
U64 sig = 0; if (coff_is_archive(data)) {
cursor += str8_deserial_read_struct(data, cursor, &sig); cursor = sizeof(g_coff_archive_sig);
if (sig != COFF_ARCHIVE_SIG) {
cursor = data.size;
} }
return cursor; return cursor;
} }
@@ -915,11 +1142,9 @@ coff_archive_from_data(Arena *arena, String8 data)
internal U64 internal U64
coff_thin_archive_member_iter_init(String8 data) coff_thin_archive_member_iter_init(String8 data)
{ {
U64 cursor = 0; U64 cursor = data.size;
U64 sig = 0; if (coff_is_thin_archive(data)) {
cursor += str8_deserial_read_struct(data, cursor, &sig); cursor = sizeof(g_coff_thin_archive_sig);
if (sig != COFF_THIN_ARCHIVE_SIG) {
cursor = data.size;
} }
return cursor; return cursor;
} }
@@ -990,18 +1215,59 @@ coff_archive_parse_from_data(Arena *arena, String8 data)
//////////////////////////////// ////////////////////////////////
read_only struct
{
String8 string;
COFF_MachineType machine;
} g_coff_machine_map[] = {
{ str8_lit_comp(""), COFF_MachineType_UNKNOWN },
{ str8_lit_comp("X86"), COFF_MachineType_X86 },
{ str8_lit_comp("AMD64"), COFF_MachineType_X64 },
{ str8_lit_comp("X64"), COFF_MachineType_X64 },
{ str8_lit_comp("AM33"), COFF_MachineType_AM33 },
{ str8_lit_comp("ARM"), COFF_MachineType_ARM },
{ str8_lit_comp("ARM64"), COFF_MachineType_ARM64 },
{ str8_lit_comp("ARMNT"), COFF_MachineType_ARMNT },
{ str8_lit_comp("EBC"), COFF_MachineType_EBC },
{ str8_lit_comp("IA64"), COFF_MachineType_IA64 },
{ str8_lit_comp("M32R"), COFF_MachineType_M32R },
{ str8_lit_comp("MIPS16"), COFF_MachineType_MIPS16 },
{ str8_lit_comp("MIPSFPU"), COFF_MachineType_MIPSFPU },
{ str8_lit_comp("MIPSFPU16"), COFF_MachineType_MIPSFPU16 },
{ str8_lit_comp("POWERPC"), COFF_MachineType_POWERPC },
{ str8_lit_comp("POWERPCFP"), COFF_MachineType_POWERPCFP },
{ str8_lit_comp("R4000"), COFF_MachineType_R4000 },
{ str8_lit_comp("RISCV32"), COFF_MachineType_RISCV32 },
{ str8_lit_comp("RISCV64"), COFF_MachineType_RISCV64 },
{ str8_lit_comp("SH3"), COFF_MachineType_SH3 },
{ str8_lit_comp("SH3DSP"), COFF_MachineType_SH3DSP },
{ str8_lit_comp("SH4"), COFF_MachineType_SH4 },
{ str8_lit_comp("SH5"), COFF_MachineType_SH5 },
{ str8_lit_comp("THUMB"), COFF_MachineType_THUMB },
{ str8_lit_comp("WCEMIPSV2"), COFF_MachineType_WCEMIPSV2 },
};
read_only static struct {
char * name;
COFF_ImportHeaderType type;
} g_coff_import_header_type_map[] = {
{ "CODE", COFF_ImportHeaderType_CODE },
{ "DATA", COFF_ImportHeaderType_DATA },
{ "CONST", COFF_ImportHeaderType_CONST },
};
internal String8 internal String8
coff_string_from_comdat_select_type(COFF_ComdatSelectType select) coff_string_from_comdat_select_type(COFF_ComdatSelectType select)
{ {
String8 result = str8(0,0); String8 result = str8(0,0);
switch (select) { switch (select) {
case COFF_ComdatSelectType_NULL: result = str8_lit("NULL"); break; case COFF_ComdatSelectType_NULL: result = str8_lit("NULL"); break;
case COFF_ComdatSelectType_NODUPLICATES: result = str8_lit("NODUPLICATES"); break; case COFF_ComdatSelectType_NODUPLICATES: result = str8_lit("NODUPLICATES"); break;
case COFF_ComdatSelectType_ANY: result = str8_lit("ANY"); break; case COFF_ComdatSelectType_ANY: result = str8_lit("ANY"); break;
case COFF_ComdatSelectType_SAME_SIZE: result = str8_lit("SAME_SIZE"); break; case COFF_ComdatSelectType_SAME_SIZE: result = str8_lit("SAME_SIZE"); break;
case COFF_ComdatSelectType_EXACT_MATCH: result = str8_lit("EXACT_MATCH"); break; case COFF_ComdatSelectType_EXACT_MATCH: result = str8_lit("EXACT_MATCH"); break;
case COFF_ComdatSelectType_ASSOCIATIVE: result = str8_lit("ASSOCIATIVE"); break; case COFF_ComdatSelectType_ASSOCIATIVE: result = str8_lit("ASSOCIATIVE"); break;
case COFF_ComdatSelectType_LARGEST: result = str8_lit("LARGEST"); break; case COFF_ComdatSelectType_LARGEST: result = str8_lit("LARGEST"); break;
} }
return result; return result;
} }
@@ -1009,35 +1275,12 @@ coff_string_from_comdat_select_type(COFF_ComdatSelectType select)
internal String8 internal String8
coff_string_from_machine_type(COFF_MachineType machine) coff_string_from_machine_type(COFF_MachineType machine)
{ {
String8 result = str8(0,0); for (U64 i = 0; i < ArrayCount(g_coff_machine_map); ++i) {
switch (machine) { if (g_coff_machine_map[i].machine == machine) {
case COFF_MachineType_UNKNOWN: result = str8_lit("UNKNOWN"); break; return g_coff_machine_map[i].string;
case COFF_MachineType_X86: result = str8_lit("X86"); break; }
case COFF_MachineType_X64: result = str8_lit("X64"); break;
case COFF_MachineType_ARM33: result = str8_lit("ARM33"); break;
case COFF_MachineType_ARM: result = str8_lit("ARM"); break;
case COFF_MachineType_ARM64: result = str8_lit("ARM64"); break;
case COFF_MachineType_ARMNT: result = str8_lit("ARMNT"); break;
case COFF_MachineType_EBC: result = str8_lit("EBC"); break;
case COFF_MachineType_IA64: result = str8_lit("IA64"); break;
case COFF_MachineType_M32R: result = str8_lit("M32R"); break;
case COFF_MachineType_MIPS16: result = str8_lit("MIPS16"); break;
case COFF_MachineType_MIPSFPU: result = str8_lit("MIPSFPU"); break;
case COFF_MachineType_MIPSFPU16: result = str8_lit("MIPSFPU16"); break;
case COFF_MachineType_POWERPC: result = str8_lit("POWERPC"); break;
case COFF_MachineType_POWERPCFP: result = str8_lit("POWERPCFP"); break;
case COFF_MachineType_R4000: result = str8_lit("R4000"); break;
case COFF_MachineType_RISCV32: result = str8_lit("RISCV32"); break;
case COFF_MachineType_RISCV64: result = str8_lit("RISCV64"); break;
case COFF_MachineType_RISCV128: result = str8_lit("RISCV128"); break;
case COFF_MachineType_SH3: result = str8_lit("SH3"); break;
case COFF_MachineType_SH3DSP: result = str8_lit("SH3DSP"); break;
case COFF_MachineType_SH4: result = str8_lit("SH4"); break;
case COFF_MachineType_SH5: result = str8_lit("SH5"); break;
case COFF_MachineType_THUMB: result = str8_lit("THUMB"); break;
case COFF_MachineType_WCEMIPSV2: result = str8_lit("WCEMIPSV2"); break;
} }
return result; return str8_zero();
} }
internal String8 internal String8
@@ -1117,3 +1360,36 @@ coff_string_from_section_flags(Arena *arena, COFF_SectionFlags flags)
return result; return result;
} }
internal String8
coff_string_from_import_header_type(COFF_ImportHeaderType type)
{
for (U64 i = 0; i < ArrayCount(g_coff_import_header_type_map); ++i) {
if (g_coff_import_header_type_map[i].type == type) {
return str8_cstring(g_coff_import_header_type_map[i].name);
}
}
return str8(0,0);
}
internal COFF_MachineType
coff_machine_from_string(String8 string)
{
for (U64 i = 0; i < ArrayCount(g_coff_machine_map); ++i) {
if (str8_match(g_coff_machine_map[i].string, string, StringMatchFlag_CaseInsensitive)) {
return g_coff_machine_map[i].machine;
}
}
return COFF_MachineType_UNKNOWN;
}
internal COFF_ImportHeaderType
coff_import_header_type_from_string(String8 name)
{
for (U64 i = 0; i < ArrayCount(g_coff_import_header_type_map); ++i) {
if (str8_match(str8_cstring(g_coff_import_header_type_map[i].name), name, StringMatchFlag_CaseInsensitive)) {
return g_coff_import_header_type_map[i].type;
}
}
return COFF_ImportHeaderType_COUNT;
}
+309 -287
View File
@@ -48,7 +48,7 @@ enum
COFF_MachineType_UNKNOWN = 0x0, COFF_MachineType_UNKNOWN = 0x0,
COFF_MachineType_X86 = 0x14c, COFF_MachineType_X86 = 0x14c,
COFF_MachineType_X64 = 0x8664, COFF_MachineType_X64 = 0x8664,
COFF_MachineType_ARM33 = 0x1d3, COFF_MachineType_AM33 = 0x1d3,
COFF_MachineType_ARM = 0x1c0, COFF_MachineType_ARM = 0x1c0,
COFF_MachineType_ARM64 = 0xaa64, COFF_MachineType_ARM64 = 0xaa64,
COFF_MachineType_ARMNT = 0x1c4, COFF_MachineType_ARMNT = 0x1c4,
@@ -77,12 +77,12 @@ typedef struct COFF_Header COFF_Header;
struct COFF_Header struct COFF_Header
{ {
COFF_MachineType machine; COFF_MachineType machine;
U16 section_count; U16 section_count;
COFF_TimeStamp time_stamp; COFF_TimeStamp time_stamp;
U32 symbol_table_foff; U32 symbol_table_foff;
U32 symbol_count; U32 symbol_count;
U16 optional_header_size; U16 optional_header_size;
COFF_Flags flags; COFF_Flags flags;
}; };
typedef U32 COFF_SectionAlign; typedef U32 COFF_SectionAlign;
@@ -108,35 +108,36 @@ enum
typedef U32 COFF_SectionFlags; typedef U32 COFF_SectionFlags;
enum enum
{ {
COFF_SectionFlag_TYPE_NO_PAD = (1 << 3), COFF_SectionFlag_TYPE_NO_PAD = (1 << 3),
COFF_SectionFlag_CNT_CODE = (1 << 5), COFF_SectionFlag_CNT_CODE = (1 << 5),
COFF_SectionFlag_CNT_INITIALIZED_DATA = (1 << 6), COFF_SectionFlag_CNT_INITIALIZED_DATA = (1 << 6),
COFF_SectionFlag_CNT_UNINITIALIZED_DATA = (1 << 7), COFF_SectionFlag_CNT_UNINITIALIZED_DATA = (1 << 7),
COFF_SectionFlag_LNK_OTHER = (1 << 8), COFF_SectionFlag_LNK_OTHER = (1 << 8),
COFF_SectionFlag_LNK_INFO = (1 << 9), COFF_SectionFlag_LNK_INFO = (1 << 9),
COFF_SectionFlag_LNK_REMOVE = (1 << 11), COFF_SectionFlag_LNK_REMOVE = (1 << 11),
COFF_SectionFlag_LNK_COMDAT = (1 << 12), COFF_SectionFlag_LNK_COMDAT = (1 << 12),
COFF_SectionFlag_GPREL = (1 << 15), COFF_SectionFlag_GPREL = (1 << 15),
COFF_SectionFlag_MEM_16BIT = (1 << 17), COFF_SectionFlag_MEM_16BIT = (1 << 17),
COFF_SectionFlag_MEM_LOCKED = (1 << 18), COFF_SectionFlag_MEM_LOCKED = (1 << 18),
COFF_SectionFlag_MEM_PRELOAD = (1 << 19), COFF_SectionFlag_MEM_PRELOAD = (1 << 19),
COFF_SectionFlag_ALIGN_SHIFT = 20, COFF_SectionFlag_ALIGN_MASK = 0xf, COFF_SectionFlag_ALIGN_SHIFT = 20,
COFF_SectionFlag_LNK_NRELOC_OVFL = (1 << 24), COFF_SectionFlag_ALIGN_MASK = 0xf,
COFF_SectionFlag_MEM_DISCARDABLE = (1 << 25), COFF_SectionFlag_LNK_NRELOC_OVFL = (1 << 24),
COFF_SectionFlag_MEM_NOT_CACHED = (1 << 26), COFF_SectionFlag_MEM_DISCARDABLE = (1 << 25),
COFF_SectionFlag_MEM_NOT_PAGED = (1 << 27), COFF_SectionFlag_MEM_NOT_CACHED = (1 << 26),
COFF_SectionFlag_MEM_SHARED = (1 << 28), COFF_SectionFlag_MEM_NOT_PAGED = (1 << 27),
COFF_SectionFlag_MEM_EXECUTE = (1 << 29), COFF_SectionFlag_MEM_SHARED = (1 << 28),
COFF_SectionFlag_MEM_READ = (1 << 30), COFF_SectionFlag_MEM_EXECUTE = (1 << 29),
COFF_SectionFlag_MEM_WRITE = (1 << 31), COFF_SectionFlag_MEM_READ = (1 << 30),
COFF_SectionFlag_MEM_WRITE = (1 << 31),
}; };
#define COFF_SectionFlags_Extract_ALIGN(f) (COFF_SectionAlign)(((f) >> COFF_SectionFlag_ALIGN_SHIFT) & COFF_SectionFlag_ALIGN_MASK) #define COFF_SectionFlags_Extract_ALIGN(f) (COFF_SectionAlign)(((f) >> COFF_SectionFlag_ALIGN_SHIFT) & COFF_SectionFlag_ALIGN_MASK)
#define COFF_SectionFlags_LNK_FLAGS ((COFF_SectionFlag_ALIGN_MASK << COFF_SectionFlag_ALIGN_SHIFT) | COFF_SectionFlag_LNK_COMDAT | COFF_SectionFlag_LNK_INFO | COFF_SectionFlag_LNK_OTHER | COFF_SectionFlag_LNK_REMOVE | COFF_SectionFlag_LNK_NRELOC_OVFL) #define COFF_SectionFlags_LNK_FLAGS ((COFF_SectionFlag_ALIGN_MASK << COFF_SectionFlag_ALIGN_SHIFT) | COFF_SectionFlag_LNK_COMDAT | COFF_SectionFlag_LNK_INFO | COFF_SectionFlag_LNK_OTHER | COFF_SectionFlag_LNK_REMOVE | COFF_SectionFlag_LNK_NRELOC_OVFL)
typedef struct COFF_SectionHeader COFF_SectionHeader; typedef struct COFF_SectionHeader COFF_SectionHeader;
struct COFF_SectionHeader struct COFF_SectionHeader
{ {
U8 name[8]; U8 name[8];
U32 vsize; U32 vsize;
U32 voff; U32 voff;
U32 fsize; U32 fsize;
@@ -151,112 +152,99 @@ struct COFF_SectionHeader
typedef U16 COFF_RelocTypeX64; typedef U16 COFF_RelocTypeX64;
enum enum
{ {
COFF_RelocTypeX64_ABS = 0x0, COFF_RelocTypeX64_ABS = 0x0,
COFF_RelocTypeX64_ADDR64 = 0x1, COFF_RelocTypeX64_ADDR64 = 0x1,
COFF_RelocTypeX64_ADDR32 = 0x2, COFF_RelocTypeX64_ADDR32 = 0x2,
COFF_RelocTypeX64_ADDR32NB = 0x3, COFF_RelocTypeX64_ADDR32NB = 0x3, // NB => No Base
// NB => No Base COFF_RelocTypeX64_REL32 = 0x4,
COFF_RelocTypeX64_REL32 = 0x4, COFF_RelocTypeX64_REL32_1 = 0x5,
COFF_RelocTypeX64_REL32_1 = 0x5, COFF_RelocTypeX64_REL32_2 = 0x6,
COFF_RelocTypeX64_REL32_2 = 0x6, COFF_RelocTypeX64_REL32_3 = 0x7,
COFF_RelocTypeX64_REL32_3 = 0x7, COFF_RelocTypeX64_REL32_4 = 0x8,
COFF_RelocTypeX64_REL32_4 = 0x8, COFF_RelocTypeX64_REL32_5 = 0x9,
COFF_RelocTypeX64_REL32_5 = 0x9, COFF_RelocTypeX64_SECTION = 0xA,
COFF_RelocTypeX64_SECTION = 0xA, COFF_RelocTypeX64_SECREL = 0xB,
COFF_RelocTypeX64_SECREL = 0xB, COFF_RelocTypeX64_SECREL7 = 0xC, // TODO(nick): MSDN doesn't specify size for CLR token
COFF_RelocTypeX64_SECREL7 = 0xC, COFF_RelocTypeX64_TOKEN = 0xD,
// TODO(nick): MSDN doesn't specify size for CLR token COFF_RelocTypeX64_SREL32 = 0xE, // TODO(nick): MSDN doesn't specify size for PAIR
COFF_RelocTypeX64_TOKEN = 0xD, COFF_RelocTypeX64_PAIR = 0xF,
COFF_RelocTypeX64_SREL32 = 0xE, COFF_RelocTypeX64_SSPAN32 = 0x10,
// TODO(nick): MSDN doesn't specify size for PAIR COFF_RelocTypeX64_COUNT = 17
COFF_RelocTypeX64_PAIR = 0xF,
COFF_RelocTypeX64_SSPAN32 = 0x10,
COFF_RelocTypeX64_COUNT = 17
}; };
typedef U16 COFF_RelocTypeX86; typedef U16 COFF_RelocTypeX86;
enum enum
{ {
COFF_RelocTypeX86_ABS = 0x0, COFF_RelocTypeX86_ABS = 0x0, // relocation is ignored
// relocation is ignored COFF_RelocTypeX86_DIR16 = 0x1, // no support
COFF_RelocTypeX86_DIR16 = 0x1, COFF_RelocTypeX86_REL16 = 0x2, // no support
// no support COFF_RelocTypeX86_UNKNOWN0 = 0x3,
COFF_RelocTypeX86_REL16 = 0x2, COFF_RelocTypeX86_UNKNOWN2 = 0x4,
// no support COFF_RelocTypeX86_UNKNOWN3 = 0x5,
COFF_RelocTypeX86_UNKNOWN0 = 0x3, COFF_RelocTypeX86_DIR32 = 0x6, // 32-bit virtual address
COFF_RelocTypeX86_UNKNOWN2 = 0x4, COFF_RelocTypeX86_DIR32NB = 0x7, // 32-bit virtual offset
COFF_RelocTypeX86_UNKNOWN3 = 0x5, COFF_RelocTypeX86_SEG12 = 0x9, // no support
COFF_RelocTypeX86_DIR32 = 0x6, COFF_RelocTypeX86_SECTION = 0xA, // 16-bit section index, used for debug info purposes
// 32-bit virtual address COFF_RelocTypeX86_SECREL = 0xB, // 32-bit offset from start of a section
COFF_RelocTypeX86_DIR32NB = 0x7, COFF_RelocTypeX86_TOKEN = 0xC, // CLR token? (for managed languages)
// 32-bit virtual offset COFF_RelocTypeX86_SECREL7 = 0xD, // 7-bit offset from the base of the section that contains the target.
COFF_RelocTypeX86_SEG12 = 0x9, COFF_RelocTypeX86_UNKNOWN4 = 0xE,
// no support COFF_RelocTypeX86_UNKNOWN5 = 0xF,
COFF_RelocTypeX86_SECTION = 0xA, COFF_RelocTypeX86_UNKNOWN6 = 0x10,
// 16-bit section index, used for debug info purposes COFF_RelocTypeX86_UNKNOWN7 = 0x11,
COFF_RelocTypeX86_SECREL = 0xB, COFF_RelocTypeX86_UNKNOWN8 = 0x12,
// 32-bit offset from start of a section COFF_RelocTypeX86_UNKNOWN9 = 0x13,
COFF_RelocTypeX86_TOKEN = 0xC, COFF_RelocTypeX86_REL32 = 0x14,
// CLR token? (for managed languages) COFF_RelocTypeX86_COUNT = 20
COFF_RelocTypeX86_SECREL7 = 0xD,
// 7-bit offset from the base of the section that contains the target.
COFF_RelocTypeX86_UNKNOWN4 = 0xE,
COFF_RelocTypeX86_UNKNOWN5 = 0xF,
COFF_RelocTypeX86_UNKNOWN6 = 0x10,
COFF_RelocTypeX86_UNKNOWN7 = 0x11,
COFF_RelocTypeX86_UNKNOWN8 = 0x12,
COFF_RelocTypeX86_UNKNOWN9 = 0x13,
COFF_RelocTypeX86_REL32 = 0x14,
COFF_RelocTypeX86_COUNT = 20
}; };
typedef U16 COFF_RelocTypeARM; typedef U16 COFF_RelocTypeARM;
enum enum
{ {
COFF_RelocTypeARM_ABS = 0x0, COFF_RelocTypeARM_ABS = 0x0,
COFF_RelocTypeARM_ADDR32 = 0x1, COFF_RelocTypeARM_ADDR32 = 0x1,
COFF_RelocTypeARM_ADDR32NB = 0x2, COFF_RelocTypeARM_ADDR32NB = 0x2,
COFF_RelocTypeARM_BRANCH24 = 0x3, COFF_RelocTypeARM_BRANCH24 = 0x3,
COFF_RelocTypeARM_BRANCH11 = 0x4, COFF_RelocTypeARM_BRANCH11 = 0x4,
COFF_RelocTypeARM_UNKNOWN1 = 0x5, COFF_RelocTypeARM_UNKNOWN1 = 0x5,
COFF_RelocTypeARM_UNKNOWN2 = 0x6, COFF_RelocTypeARM_UNKNOWN2 = 0x6,
COFF_RelocTypeARM_UNKNOWN3 = 0x7, COFF_RelocTypeARM_UNKNOWN3 = 0x7,
COFF_RelocTypeARM_UNKNOWN4 = 0x8, COFF_RelocTypeARM_UNKNOWN4 = 0x8,
COFF_RelocTypeARM_UNKNOWN5 = 0x9, COFF_RelocTypeARM_UNKNOWN5 = 0x9,
COFF_RelocTypeARM_REL32 = 0xA, COFF_RelocTypeARM_REL32 = 0xA,
COFF_RelocTypeARM_SECTION = 0xE, COFF_RelocTypeARM_SECTION = 0xE,
COFF_RelocTypeARM_SECREL = 0xF, COFF_RelocTypeARM_SECREL = 0xF,
COFF_RelocTypeARM_MOV32 = 0x10, COFF_RelocTypeARM_MOV32 = 0x10,
COFF_RelocTypeARM_THUMB_MOV32 = 0x11, COFF_RelocTypeARM_THUMB_MOV32 = 0x11,
COFF_RelocTypeARM_THUMB_BRANCH20 = 0x12, COFF_RelocTypeARM_THUMB_BRANCH20 = 0x12,
COFF_RelocTypeARM_UNUSED = 0x13, COFF_RelocTypeARM_UNUSED = 0x13,
COFF_RelocTypeARM_THUMB_BRANCH24 = 0x14, COFF_RelocTypeARM_THUMB_BRANCH24 = 0x14,
COFF_RelocTypeARM_THUMB_BLX23 = 0x15, COFF_RelocTypeARM_THUMB_BLX23 = 0x15,
COFF_RelocTypeARM_PAIR = 0x16, COFF_RelocTypeARM_PAIR = 0x16,
COFF_RelocTypeARM_COUNT = 20 COFF_RelocTypeARM_COUNT = 20
}; };
typedef U16 COFF_RelocTypeARM64; typedef U16 COFF_RelocTypeARM64;
enum enum
{ {
COFF_RelocTypeARM64_ABS = 0x0, COFF_RelocTypeARM64_ABS = 0x0,
COFF_RelocTypeARM64_ADDR32 = 0x1, COFF_RelocTypeARM64_ADDR32 = 0x1,
COFF_RelocTypeARM64_ADDR32NB = 0x2, COFF_RelocTypeARM64_ADDR32NB = 0x2,
COFF_RelocTypeARM64_BRANCH26 = 0x3, COFF_RelocTypeARM64_BRANCH26 = 0x3,
COFF_RelocTypeARM64_PAGEBASE_REL21 = 0x4, COFF_RelocTypeARM64_PAGEBASE_REL21 = 0x4,
COFF_RelocTypeARM64_REL21 = 0x5, COFF_RelocTypeARM64_REL21 = 0x5,
COFF_RelocTypeARM64_PAGEOFFSET_12A = 0x6, COFF_RelocTypeARM64_PAGEOFFSET_12A = 0x6,
COFF_RelocTypeARM64_SECREL = 0x8, COFF_RelocTypeARM64_SECREL = 0x8,
COFF_RelocTypeARM64_SECREL_LOW12A = 0x9, COFF_RelocTypeARM64_SECREL_LOW12A = 0x9,
COFF_RelocTypeARM64_SECREL_HIGH12A = 0xA, COFF_RelocTypeARM64_SECREL_HIGH12A = 0xA,
COFF_RelocTypeARM64_SECREL_LOW12L = 0xB, COFF_RelocTypeARM64_SECREL_LOW12L = 0xB,
COFF_RelocTypeARM64_TOKEN = 0xC, COFF_RelocTypeARM64_TOKEN = 0xC,
COFF_RelocTypeARM64_SECTION = 0xD, COFF_RelocTypeARM64_SECTION = 0xD,
COFF_RelocTypeARM64_ADDR64 = 0xE, COFF_RelocTypeARM64_ADDR64 = 0xE,
COFF_RelocTypeARM64_BRANCH19 = 0xF, COFF_RelocTypeARM64_BRANCH19 = 0xF,
COFF_RelocTypeARM64_BRANCH14 = 0x10, COFF_RelocTypeARM64_BRANCH14 = 0x10,
COFF_RelocTypeARM64_REL32 = 0x11, COFF_RelocTypeARM64_REL32 = 0x11,
COFF_RelocTypeARM64_COUNT = 17 COFF_RelocTypeARM64_COUNT = 17
}; };
typedef U8 COFF_SymType; typedef U8 COFF_SymType;
@@ -273,8 +261,7 @@ enum
COFF_SymType_STRUCT, COFF_SymType_STRUCT,
COFF_SymType_UNION, COFF_SymType_UNION,
COFF_SymType_ENUM, COFF_SymType_ENUM,
COFF_SymType_MOE, COFF_SymType_MOE, // member of enumeration
// member of enumeration
COFF_SymType_BYTE, COFF_SymType_BYTE,
COFF_SymType_WORD, COFF_SymType_WORD,
COFF_SymType_UINT, COFF_SymType_UINT,
@@ -285,100 +272,100 @@ enum
typedef U8 COFF_SymStorageClass; typedef U8 COFF_SymStorageClass;
enum enum
{ {
COFF_SymStorageClass_END_OF_FUNCTION = 0xff, COFF_SymStorageClass_END_OF_FUNCTION = 0xff,
COFF_SymStorageClass_NULL = 0, COFF_SymStorageClass_NULL = 0,
COFF_SymStorageClass_AUTOMATIC = 1, COFF_SymStorageClass_AUTOMATIC = 1,
COFF_SymStorageClass_EXTERNAL = 2, COFF_SymStorageClass_EXTERNAL = 2,
COFF_SymStorageClass_STATIC = 3, COFF_SymStorageClass_STATIC = 3,
COFF_SymStorageClass_REGISTER = 4, COFF_SymStorageClass_REGISTER = 4,
COFF_SymStorageClass_EXTERNAL_DEF = 5, COFF_SymStorageClass_EXTERNAL_DEF = 5,
COFF_SymStorageClass_LABEL = 6, COFF_SymStorageClass_LABEL = 6,
COFF_SymStorageClass_UNDEFINED_LABEL = 7, COFF_SymStorageClass_UNDEFINED_LABEL = 7,
COFF_SymStorageClass_MEMBER_OF_STRUCT = 8, COFF_SymStorageClass_MEMBER_OF_STRUCT = 8,
COFF_SymStorageClass_ARGUMENT = 9, COFF_SymStorageClass_ARGUMENT = 9,
COFF_SymStorageClass_STRUCT_TAG = 10, COFF_SymStorageClass_STRUCT_TAG = 10,
COFF_SymStorageClass_MEMBER_OF_UNION = 11, COFF_SymStorageClass_MEMBER_OF_UNION = 11,
COFF_SymStorageClass_UNION_TAG = 12, COFF_SymStorageClass_UNION_TAG = 12,
COFF_SymStorageClass_TYPE_DEFINITION = 13, COFF_SymStorageClass_TYPE_DEFINITION = 13,
COFF_SymStorageClass_UNDEFINED_STATIC = 14, COFF_SymStorageClass_UNDEFINED_STATIC = 14,
COFF_SymStorageClass_ENUM_TAG = 15, COFF_SymStorageClass_ENUM_TAG = 15,
COFF_SymStorageClass_MEMBER_OF_ENUM = 16, COFF_SymStorageClass_MEMBER_OF_ENUM = 16,
COFF_SymStorageClass_REGISTER_PARAM = 17, COFF_SymStorageClass_REGISTER_PARAM = 17,
COFF_SymStorageClass_BIT_FIELD = 18, COFF_SymStorageClass_BIT_FIELD = 18,
COFF_SymStorageClass_BLOCK = 100, COFF_SymStorageClass_BLOCK = 100,
COFF_SymStorageClass_FUNCTION = 101, COFF_SymStorageClass_FUNCTION = 101,
COFF_SymStorageClass_END_OF_STRUCT = 102, COFF_SymStorageClass_END_OF_STRUCT = 102,
COFF_SymStorageClass_FILE = 103, COFF_SymStorageClass_FILE = 103,
COFF_SymStorageClass_SECTION = 104, COFF_SymStorageClass_SECTION = 104,
COFF_SymStorageClass_WEAK_EXTERNAL = 105, COFF_SymStorageClass_WEAK_EXTERNAL = 105,
COFF_SymStorageClass_CLR_TOKEN = 107, COFF_SymStorageClass_CLR_TOKEN = 107,
COFF_SymStorageClass_COUNT = 27 COFF_SymStorageClass_COUNT = 27
}; };
typedef U16 COFF_SymSecNumber; typedef U16 COFF_SymSecNumber;
enum enum
{ {
COFF_SymSecNumber_NUMBER_UNDEFINED = 0, COFF_SymSecNumber_NUMBER_UNDEFINED = 0,
COFF_SymSecNumber_ABSOLUTE = 0xffff, COFF_SymSecNumber_ABSOLUTE = 0xffff,
COFF_SymSecNumber_DEBUG = 0xfffe, COFF_SymSecNumber_DEBUG = 0xfffe,
COFF_SymSecNumber_COUNT = 3 COFF_SymSecNumber_COUNT = 3
}; };
typedef U8 COFF_SymDType; typedef U8 COFF_SymDType;
enum enum
{ {
COFF_SymDType_NULL = 0, COFF_SymDType_NULL = 0,
COFF_SymDType_PTR = 16, COFF_SymDType_PTR = 16,
COFF_SymDType_FUNC = 32, COFF_SymDType_FUNC = 32,
COFF_SymDType_ARRAY = 48, COFF_SymDType_ARRAY = 48,
COFF_SymDType_COUNT = 4 COFF_SymDType_COUNT = 4
}; };
typedef U32 COFF_WeakExtType; typedef U32 COFF_WeakExtType;
enum enum
{ {
COFF_WeakExtType_NOLIBRARY = 1, COFF_WeakExtType_NOLIBRARY = 1,
COFF_WeakExtType_SEARCH_LIBRARY = 2, COFF_WeakExtType_SEARCH_LIBRARY = 2,
COFF_WeakExtType_SEARCH_ALIAS = 3, COFF_WeakExtType_SEARCH_ALIAS = 3,
COFF_WeakExtType_COUNT = 3 COFF_WeakExtType_COUNT = 3
}; };
typedef U32 COFF_ImportHeaderType; typedef U32 COFF_ImportHeaderType;
enum enum
{ {
COFF_ImportHeaderType_CODE = 0, COFF_ImportHeaderType_CODE = 0,
COFF_ImportHeaderType_DATA = 1, COFF_ImportHeaderType_DATA = 1,
COFF_ImportHeaderType_CONST = 2, COFF_ImportHeaderType_CONST = 2,
COFF_ImportHeaderType_COUNT = 3 COFF_ImportHeaderType_COUNT = 3
}; };
typedef U32 COFF_ImportHeaderNameType; typedef U32 COFF_ImportHeaderNameType;
enum enum
{ {
COFF_ImportHeaderNameType_ORDINAL = 0, COFF_ImportHeaderNameType_ORDINAL = 0,
COFF_ImportHeaderNameType_NAME = 1, COFF_ImportHeaderNameType_NAME = 1,
COFF_ImportHeaderNameType_NAME_NOPREFIX = 2, COFF_ImportHeaderNameType_NAME_NOPREFIX = 2,
COFF_ImportHeaderNameType_UNDECORATE = 3, COFF_ImportHeaderNameType_UNDECORATE = 3,
COFF_ImportHeaderNameType_COUNT = 4 COFF_ImportHeaderNameType_COUNT = 4
}; };
#define COFF_IMPORT_HEADER_TYPE_MASK 0x03 #define COFF_IMPORT_HEADER_TYPE_MASK 0x03
#define COFF_IMPORT_HEADER_TYPE_SHIFT 0 #define COFF_IMPORT_HEADER_TYPE_SHIFT 0
#define COFF_IMPORT_HEADER_NAME_TYPE_MASK 0x1c #define COFF_IMPORT_HEADER_NAME_TYPE_MASK 0x1c
#define COFF_IMPORT_HEADER_NAME_TYPE_SHIFT 2 #define COFF_IMPORT_HEADER_NAME_TYPE_SHIFT 2
#define COFF_IMPORT_HEADER_GET_TYPE(x) (((x) & COFF_IMPORT_HEADER_TYPE_MASK) >> COFF_IMPORT_HEADER_TYPE_SHIFT) #define COFF_IMPORT_HEADER_GET_TYPE(x) (((x) & COFF_IMPORT_HEADER_TYPE_MASK) >> COFF_IMPORT_HEADER_TYPE_SHIFT)
#define COFF_IMPORT_HEADER_GET_NAME_TYPE(x) (((x) & COFF_IMPORT_HEADER_NAME_TYPE_MASK) >> COFF_IMPORT_HEADER_NAME_TYPE_SHIFT) #define COFF_IMPORT_HEADER_GET_NAME_TYPE(x) (((x) & COFF_IMPORT_HEADER_NAME_TYPE_MASK) >> COFF_IMPORT_HEADER_NAME_TYPE_SHIFT)
typedef struct COFF_ImportHeader typedef struct COFF_ImportHeader
{ {
U16 sig1; U16 sig1;
U16 sig2; U16 sig2;
U16 version; U16 version;
U16 machine; U16 machine;
COFF_TimeStamp time_stamp; COFF_TimeStamp time_stamp;
U32 data_size; U32 data_size;
U16 hint; U16 hint;
U16 type; U16 type;
U16 name_type; U16 name_type;
// type : 2 // type : 2
// name type : 3 // name type : 3
// reserved : 11 // reserved : 11
@@ -390,30 +377,18 @@ typedef struct COFF_ImportHeader
typedef U8 COFF_ComdatSelectType; typedef U8 COFF_ComdatSelectType;
enum enum
{ {
COFF_ComdatSelectType_NULL = 0, COFF_ComdatSelectType_NULL = 0, // Only one symbol is allowed to be in global symbol table, otherwise multiply defintion error is thrown.
// Only one symbol is allowed to be in global symbol table, otherwise multiply defintion error is thrown. COFF_ComdatSelectType_NODUPLICATES = 1, // Select any symbol, even if there are multiple definitions. (we default to first declaration)
COFF_ComdatSelectType_NODUPLICATES = 1, COFF_ComdatSelectType_ANY = 2, // Sections that symbols reference must match in size, otherwise multiply definition error is thrown.
// Select any symbol, even if there are multiple definitions. (we default to first declaration) COFF_ComdatSelectType_SAME_SIZE = 3, // Sections that symbols reference must have identical checksums, otherwise multiply defintion error is thrown.
COFF_ComdatSelectType_ANY = 2, COFF_ComdatSelectType_EXACT_MATCH = 4, // Symbols with associative type form a chain of sections are related to each other. (next link is indicated in COFF_SecDef in 'number')
// Sections that symbols reference must match in size, otherwise multiply definition error is thrown. COFF_ComdatSelectType_ASSOCIATIVE = 5, // Linker selects section with largest size.
COFF_ComdatSelectType_SAME_SIZE = 3, COFF_ComdatSelectType_LARGEST = 6,
// Sections that symbols reference must have identical checksums, otherwise multiply defintion error is thrown. COFF_ComdatSelectType_COUNT = 7
COFF_ComdatSelectType_EXACT_MATCH = 4,
// Symbols with associative type form a chain of sections are related to each other. (next link is indicated in COFF_SecDef in 'number')
COFF_ComdatSelectType_ASSOCIATIVE = 5,
// Linker selects section with largest size.
COFF_ComdatSelectType_LARGEST = 6,
COFF_ComdatSelectType_COUNT = 7
}; };
#define COFF_MIN_BIG_OBJ_VERSION 2 #define COFF_MIN_BIG_OBJ_VERSION 2
global U8 coff_big_obj_magic[] =
{
0xC7,0xA1,0xBA,0xD1,0xEE,0xBA,0xA9,0x4B,
0xAF,0x20,0xFA,0xF6,0x6A,0xA4,0xDC,0xB8,
};
typedef struct COFF_HeaderBigObj COFF_HeaderBigObj; typedef struct COFF_HeaderBigObj COFF_HeaderBigObj;
struct COFF_HeaderBigObj struct COFF_HeaderBigObj
{ {
@@ -422,7 +397,7 @@ struct COFF_HeaderBigObj
U16 version; U16 version;
U16 machine; U16 machine;
U32 time_stamp; U32 time_stamp;
U8 magic[16]; U8 magic[16];
U32 unused[4]; U32 unused[4];
U32 section_count; U32 section_count;
U32 pointer_to_symbol_table; U32 pointer_to_symbol_table;
@@ -454,8 +429,8 @@ typedef struct COFF_Symbol16 COFF_Symbol16;
struct COFF_Symbol16 struct COFF_Symbol16
{ {
COFF_SymbolName name; COFF_SymbolName name;
U32 value; U32 value;
U16 section_number; U16 section_number;
union union
{ {
struct struct
@@ -473,8 +448,8 @@ typedef struct COFF_Symbol32 COFF_Symbol32;
struct COFF_Symbol32 struct COFF_Symbol32
{ {
COFF_SymbolName name; COFF_SymbolName name;
U32 value; U32 value;
U32 section_number; U32 section_number;
union union
{ {
struct struct
@@ -494,11 +469,11 @@ struct COFF_Symbol32
// storage class: FUNCTION // storage class: FUNCTION
typedef struct COFF_SymbolFunc typedef struct COFF_SymbolFunc
{ {
U8 unused[4]; U8 unused[4];
U16 ln; U16 ln;
U8 unused2[2]; U8 unused2[2];
U32 ptr_to_next_func; U32 ptr_to_next_func;
U8 unused3[2]; U8 unused3[2];
} COFF_SymbolFunc; } COFF_SymbolFunc;
// storage class: WEAK_EXTERNAL // storage class: WEAK_EXTERNAL
@@ -506,7 +481,7 @@ typedef struct COFF_SymbolWeakExt
{ {
U32 tag_index; U32 tag_index;
U32 characteristics; U32 characteristics;
U8 unused[10]; U8 unused[10];
} COFF_SymbolWeakExt; } COFF_SymbolWeakExt;
typedef struct COFF_SymbolFile typedef struct COFF_SymbolFile
@@ -522,9 +497,10 @@ typedef struct COFF_SymbolSecDef
U16 number_of_relocations; U16 number_of_relocations;
U16 number_of_ln; U16 number_of_ln;
U32 check_sum; U32 check_sum;
U16 number; // one-based section index U16 number_lo; // one-based section index
U8 selection; U8 selection;
U8 unused[3]; U8 unused;
U16 number_hi;
} COFF_SymbolSecDef; } COFF_SymbolSecDef;
// specifies how section data should be modified when placed in the image file. // specifies how section data should be modified when placed in the image file.
@@ -584,7 +560,7 @@ typedef struct COFF_ResourceID_16
COFF_ResourceIDType type; COFF_ResourceIDType type;
union union
{ {
U16 number; U16 number;
String16 string; String16 string;
} u; } u;
} COFF_ResourceID_16; } COFF_ResourceID_16;
@@ -594,20 +570,21 @@ typedef struct COFF_ResourceID
COFF_ResourceIDType type; COFF_ResourceIDType type;
union union
{ {
U16 number; U16 number;
String8 string; String8 string;
} u; } u;
} COFF_ResourceID; } COFF_ResourceID;
typedef struct COFF_Resource typedef struct COFF_Resource
{ {
COFF_ResourceID type; COFF_ResourceID type;
COFF_ResourceID name; COFF_ResourceID name;
U16 language_id; U32 data_version;
U32 data_version;
U32 version;
COFF_ResourceMemoryFlags memory_flags; COFF_ResourceMemoryFlags memory_flags;
String8 data; U16 language_id;
U32 version;
U32 characteristics;
String8 data;
} COFF_Resource; } COFF_Resource;
typedef struct COFF_ResourceDataEntry typedef struct COFF_ResourceDataEntry
@@ -620,12 +597,12 @@ typedef struct COFF_ResourceDataEntry
typedef struct COFF_ResourceDirTable typedef struct COFF_ResourceDirTable
{ {
U32 characteristics; U32 characteristics;
COFF_TimeStamp time_stamp; COFF_TimeStamp time_stamp;
U16 major_version; U16 major_version;
U16 minor_version; U16 minor_version;
U16 name_entry_count; U16 name_entry_count;
U16 id_entry_count; U16 id_entry_count;
} COFF_ResourceDirTable; } COFF_ResourceDirTable;
#define COFF_RESOURCE_SUB_DIR_FLAG (1u << 31u) #define COFF_RESOURCE_SUB_DIR_FLAG (1u << 31u)
@@ -643,24 +620,19 @@ typedef struct COFF_ResourceDirEntry
//////////////////////////////// ////////////////////////////////
// !<arch>\n #define COFF_ARCHIVE_ALIGN 2
#define COFF_ARCHIVE_SIG 0x0A3E686372613C21ULL
// !<thin>\n
#define COFF_THIN_ARCHIVE_SIG 0xA3E6E6968743C21ULL
#define COFF_ARCHIVE_MAX_SHORT_NAME_SIZE 15 #define COFF_ARCHIVE_MAX_SHORT_NAME_SIZE 15
#define COFF_ARCHIVE_MEMBER_HEADER_SIZE 60
#define COFF_ARCHIVE_ALIGN 2
typedef struct COFF_ArchiveMemberHeader typedef struct COFF_ArchiveMemberHeader
{ {
String8 name; // padded to 16 bytes with spaces String8 name; // padded to 16 bytes with spaces
U32 date; // unix time U32 date; // unix time
U32 user_id; // unix artifact that does not have meaning on windows U32 user_id; // unix artifact that does not have meaning on windows
U32 group_id; // unix artifact that does not have meaning on windows U32 group_id; // unix artifact that does not have meaning on windows
String8 mode; // octal representation the members file mode String8 mode; // octal representation the members file mode
U32 size; // size of the member data, not including header U32 size; // size of the member data, not including header
B32 is_end_correct; // set to true if found correct signature after header B32 is_end_correct; // set to true if found correct signature after header
} COFF_ArchiveMemberHeader; } COFF_ArchiveMemberHeader;
//////////////////////////////// ////////////////////////////////
@@ -678,71 +650,61 @@ typedef U32 COFF_DataType;
typedef struct COFF_HeaderInfo typedef struct COFF_HeaderInfo
{ {
COFF_MachineType machine; COFF_MachineType machine;
U64 section_array_off; COFF_DataType type;
U64 section_count_no_null; U64 section_array_off;
U64 string_table_off; U64 section_count_no_null;
U64 symbol_size; U64 string_table_off;
U64 symbol_off; U64 symbol_size;
U64 symbol_count; U64 symbol_off;
U64 symbol_count;
} COFF_HeaderInfo; } COFF_HeaderInfo;
enum enum
{ {
// symbol has section and offset. COFF_SymbolValueInterp_REGULAR, // symbol has section and offset.
COFF_SymbolValueInterp_REGULAR, COFF_SymbolValueInterp_WEAK, // symbol is overridable
COFF_SymbolValueInterp_UNDEFINED, // symbol doesn't have a reference section.
// symbol is overridable COFF_SymbolValueInterp_COMMON, // symbol has no section but still has size.
COFF_SymbolValueInterp_WEAK, COFF_SymbolValueInterp_ABS, // symbol has an absolute (non-relocatable) value and is not an address.
COFF_SymbolValueInterp_DEBUG // symbol is used to provide general type of debugging information.
// symbol doesn't have a reference section.
COFF_SymbolValueInterp_UNDEFINED,
// symbol has no section but still has size.
COFF_SymbolValueInterp_COMMON,
// symbol has an absolute (non-relocatable) value and is not an address.
COFF_SymbolValueInterp_ABS,
// symbol is used to provide general type of debugging information.
COFF_SymbolValueInterp_DEBUG
}; };
typedef U32 COFF_SymbolValueInterpType; typedef U32 COFF_SymbolValueInterpType;
typedef struct COFF_Symbol16Node typedef struct COFF_Symbol16Node
{ {
struct COFF_Symbol16Node *next; struct COFF_Symbol16Node *next;
COFF_Symbol16 data; COFF_Symbol16 data;
} COFF_Symbol16Node; } COFF_Symbol16Node;
typedef struct COFF_Symbol16List typedef struct COFF_Symbol16List
{ {
U64 count; U64 count;
COFF_Symbol16Node *first; COFF_Symbol16Node *first;
COFF_Symbol16Node *last; COFF_Symbol16Node *last;
} COFF_Symbol16List; } COFF_Symbol16List;
typedef struct COFF_Symbol32Array typedef struct COFF_Symbol32Array
{ {
U64 count; U64 count;
COFF_Symbol32 *v; COFF_Symbol32 *v;
} COFF_Symbol32Array; } COFF_Symbol32Array;
typedef struct COFF_RelocNode typedef struct COFF_RelocNode
{ {
struct COFF_RelocNode *next; struct COFF_RelocNode *next;
COFF_Reloc data; COFF_Reloc data;
} COFF_RelocNode; } COFF_RelocNode;
typedef struct COFF_RelocList typedef struct COFF_RelocList
{ {
U64 count; U64 count;
COFF_RelocNode *first; COFF_RelocNode *first;
COFF_RelocNode *last; COFF_RelocNode *last;
} COFF_RelocList; } COFF_RelocList;
typedef struct COFF_RelocArray typedef struct COFF_RelocArray
{ {
U64 count; U64 count;
COFF_Reloc *v; COFF_Reloc *v;
} COFF_RelocArray; } COFF_RelocArray;
@@ -755,12 +717,12 @@ typedef struct COFF_RelocInfo
typedef struct COFF_ResourceNode typedef struct COFF_ResourceNode
{ {
struct COFF_ResourceNode *next; struct COFF_ResourceNode *next;
COFF_Resource data; COFF_Resource data;
} COFF_ResourceNode; } COFF_ResourceNode;
typedef struct COFF_ResourceList typedef struct COFF_ResourceList
{ {
U64 count; U64 count;
COFF_ResourceNode *first; COFF_ResourceNode *first;
COFF_ResourceNode *last; COFF_ResourceNode *last;
} COFF_ResourceList; } COFF_ResourceList;
@@ -770,21 +732,21 @@ typedef struct COFF_ResourceList
typedef struct COFF_ArchiveMember typedef struct COFF_ArchiveMember
{ {
COFF_ArchiveMemberHeader header; COFF_ArchiveMemberHeader header;
U64 offset; U64 offset;
String8 data; String8 data;
} COFF_ArchiveMember; } COFF_ArchiveMember;
typedef struct COFF_ArchiveFirstMember typedef struct COFF_ArchiveFirstMember
{ {
U32 symbol_count; U32 symbol_count;
String8 member_offsets; String8 member_offsets;
String8 string_table; String8 string_table;
} COFF_ArchiveFirstMember; } COFF_ArchiveFirstMember;
typedef struct COFF_ArchiveSecondMember typedef struct COFF_ArchiveSecondMember
{ {
U32 member_count; U32 member_count;
U32 symbol_count; U32 symbol_count;
String8 member_offsets; String8 member_offsets;
String8 symbol_indices; String8 symbol_indices;
String8 string_table; String8 string_table;
@@ -793,12 +755,12 @@ typedef struct COFF_ArchiveSecondMember
typedef struct COFF_ArchiveMemberNode typedef struct COFF_ArchiveMemberNode
{ {
struct COFF_ArchiveMemberNode *next; struct COFF_ArchiveMemberNode *next;
COFF_ArchiveMember data; COFF_ArchiveMember data;
} COFF_ArchiveMemberNode; } COFF_ArchiveMemberNode;
typedef struct COFF_ArchiveMemberList typedef struct COFF_ArchiveMemberList
{ {
U64 count; U64 count;
COFF_ArchiveMemberNode *first; COFF_ArchiveMemberNode *first;
COFF_ArchiveMemberNode *last; COFF_ArchiveMemberNode *last;
} COFF_ArchiveMemberList; } COFF_ArchiveMemberList;
@@ -812,14 +774,37 @@ typedef enum
typedef struct COFF_ArchiveParse typedef struct COFF_ArchiveParse
{ {
COFF_ArchiveFirstMember first_member; COFF_ArchiveFirstMember first_member;
COFF_ArchiveSecondMember second_member; COFF_ArchiveSecondMember second_member;
String8 long_names; String8 long_names;
} COFF_ArchiveParse; } COFF_ArchiveParse;
////////////////////////////////
typedef struct COFF_SectionHeaderArray
{
U64 count;
COFF_SectionHeader *v;
} COFF_SectionHeaderArray;
//////////////////////////////// ////////////////////////////////
//~ rjf: Globals //~ rjf: Globals
read_only global U8 coff_big_obj_magic[] =
{
0xC7,0xA1,0xBA,0xD1,0xEE,0xBA,0xA9,0x4B,
0xAF,0x20,0xFA,0xF6,0x6A,0xA4,0xDC,0xB8,
};
read_only global U8 g_coff_archive_sig[8] = "!<arch>\n";
read_only global U8 g_coff_thin_archive_sig[8] = "!<thin>\n";
read_only global U8 g_coff_res_magic[] =
{
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
read_only global COFF_SectionHeader coff_section_header_nil = {0}; read_only global COFF_SectionHeader coff_section_header_nil = {0};
//////////////////////////////// ////////////////////////////////
@@ -829,6 +814,7 @@ internal B32 coff_is_big_obj(String8 data);
internal B32 coff_is_obj(String8 data); internal B32 coff_is_obj(String8 data);
internal COFF_HeaderInfo coff_header_info_from_data(String8 data); internal COFF_HeaderInfo coff_header_info_from_data(String8 data);
internal U64 coff_align_size_from_section_flags(COFF_SectionFlags flags); internal U64 coff_align_size_from_section_flags(COFF_SectionFlags flags);
internal COFF_SectionFlags coff_section_flag_from_align_size(U64 align);
internal COFF_SymbolValueInterpType coff_interp_symbol(COFF_Symbol32 *symbol); internal COFF_SymbolValueInterpType coff_interp_symbol(COFF_Symbol32 *symbol);
internal U64 coff_foff_from_voff(COFF_SectionHeader *sections, U64 section_count, U64 voff); internal U64 coff_foff_from_voff(COFF_SectionHeader *sections, U64 section_count, U64 voff);
@@ -844,18 +830,47 @@ internal COFF_Symbol32Array coff_symbol_array_from_data(Arena *arena, String8 d
internal COFF_Symbol16Node * coff_symbol16_list_push(Arena *arena, COFF_Symbol16List *list, COFF_Symbol16 symbol); internal COFF_Symbol16Node * coff_symbol16_list_push(Arena *arena, COFF_Symbol16List *list, COFF_Symbol16 symbol);
internal COFF_RelocInfo coff_reloc_info_from_section_header(String8 data, COFF_SectionHeader *header); internal COFF_RelocInfo coff_reloc_info_from_section_header(String8 data, COFF_SectionHeader *header);
internal U64 coff_word_size_from_machine(COFF_MachineType machine); internal U64 coff_word_size_from_machine(COFF_MachineType machine);
internal U64 coff_default_exe_base_from_machine(COFF_MachineType machine);
internal U64 coff_default_dll_base_from_machine(COFF_MachineType machine);
internal String8 coff_make_import_lookup(Arena *arena, U16 hint, String8 name); internal String8 coff_make_import_lookup(Arena *arena, U16 hint, String8 name);
internal U32 coff_make_ordinal_32(U16 hint); internal U32 coff_make_ordinal_32(U16 hint);
internal U64 coff_make_ordinal_64(U16 hint); internal U64 coff_make_ordinal_64(U16 hint);
internal B32 coff_resource_id_is_equal(COFF_ResourceID a, COFF_ResourceID b); internal String8 coff_make_import_header_by_name(Arena *arena,
internal COFF_ResourceID coff_resource_id_copy(Arena *arena, COFF_ResourceID id); String8 dll_name,
internal COFF_ResourceID coff_convert_resource_id(Arena *arena, COFF_ResourceID_16 *id_16); COFF_MachineType machine,
internal U64 coff_read_resource_id(String8 res, U64 off, COFF_ResourceID_16 *id_out); COFF_TimeStamp time_stamp,
String8 name,
U16 hint,
COFF_ImportHeaderType type);
internal String8 coff_make_import_header_by_ordinal(Arena *arena,
String8 dll_name,
COFF_MachineType machine,
COFF_TimeStamp time_stamp,
U16 ordinal,
COFF_ImportHeaderType type);
////////////////////////////////
//~ Resources
internal String8 coff_resource_string_from_str16(Arena *arena, String16 string);
internal String8 coff_resource_string_from_str8(Arena *arena, String8 string);
internal String8 coff_resource_number_from_u16(Arena *arena, U16 number);
internal B32 coff_resource_id_is_equal(COFF_ResourceID a, COFF_ResourceID b);
internal COFF_ResourceID coff_utf8_resource_id_from_utf16(Arena *arena, COFF_ResourceID_16 *id_16);
internal U64 coff_read_resource_id_utf16(String8 res, U64 off, COFF_ResourceID_16 *id_out);
internal U64 coff_read_resource(String8 data, U64 off, Arena *arena, COFF_Resource *res_out); internal U64 coff_read_resource(String8 data, U64 off, Arena *arena, COFF_Resource *res_out);
internal COFF_ResourceList coff_resource_list_from_data(Arena *arena, String8 data); internal COFF_ResourceList coff_resource_list_from_data(Arena *arena, String8 data);
internal String8 coff_write_resource_id(Arena *arena, COFF_ResourceID id);
internal String8 coff_write_resource(Arena *arena, COFF_ResourceID type, COFF_ResourceID name, U32 data_version, COFF_ResourceMemoryFlags memory_flags, U16 language_id, U32 version, U32 characteristics, String8 data);
////////////////////////////////
internal COFF_DataType coff_data_type_from_data(String8 data); internal COFF_DataType coff_data_type_from_data(String8 data);
internal B32 coff_is_import(String8 data); internal B32 coff_is_import(String8 data);
internal B32 coff_is_archive(String8 data); internal B32 coff_is_archive(String8 data);
@@ -875,8 +890,15 @@ internal COFF_ArchiveParse coff_thin_archive_from_data(Arena *arena, String8 da
internal COFF_ArchiveType coff_archive_type_from_data(String8 data); internal COFF_ArchiveType coff_archive_type_from_data(String8 data);
internal COFF_ArchiveParse coff_archive_parse_from_data(Arena *arena, String8 data); internal COFF_ArchiveParse coff_archive_parse_from_data(Arena *arena, String8 data);
////////////////////////////////
// String <-> Enum
internal String8 coff_string_from_comdat_select_type(COFF_ComdatSelectType select); internal String8 coff_string_from_comdat_select_type(COFF_ComdatSelectType select);
internal String8 coff_string_from_machine_type(COFF_MachineType machine); internal String8 coff_string_from_machine_type(COFF_MachineType machine);
internal String8 coff_string_from_section_flags(Arena *arena, COFF_SectionFlags flags); internal String8 coff_string_from_section_flags(Arena *arena, COFF_SectionFlags flags);
internal String8 coff_string_from_import_header_type(COFF_ImportHeaderType type);
internal COFF_MachineType coff_machine_from_string(String8 string);
internal COFF_ImportHeaderType coff_import_header_type_from_string(String8 name);
#endif //COFF_H #endif //COFF_H
+29 -4
View File
@@ -2,7 +2,35 @@
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
//////////////////////////////// ////////////////////////////////
//~ rjf: Tables //~ rjf: Entity Kinds
@table(name display_string)
CTRL_EntityKindTable:
{
{Root "Root" }
{Machine "Machine" }
{Process "Process" }
{Thread "Thread" }
{Module "Module" }
{EntryPoint "Entry Point" }
{DebugInfoPath "Debug Info Path" }
}
@enum CTRL_EntityKind:
{
Null,
@expand(CTRL_EntityKindTable a) `$(a.name)`,
COUNT,
}
@data(String8) ctrl_entity_kind_display_string_table:
{
`{0}`,
@expand(CTRL_EntityKindTable a) `str8_lit_comp("$(a.display_name)")`
}
////////////////////////////////
//~ rjf: Exception Codes
@table(name lower_name code default display_string) @table(name lower_name code default display_string)
CTRL_ExceptionCodeKindTable: CTRL_ExceptionCodeKindTable:
@@ -46,9 +74,6 @@ CTRL_ExceptionCodeKindTable:
{Win32DirectXDebugLayer win32_directx_debug_layer 0x0000087a 1 "(Win32) DirectX Debug Layer" } {Win32DirectXDebugLayer win32_directx_debug_layer 0x0000087a 1 "(Win32) DirectX Debug Layer" }
} }
////////////////////////////////
//~ rjf: Generators
@enum CTRL_ExceptionCodeKind: @enum CTRL_ExceptionCodeKind:
{ {
Null, Null,
+1500 -682
View File
File diff suppressed because it is too large Load Diff
+438 -89
View File
@@ -13,46 +13,260 @@ typedef U64 CTRL_MachineID;
#define CTRL_MachineID_Local (1) #define CTRL_MachineID_Local (1)
//////////////////////////////// ////////////////////////////////
//~ rjf: Machine/Handle Pair Types //~ rjf: Meta Evaluation Types
typedef struct CTRL_MachineIDHandlePair CTRL_MachineIDHandlePair; //- rjf: auto-checkbox b32s
struct CTRL_MachineIDHandlePair
typedef struct CTRL_CheckB32 CTRL_CheckB32;
struct CTRL_CheckB32
{
B32 b32;
};
struct_members(CTRL_CheckB32)
{
member_lit_comp(CTRL_CheckB32, type(B32), b32),
};
struct_type(CTRL_CheckB32);
//- rjf: styled string types
ptr_type(CTRL_PlainString8__str_ptr_type, type(U8), .flags = TypeFlag_IsPlainText,.count_delimiter_name = str8_lit_comp("size"));
ptr_type(CTRL_CodeString8__str_ptr_type, type(U8), .flags = TypeFlag_IsCodeText, .count_delimiter_name = str8_lit_comp("size"));
ptr_type(CTRL_PathString8__str_ptr_type, type(U8), .flags = TypeFlag_IsPathText, .count_delimiter_name = str8_lit_comp("size"));
Member CTRL_PlainString8__members[] =
{
member_lit_comp(String8, &CTRL_PlainString8__str_ptr_type, str, .pretty_name = str8_lit_comp("Contents")),
member_lit_comp(String8, type(U64), size, .pretty_name = str8_lit_comp("Size")),
};
Member CTRL_CodeString8__members[] =
{
member_lit_comp(String8, &CTRL_CodeString8__str_ptr_type, str, .pretty_name = str8_lit_comp("Contents")),
member_lit_comp(String8, type(U64), size, .pretty_name = str8_lit_comp("Size")),
};
Member CTRL_PathString8__members[] =
{
member_lit_comp(String8, &CTRL_PathString8__str_ptr_type, str, .pretty_name = str8_lit_comp("Contents")),
member_lit_comp(String8, type(U64), size, .pretty_name = str8_lit_comp("Size")),
};
named_struct_type(CTRL_PlainString8, String8, .name = str8_lit_comp("string"));
named_struct_type(CTRL_CodeString8, String8, .name = str8_lit_comp("string"));
named_struct_type(CTRL_PathString8, String8, .name = str8_lit_comp("string"));
//- rjf: meta evaluation callstack types
typedef struct CTRL_MetaEvalFrame CTRL_MetaEvalFrame;
struct CTRL_MetaEvalFrame
{
U64 vaddr;
U64 inline_depth;
};
ptr_type(CTRL_MetaEvalFrame__vaddr_type, type(void), .flags = TypeFlag_IsExternal, .size = sizeof(U64));
struct_members(CTRL_MetaEvalFrame)
{
member_lit_comp(CTRL_MetaEvalFrame, &CTRL_MetaEvalFrame__vaddr_type, vaddr),
member_lit_comp(CTRL_MetaEvalFrame, type(U64), inline_depth),
};
struct_type(CTRL_MetaEvalFrame, .name = str8_lit_comp("callstack_frame"));
typedef struct CTRL_MetaEvalFrameArray CTRL_MetaEvalFrameArray;
struct CTRL_MetaEvalFrameArray
{
U64 count;
CTRL_MetaEvalFrame *v;
};
ptr_type(CTRL_MetaEvalFrameArray__v_ptr_type, type(CTRL_MetaEvalFrame), .count_delimiter_name = str8_lit_comp("count"));
struct_members(CTRL_MetaEvalFrameArray)
{
member_lit_comp(CTRL_MetaEvalFrameArray, type(U64), count, .pretty_name = str8_lit_comp("Frame Count")),
{str8_lit_comp("v"), str8_lit_comp("Frame Addresses"), &CTRL_MetaEvalFrameArray__v_ptr_type, OffsetOf(CTRL_MetaEvalFrameArray, v)},
};
struct_type(CTRL_MetaEvalFrameArray, .name = str8_lit_comp("callstack_frames"));
//- rjf: meta evaluation instance types
typedef struct CTRL_MetaEval CTRL_MetaEval;
struct CTRL_MetaEval
{
#define CTRL_MetaEval_MemberXList \
X(B32, enabled, "Enabled")\
X(B32, frozen, "Frozen")\
X(U64, hit_count, "Hit Count")\
X(U64, id, "ID")\
X(Rng1U64, vaddr_range, "Address Range")\
X(U32, color, "Color")\
X(CTRL_CheckB32, debug_subprocesses,"Debug Subprocesses")\
Y(String8, type(CTRL_CodeString8), label, "Label")\
Y(String8, type(CTRL_PathString8), exe, "Executable Path")\
Y(String8, type(CTRL_PathString8), dbg, "Debug Info Path")\
Y(String8, type(CTRL_PlainString8), args, "Arguments")\
Y(String8, type(CTRL_PathString8), working_directory, "Working Directory")\
Y(String8, type(CTRL_CodeString8), entry_point, "Custom Entry Point")\
Y(String8, type(CTRL_PathString8), stdout_path, "Standard Output Path")\
Y(String8, type(CTRL_PathString8), stderr_path, "Standard Error Path")\
Y(String8, type(CTRL_PathString8), stdin_path, "Standard Input Path")\
Y(String8, type(CTRL_PathString8), source_location, "Source Location")\
Y(String8, type(CTRL_CodeString8), function_location, "Function Location")\
Y(String8, type(CTRL_CodeString8), address_location, "Address Location")\
Y(String8, type(CTRL_PathString8), source_path, "Source Path")\
Y(String8, type(CTRL_PathString8), destination_path, "Destination Path")\
Y(String8, type(CTRL_CodeString8), type, "Type")\
Y(String8, type(CTRL_CodeString8), view_rule, "View Rule")\
Y(String8, type(CTRL_CodeString8), condition, "Condition")\
X(CTRL_MetaEvalFrameArray, callstack, "Call Stack")
#define X(T, name, pretty_name) T name;
#define Y(T, ti, name, pretty_name) T name;
CTRL_MetaEval_MemberXList
#undef X
#undef Y
};
struct_members(CTRL_MetaEval)
{
#define X(T, name, pretty_name_) member_lit_comp(CTRL_MetaEval, type(T), name, .pretty_name = str8_lit_comp(pretty_name_)),
#define Y(T, ti, name, pretty_name_) member_lit_comp(CTRL_MetaEval, (ti), name, .pretty_name = str8_lit_comp(pretty_name_)),
CTRL_MetaEval_MemberXList
#undef X
#undef Y
};
struct_type(CTRL_MetaEval);
//- rjf: filters on main meta evaluation bundle
struct_members(CTRL_BreakpointMetaEval)
{
member_lit_comp(CTRL_MetaEval, type(B32), enabled, .pretty_name = str8_lit_comp("Enabled")),
member_lit_comp(CTRL_MetaEval, type(U32), color, .pretty_name = str8_lit_comp("Color")),
member_lit_comp(CTRL_MetaEval, type(U64), hit_count, .pretty_name = str8_lit_comp("Hit Count")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Label")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), condition, .pretty_name = str8_lit_comp("Condition")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), source_location, .pretty_name = str8_lit_comp("Source Location")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), function_location, .pretty_name = str8_lit_comp("Function Location")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), address_location, .pretty_name = str8_lit_comp("Address Location")),
};
struct_members(CTRL_TargetMetaEval)
{
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Label")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), exe, .pretty_name = str8_lit_comp("Executable")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PlainString8),args, .pretty_name = str8_lit_comp("Arguments")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), working_directory, .pretty_name = str8_lit_comp("Working Directory")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), entry_point, .pretty_name = str8_lit_comp("Custom Entry Point")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), stdout_path, .pretty_name = str8_lit_comp("Standard Output Path")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), stderr_path, .pretty_name = str8_lit_comp("Standard Error Path")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), stdin_path, .pretty_name = str8_lit_comp("Standard Input Path")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CheckB32), debug_subprocesses, .pretty_name = str8_lit_comp("Debug Subprocesses")),
};
struct_members(CTRL_PinMetaEval)
{
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Expression")),
member_lit_comp(CTRL_MetaEval, type(U32), color, .pretty_name = str8_lit_comp("Color")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), source_location, .pretty_name = str8_lit_comp("Source Location")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), address_location, .pretty_name = str8_lit_comp("Address Location")),
};
struct_members(CTRL_FilePathMapMetaEval)
{
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), source_path, .pretty_name = str8_lit_comp("Source Path")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), destination_path, .pretty_name = str8_lit_comp("Destination Path")),
};
struct_members(CTRL_AutoViewRuleMetaEval)
{
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), type, .pretty_name = str8_lit_comp("Type")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), view_rule, .pretty_name = str8_lit_comp("View Rule")),
};
struct_members(CTRL_MachineMetaEval)
{
member_lit_comp(CTRL_MetaEval, type(B32), frozen, .pretty_name = str8_lit_comp("Frozen")),
member_lit_comp(CTRL_MetaEval, type(U32), color, .pretty_name = str8_lit_comp("Color")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Name")),
};
struct_members(CTRL_ProcessMetaEval)
{
member_lit_comp(CTRL_MetaEval, type(B32), frozen, .pretty_name = str8_lit_comp("Frozen")),
member_lit_comp(CTRL_MetaEval, type(U32), color, .pretty_name = str8_lit_comp("Color")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Name")),
member_lit_comp(CTRL_MetaEval, type(U64), id, .pretty_name = str8_lit_comp("ID")),
};
struct_members(CTRL_ModuleMetaEval)
{
member_lit_comp(CTRL_MetaEval, type(U32), color, .pretty_name = str8_lit_comp("Color")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Name")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), exe, .pretty_name = str8_lit_comp("Executable Path")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), dbg, .pretty_name = str8_lit_comp("Debug Info Path")),
member_lit_comp(CTRL_MetaEval, type(Rng1U64), vaddr_range, .pretty_name = str8_lit_comp("Address Range")),
};
struct_members(CTRL_ThreadMetaEval)
{
member_lit_comp(CTRL_MetaEval, type(B32), frozen, .pretty_name = str8_lit_comp("Frozen")),
member_lit_comp(CTRL_MetaEval, type(U32), color, .pretty_name = str8_lit_comp("Color")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Name")),
member_lit_comp(CTRL_MetaEval, type(U64), id, .pretty_name = str8_lit_comp("ID")),
member_lit_comp(CTRL_MetaEval, type(CTRL_MetaEvalFrameArray), callstack, .pretty_name = str8_lit_comp("Call Stack")),
};
named_struct_type(CTRL_BreakpointMetaEval, CTRL_MetaEval, .name = str8_lit_comp("breakpoint"));
named_struct_type(CTRL_TargetMetaEval, CTRL_MetaEval, .name = str8_lit_comp("target"));
named_struct_type(CTRL_PinMetaEval, CTRL_MetaEval, .name = str8_lit_comp("pin"));
named_struct_type(CTRL_FilePathMapMetaEval, CTRL_MetaEval, .name = str8_lit_comp("file_path_map"));
named_struct_type(CTRL_AutoViewRuleMetaEval,CTRL_MetaEval, .name = str8_lit_comp("auto_view_rule"));
named_struct_type(CTRL_MachineMetaEval, CTRL_MetaEval, .name = str8_lit_comp("machine"));
named_struct_type(CTRL_ProcessMetaEval, CTRL_MetaEval, .name = str8_lit_comp("process"));
named_struct_type(CTRL_ModuleMetaEval, CTRL_MetaEval, .name = str8_lit_comp("module"));
named_struct_type(CTRL_ThreadMetaEval, CTRL_MetaEval, .name = str8_lit_comp("thread"));
//- rjf: meta evaluation array
typedef struct CTRL_MetaEvalArray CTRL_MetaEvalArray;
struct CTRL_MetaEvalArray
{
CTRL_MetaEval *v;
U64 count;
};
ptr_type(CTRL_MetaEvalArray__v_ptr_type, type(CTRL_BreakpointMetaEval), .count_delimiter_name = str8_lit_comp("count"));
struct_members(CTRL_MetaEvalArray)
{
{str8_lit_comp("v"), {0}, &CTRL_MetaEvalArray__v_ptr_type, OffsetOf(CTRL_MetaEvalArray, v)},
member_lit_comp(CTRL_MetaEvalArray, type(U64), count),
};
struct_type(CTRL_MetaEvalArray);
////////////////////////////////
//~ rjf: Entity Handle Types
typedef struct CTRL_Handle CTRL_Handle;
struct CTRL_Handle
{ {
CTRL_MachineID machine_id; CTRL_MachineID machine_id;
DMN_Handle handle; DMN_Handle dmn_handle;
}; };
typedef struct CTRL_MachineIDHandlePairNode CTRL_MachineIDHandlePairNode; typedef struct CTRL_HandleNode CTRL_HandleNode;
struct CTRL_MachineIDHandlePairNode struct CTRL_HandleNode
{ {
CTRL_MachineIDHandlePairNode *next; CTRL_HandleNode *next;
CTRL_MachineIDHandlePair v; CTRL_Handle v;
}; };
typedef struct CTRL_MachineIDHandlePairList CTRL_MachineIDHandlePairList; typedef struct CTRL_HandleList CTRL_HandleList;
struct CTRL_MachineIDHandlePairList struct CTRL_HandleList
{ {
CTRL_MachineIDHandlePairNode *first; CTRL_HandleNode *first;
CTRL_MachineIDHandlePairNode *last; CTRL_HandleNode *last;
U64 count; U64 count;
}; };
//////////////////////////////// ////////////////////////////////
//~ rjf: Entity Types //~ rjf: Generated Code
typedef enum CTRL_EntityKind #include "generated/ctrl.meta.h"
{
CTRL_EntityKind_Null, ////////////////////////////////
CTRL_EntityKind_Root, //~ rjf: Entity Types
CTRL_EntityKind_Machine,
CTRL_EntityKind_Process,
CTRL_EntityKind_Thread,
CTRL_EntityKind_Module,
CTRL_EntityKind_EntryPoint,
CTRL_EntityKind_DebugInfoPath,
CTRL_EntityKind_COUNT
}
CTRL_EntityKind;
typedef struct CTRL_Entity CTRL_Entity; typedef struct CTRL_Entity CTRL_Entity;
struct CTRL_Entity struct CTRL_Entity
@@ -63,15 +277,47 @@ struct CTRL_Entity
CTRL_Entity *prev; CTRL_Entity *prev;
CTRL_Entity *parent; CTRL_Entity *parent;
CTRL_EntityKind kind; CTRL_EntityKind kind;
Architecture arch; Arch arch;
CTRL_MachineID machine_id; B32 is_frozen;
DMN_Handle handle; U32 rgba;
CTRL_Handle handle;
U64 id; U64 id;
Rng1U64 vaddr_range; Rng1U64 vaddr_range;
U64 stack_base;
U64 timestamp; U64 timestamp;
String8 string; String8 string;
}; };
typedef struct CTRL_EntityNode CTRL_EntityNode;
struct CTRL_EntityNode
{
CTRL_EntityNode *next;
CTRL_Entity *v;
};
typedef struct CTRL_EntityList CTRL_EntityList;
struct CTRL_EntityList
{
CTRL_EntityNode *first;
CTRL_EntityNode *last;
U64 count;
};
typedef struct CTRL_EntityArray CTRL_EntityArray;
struct CTRL_EntityArray
{
CTRL_Entity **v;
U64 count;
};
typedef struct CTRL_EntityRec CTRL_EntityRec;
struct CTRL_EntityRec
{
CTRL_Entity *next;
S32 push_count;
S64 pop_count;
};
typedef struct CTRL_EntityHashNode CTRL_EntityHashNode; typedef struct CTRL_EntityHashNode CTRL_EntityHashNode;
struct CTRL_EntityHashNode struct CTRL_EntityHashNode
{ {
@@ -104,6 +350,11 @@ struct CTRL_EntityStore
CTRL_EntityHashNode *hash_node_free; CTRL_EntityHashNode *hash_node_free;
U64 hash_slots_count; U64 hash_slots_count;
CTRL_EntityStringChunkNode *free_string_chunks[8]; CTRL_EntityStringChunkNode *free_string_chunks[8];
U64 entity_kind_counts[CTRL_EntityKind_COUNT];
Arena *entity_kind_lists_arenas[CTRL_EntityKind_COUNT];
U64 entity_kind_lists_gens[CTRL_EntityKind_COUNT];
U64 entity_kind_alloc_gens[CTRL_EntityKind_COUNT];
CTRL_EntityList entity_kind_lists[CTRL_EntityKind_COUNT];
}; };
//////////////////////////////// ////////////////////////////////
@@ -150,6 +401,37 @@ struct CTRL_Unwind
CTRL_UnwindFlags flags; CTRL_UnwindFlags flags;
}; };
////////////////////////////////
//~ rjf: Call Stack Types
typedef struct CTRL_CallStackInlineFrame CTRL_CallStackInlineFrame;
struct CTRL_CallStackInlineFrame
{
CTRL_CallStackInlineFrame *next;
CTRL_CallStackInlineFrame *prev;
RDI_InlineSite *inline_site;
};
typedef struct CTRL_CallStackFrame CTRL_CallStackFrame;
struct CTRL_CallStackFrame
{
CTRL_CallStackInlineFrame *first_inline_frame;
CTRL_CallStackInlineFrame *last_inline_frame;
U64 inline_frame_count;
void *regs;
RDI_Parsed *rdi;
RDI_Procedure *procedure;
};
typedef struct CTRL_CallStack CTRL_CallStack;
struct CTRL_CallStack
{
CTRL_CallStackFrame *frames;
U64 concrete_frame_count;
U64 inline_frame_count;
U64 total_frame_count;
};
//////////////////////////////// ////////////////////////////////
//~ rjf: Trap Types //~ rjf: Trap Types
@@ -199,6 +481,7 @@ struct CTRL_Spoof
typedef enum CTRL_UserBreakpointKind typedef enum CTRL_UserBreakpointKind
{ {
CTRL_UserBreakpointKind_Null,
CTRL_UserBreakpointKind_FileNameAndLineColNumber, CTRL_UserBreakpointKind_FileNameAndLineColNumber,
CTRL_UserBreakpointKind_SymbolNameAndOffset, CTRL_UserBreakpointKind_SymbolNameAndOffset,
CTRL_UserBreakpointKind_VirtualAddress, CTRL_UserBreakpointKind_VirtualAddress,
@@ -232,9 +515,14 @@ struct CTRL_UserBreakpointList
}; };
//////////////////////////////// ////////////////////////////////
//~ rjf: Generated Code //~ rjf: Evaluation Spaces
#include "generated/ctrl.meta.h" typedef U64 CTRL_EvalSpaceKind;
enum
{
CTRL_EvalSpaceKind_Entity = E_SpaceKind_FirstUserDefined,
CTRL_EvalSpaceKind_Meta,
};
//////////////////////////////// ////////////////////////////////
//~ rjf: Message Types //~ rjf: Message Types
@@ -245,11 +533,14 @@ typedef enum CTRL_MsgKind
CTRL_MsgKind_Launch, CTRL_MsgKind_Launch,
CTRL_MsgKind_Attach, CTRL_MsgKind_Attach,
CTRL_MsgKind_Kill, CTRL_MsgKind_Kill,
CTRL_MsgKind_KillAll,
CTRL_MsgKind_Detach, CTRL_MsgKind_Detach,
CTRL_MsgKind_Run, CTRL_MsgKind_Run,
CTRL_MsgKind_SingleStep, CTRL_MsgKind_SingleStep,
CTRL_MsgKind_SetUserEntryPoints, CTRL_MsgKind_SetUserEntryPoints,
CTRL_MsgKind_SetModuleDebugInfoPath, CTRL_MsgKind_SetModuleDebugInfoPath,
CTRL_MsgKind_FreezeThread,
CTRL_MsgKind_ThawThread,
CTRL_MsgKind_COUNT, CTRL_MsgKind_COUNT,
} }
CTRL_MsgKind; CTRL_MsgKind;
@@ -266,21 +557,23 @@ struct CTRL_Msg
CTRL_MsgKind kind; CTRL_MsgKind kind;
CTRL_RunFlags run_flags; CTRL_RunFlags run_flags;
CTRL_MsgID msg_id; CTRL_MsgID msg_id;
CTRL_MachineID machine_id; CTRL_Handle entity;
DMN_Handle entity; CTRL_Handle parent;
DMN_Handle parent;
U32 entity_id; U32 entity_id;
U32 exit_code; U32 exit_code;
B32 env_inherit; B32 env_inherit;
B32 debug_subprocesses;
U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64]; U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64];
String8 path; String8 path;
String8List entry_points; String8List entry_points;
String8List cmd_line_string_list; String8List cmd_line_string_list;
String8List env_string_list; String8List env_string_list;
String8 stdout_path;
String8 stderr_path;
String8 stdin_path;
CTRL_TrapList traps; CTRL_TrapList traps;
CTRL_UserBreakpointList user_bps; CTRL_UserBreakpointList user_bps;
CTRL_MachineIDHandlePairList freeze_state_threads; // NOTE(rjf): can be frozen or unfrozen, depending on `freeze_state_is_frozen` CTRL_MetaEvalArray meta_evals;
B32 freeze_state_is_frozen;
}; };
typedef struct CTRL_MsgNode CTRL_MsgNode; typedef struct CTRL_MsgNode CTRL_MsgNode;
@@ -318,12 +611,17 @@ typedef enum CTRL_EventKind
CTRL_EventKind_EndThread, CTRL_EventKind_EndThread,
CTRL_EventKind_EndModule, CTRL_EventKind_EndModule,
//- rjf: thread freeze state changes
CTRL_EventKind_ThreadFrozen,
CTRL_EventKind_ThreadThawed,
//- rjf: debug info changes //- rjf: debug info changes
CTRL_EventKind_ModuleDebugInfoPathChange, CTRL_EventKind_ModuleDebugInfoPathChange,
//- rjf: debug strings //- rjf: debug strings / decorations
CTRL_EventKind_DebugString, CTRL_EventKind_DebugString,
CTRL_EventKind_ThreadName, CTRL_EventKind_ThreadName,
CTRL_EventKind_ThreadColor,
//- rjf: memory //- rjf: memory
CTRL_EventKind_MemReserve, CTRL_EventKind_MemReserve,
@@ -367,10 +665,9 @@ struct CTRL_Event
CTRL_EventCause cause; CTRL_EventCause cause;
CTRL_ExceptionKind exception_kind; CTRL_ExceptionKind exception_kind;
CTRL_MsgID msg_id; CTRL_MsgID msg_id;
CTRL_MachineID machine_id; CTRL_Handle entity;
DMN_Handle entity; CTRL_Handle parent;
DMN_Handle parent; Arch arch;
Architecture arch;
U64 u64_code; U64 u64_code;
U32 entity_id; U32 entity_id;
Rng1U64 vaddr_rng; Rng1U64 vaddr_rng;
@@ -379,6 +676,7 @@ struct CTRL_Event
U64 tls_root; U64 tls_root;
U64 timestamp; U64 timestamp;
U32 exception_code; U32 exception_code;
U32 rgba;
String8 string; String8 string;
}; };
@@ -426,8 +724,7 @@ struct CTRL_ProcessMemoryCacheNode
CTRL_ProcessMemoryCacheNode *next; CTRL_ProcessMemoryCacheNode *next;
CTRL_ProcessMemoryCacheNode *prev; CTRL_ProcessMemoryCacheNode *prev;
Arena *arena; Arena *arena;
CTRL_MachineID machine_id; CTRL_Handle handle;
DMN_Handle process;
U64 range_hash_slots_count; U64 range_hash_slots_count;
CTRL_ProcessMemoryRangeHashSlot *range_hash_slots; CTRL_ProcessMemoryRangeHashSlot *range_hash_slots;
}; };
@@ -474,8 +771,7 @@ struct CTRL_ThreadRegCacheNode
{ {
CTRL_ThreadRegCacheNode *next; CTRL_ThreadRegCacheNode *next;
CTRL_ThreadRegCacheNode *prev; CTRL_ThreadRegCacheNode *prev;
CTRL_MachineID machine_id; CTRL_Handle handle;
DMN_Handle thread;
U64 block_size; U64 block_size;
void *block; void *block;
U64 reg_gen; U64 reg_gen;
@@ -512,8 +808,7 @@ struct CTRL_ModuleImageInfoCacheNode
{ {
CTRL_ModuleImageInfoCacheNode *next; CTRL_ModuleImageInfoCacheNode *next;
CTRL_ModuleImageInfoCacheNode *prev; CTRL_ModuleImageInfoCacheNode *prev;
CTRL_MachineID machine_id; CTRL_Handle module;
DMN_Handle module;
Arena *arena; Arena *arena;
PE_IntelPdata *pdatas; PE_IntelPdata *pdatas;
U64 pdatas_count; U64 pdatas_count;
@@ -545,6 +840,23 @@ struct CTRL_ModuleImageInfoCache
CTRL_ModuleImageInfoCacheStripe *stripes; CTRL_ModuleImageInfoCacheStripe *stripes;
}; };
////////////////////////////////
//~ rjf: Touched Debug Info Directory Cache
typedef struct CTRL_DbgDirNode CTRL_DbgDirNode;
struct CTRL_DbgDirNode
{
CTRL_DbgDirNode *first;
CTRL_DbgDirNode *last;
CTRL_DbgDirNode *next;
CTRL_DbgDirNode *prev;
CTRL_DbgDirNode *parent;
String8 name;
U64 search_count;
U64 child_count;
U64 module_direct_count;
};
//////////////////////////////// ////////////////////////////////
//~ rjf: Wakeup Hook Function Types //~ rjf: Wakeup Hook Function Types
@@ -561,8 +873,8 @@ struct CTRL_State
CTRL_WakeupFunctionType *wakeup_hook; CTRL_WakeupFunctionType *wakeup_hook;
// rjf: name -> register/alias hash tables for eval // rjf: name -> register/alias hash tables for eval
EVAL_String2NumMap arch_string2reg_tables[Architecture_COUNT]; E_String2NumMap arch_string2reg_tables[Arch_COUNT];
EVAL_String2NumMap arch_string2alias_tables[Architecture_COUNT]; E_String2NumMap arch_string2alias_tables[Arch_COUNT];
// rjf: caches // rjf: caches
CTRL_ProcessMemoryCache process_memory_cache; CTRL_ProcessMemoryCache process_memory_cache;
@@ -597,8 +909,12 @@ struct CTRL_State
DMN_EventNode *free_dmn_event_node; DMN_EventNode *free_dmn_event_node;
Arena *user_entry_point_arena; Arena *user_entry_point_arena;
String8List user_entry_points; String8List user_entry_points;
Arena *user_meta_eval_arena;
CTRL_MetaEvalArray user_meta_evals;
U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64]; U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64];
U64 process_counter; U64 process_counter;
Arena *dbg_dir_arena;
CTRL_DbgDirNode *dbg_dir_root;
// rjf: user -> memstream ring buffer // rjf: user -> memstream ring buffer
U64 u2ms_ring_size; U64 u2ms_ring_size;
@@ -607,10 +923,6 @@ struct CTRL_State
U64 u2ms_ring_read_pos; U64 u2ms_ring_read_pos;
OS_Handle u2ms_ring_mutex; OS_Handle u2ms_ring_mutex;
OS_Handle u2ms_ring_cv; OS_Handle u2ms_ring_cv;
// rjf: memory stream threads
U64 ms_thread_count;
OS_Handle *ms_threads;
}; };
//////////////////////////////// ////////////////////////////////
@@ -635,16 +947,19 @@ read_only global CTRL_Entity ctrl_entity_nil =
//~ rjf: Basic Type Functions //~ rjf: Basic Type Functions
internal U64 ctrl_hash_from_string(String8 string); internal U64 ctrl_hash_from_string(String8 string);
internal U64 ctrl_hash_from_machine_id_handle(CTRL_MachineID machine_id, DMN_Handle handle); internal U64 ctrl_hash_from_handle(CTRL_Handle handle);
internal CTRL_EventCause ctrl_event_cause_from_dmn_event_kind(DMN_EventKind event_kind); internal CTRL_EventCause ctrl_event_cause_from_dmn_event_kind(DMN_EventKind event_kind);
internal String8 ctrl_string_from_event_kind(CTRL_EventKind kind); internal String8 ctrl_string_from_event_kind(CTRL_EventKind kind);
internal String8 ctrl_string_from_msg_kind(CTRL_MsgKind kind); internal String8 ctrl_string_from_msg_kind(CTRL_MsgKind kind);
//////////////////////////////// ////////////////////////////////
//~ rjf: Machine/Handle Pair Type Functions //~ rjf: Handle Type Functions
internal void ctrl_machine_id_handle_pair_list_push(Arena *arena, CTRL_MachineIDHandlePairList *list, CTRL_MachineIDHandlePair *pair); internal CTRL_Handle ctrl_handle_zero(void);
internal CTRL_MachineIDHandlePairList ctrl_machine_id_handle_pair_list_copy(Arena *arena, CTRL_MachineIDHandlePairList *src); internal CTRL_Handle ctrl_handle_make(CTRL_MachineID machine_id, DMN_Handle dmn_handle);
internal B32 ctrl_handle_match(CTRL_Handle a, CTRL_Handle b);
internal void ctrl_handle_list_push(Arena *arena, CTRL_HandleList *list, CTRL_Handle *pair);
internal CTRL_HandleList ctrl_handle_list_copy(Arena *arena, CTRL_HandleList *src);
//////////////////////////////// ////////////////////////////////
//~ rjf: Trap Type Functions //~ rjf: Trap Type Functions
@@ -666,6 +981,8 @@ internal void ctrl_msg_deep_copy(Arena *arena, CTRL_Msg *dst, CTRL_Msg *src);
//- rjf: list building //- rjf: list building
internal CTRL_Msg *ctrl_msg_list_push(Arena *arena, CTRL_MsgList *list); internal CTRL_Msg *ctrl_msg_list_push(Arena *arena, CTRL_MsgList *list);
internal CTRL_MsgList ctrl_msg_list_deep_copy(Arena *arena, CTRL_MsgList *src);
internal void ctrl_msg_list_concat_in_place(CTRL_MsgList *dst, CTRL_MsgList *src);
//- rjf: serialization //- rjf: serialization
internal String8 ctrl_serialized_string_from_msg_list(Arena *arena, CTRL_MsgList *msgs); internal String8 ctrl_serialized_string_from_msg_list(Arena *arena, CTRL_MsgList *msgs);
@@ -685,6 +1002,14 @@ internal CTRL_Event ctrl_event_from_serialized_string(Arena *arena, String8 stri
//////////////////////////////// ////////////////////////////////
//~ rjf: Entity Type Functions //~ rjf: Entity Type Functions
//- rjf: entity list data structures
internal void ctrl_entity_list_push(Arena *arena, CTRL_EntityList *list, CTRL_Entity *entity);
internal CTRL_EntityList ctrl_entity_list_from_handle_list(Arena *arena, CTRL_EntityStore *store, CTRL_HandleList *list);
#define ctrl_entity_list_first(list) ((list)->first ? (list)->first->v : &ctrl_entity_nil)
//- rjf: entity array data structure
internal CTRL_EntityArray ctrl_entity_array_from_list(Arena *arena, CTRL_EntityList *list);
//- rjf: cache creation/destruction //- rjf: cache creation/destruction
internal CTRL_EntityStore *ctrl_entity_store_alloc(void); internal CTRL_EntityStore *ctrl_entity_store_alloc(void);
internal void ctrl_entity_store_release(CTRL_EntityStore *store); internal void ctrl_entity_store_release(CTRL_EntityStore *store);
@@ -695,15 +1020,32 @@ internal String8 ctrl_entity_string_alloc(CTRL_EntityStore *store, String8 strin
internal void ctrl_entity_string_release(CTRL_EntityStore *store, String8 string); internal void ctrl_entity_string_release(CTRL_EntityStore *store, String8 string);
//- rjf: entity construction/deletion //- rjf: entity construction/deletion
internal CTRL_Entity *ctrl_entity_alloc(CTRL_EntityStore *store, CTRL_Entity *parent, CTRL_EntityKind kind, Architecture arch, CTRL_MachineID machine_id, DMN_Handle handle, U64 id); internal CTRL_Entity *ctrl_entity_alloc(CTRL_EntityStore *store, CTRL_Entity *parent, CTRL_EntityKind kind, Arch arch, CTRL_Handle handle, U64 id);
internal void ctrl_entity_release(CTRL_EntityStore *store, CTRL_Entity *entity); internal void ctrl_entity_release(CTRL_EntityStore *store, CTRL_Entity *entity);
//- rjf: entity equipment //- rjf: entity equipment
internal void ctrl_entity_equip_string(CTRL_EntityStore *store, CTRL_Entity *entity, String8 string); internal void ctrl_entity_equip_string(CTRL_EntityStore *store, CTRL_Entity *entity, String8 string);
//- rjf: entity store lookups //- rjf: entity store lookups
internal CTRL_Entity *ctrl_entity_from_machine_id_handle(CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle handle); internal CTRL_Entity *ctrl_entity_from_handle(CTRL_EntityStore *store, CTRL_Handle handle);
internal CTRL_Entity *ctrl_entity_child_from_kind(CTRL_Entity *parent, CTRL_EntityKind kind); internal CTRL_Entity *ctrl_entity_child_from_kind(CTRL_Entity *parent, CTRL_EntityKind kind);
internal CTRL_Entity *ctrl_entity_ancestor_from_kind(CTRL_Entity *entity, CTRL_EntityKind kind);
internal CTRL_Entity *ctrl_process_from_entity(CTRL_Entity *entity);
internal CTRL_Entity *ctrl_module_from_process_vaddr(CTRL_Entity *process, U64 vaddr);
internal DI_Key ctrl_dbgi_key_from_module(CTRL_Entity *module);
internal CTRL_EntityList ctrl_modules_from_dbgi_key(Arena *arena, CTRL_EntityStore *store, DI_Key *dbgi_key);
internal CTRL_Entity *ctrl_module_from_thread_candidates(CTRL_EntityStore *store, CTRL_Entity *thread, CTRL_EntityList *candidates);
internal CTRL_EntityList ctrl_entity_list_from_kind(CTRL_EntityStore *store, CTRL_EntityKind kind);
internal U64 ctrl_vaddr_from_voff(CTRL_Entity *module, U64 voff);
internal U64 ctrl_voff_from_vaddr(CTRL_Entity *module, U64 vaddr);
internal Rng1U64 ctrl_vaddr_range_from_voff_range(CTRL_Entity *module, Rng1U64 voff_range);
internal Rng1U64 ctrl_voff_range_from_vaddr_range(CTRL_Entity *module, Rng1U64 vaddr_range);
internal B32 ctrl_entity_tree_is_frozen(CTRL_Entity *root);
//- rjf: entity tree iteration
internal CTRL_EntityRec ctrl_entity_rec_depth_first(CTRL_Entity *entity, CTRL_Entity *subtree_root, U64 sib_off, U64 child_off);
#define ctrl_entity_rec_depth_first_pre(entity, subtree_root) ctrl_entity_rec_depth_first((entity), (subtree_root), OffsetOf(CTRL_Entity, next), OffsetOf(CTRL_Entity, first))
#define ctrl_entity_rec_depth_first_post(entity, subtree_root) ctrl_entity_rec_depth_first((entity), (subtree_root), OffsetOf(CTRL_Entity, prev), OffsetOf(CTRL_Entity, last))
//- rjf: applying events to entity caches //- rjf: applying events to entity caches
internal void ctrl_entity_store_apply_events(CTRL_EntityStore *store, CTRL_EventList *list); internal void ctrl_entity_store_apply_events(CTRL_EntityStore *store, CTRL_EventList *list);
@@ -722,57 +1064,62 @@ internal void ctrl_set_wakeup_hook(CTRL_WakeupFunctionType *wakeup_hook);
//~ rjf: Process Memory Functions //~ rjf: Process Memory Functions
//- rjf: process memory cache interaction //- rjf: process memory cache interaction
internal U128 ctrl_calc_hash_store_key_from_process_vaddr_range(CTRL_MachineID machine_id, DMN_Handle process, Rng1U64 range, B32 zero_terminated); internal U128 ctrl_calc_hash_store_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, B32 zero_terminated);
internal U128 ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, DMN_Handle process, Rng1U64 range, B32 zero_terminated, B32 *out_is_stale, U64 endt_us); internal U128 ctrl_stored_hash_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, B32 zero_terminated, B32 *out_is_stale, U64 endt_us);
//- rjf: bundled key/stream helper //- rjf: bundled key/stream helper
internal U128 ctrl_hash_store_key_from_process_vaddr_range(CTRL_MachineID machine_id, DMN_Handle process, Rng1U64 range, B32 zero_terminated); internal U128 ctrl_hash_store_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, B32 zero_terminated);
//- rjf: process memory cache reading helpers //- rjf: process memory cache reading helpers
internal CTRL_ProcessMemorySlice ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID machine_id, DMN_Handle process, Rng1U64 range, U64 endt_us); internal CTRL_ProcessMemorySlice ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_Handle process, Rng1U64 range, U64 endt_us);
internal CTRL_ProcessMemorySlice ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(Arena *arena, CTRL_MachineID machine_id, DMN_Handle process, U64 vaddr, U64 limit, U64 element_size, U64 endt_us); internal CTRL_ProcessMemorySlice ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(Arena *arena, CTRL_Handle process, U64 vaddr, U64 limit, U64 element_size, U64 endt_us);
internal B32 ctrl_read_cached_process_memory(CTRL_MachineID machine_id, DMN_Handle process, Rng1U64 range, B32 *is_stale_out, void *out, U64 endt_us); internal B32 ctrl_read_cached_process_memory(CTRL_Handle process, Rng1U64 range, B32 *is_stale_out, void *out, U64 endt_us);
#define ctrl_read_cached_process_memory_struct(machine_id, process, vaddr, is_stale_out, ptr, endt_us) ctrl_read_cached_process_memory((machine_id), (process), r1u64((vaddr), (vaddr)+(sizeof(*(ptr)))), (is_stale_out), (ptr), (endt_us)) #define ctrl_read_cached_process_memory_struct(process, vaddr, is_stale_out, ptr, endt_us) ctrl_read_cached_process_memory((process), r1u64((vaddr), (vaddr)+(sizeof(*(ptr)))), (is_stale_out), (ptr), (endt_us))
//- rjf: process memory writing //- rjf: process memory writing
internal B32 ctrl_process_write(CTRL_MachineID machine_id, DMN_Handle process, Rng1U64 range, void *src); internal B32 ctrl_process_write(CTRL_Handle process, Rng1U64 range, void *src);
//////////////////////////////// ////////////////////////////////
//~ rjf: Thread Register Functions //~ rjf: Thread Register Functions
//- rjf: thread register cache reading //- rjf: thread register cache reading
internal void *ctrl_query_cached_reg_block_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle thread); internal void *ctrl_query_cached_reg_block_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_Handle handle);
internal U64 ctrl_query_cached_tls_root_vaddr_from_thread(CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle thread); internal U64 ctrl_query_cached_tls_root_vaddr_from_thread(CTRL_EntityStore *store, CTRL_Handle handle);
internal U64 ctrl_query_cached_rip_from_thread(CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle thread); internal U64 ctrl_query_cached_rip_from_thread(CTRL_EntityStore *store, CTRL_Handle handle);
internal U64 ctrl_query_cached_rsp_from_thread(CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle thread); internal U64 ctrl_query_cached_rsp_from_thread(CTRL_EntityStore *store, CTRL_Handle handle);
//- rjf: thread register writing //- rjf: thread register writing
internal B32 ctrl_thread_write_reg_block(CTRL_MachineID machine_id, DMN_Handle thread, void *block); internal B32 ctrl_thread_write_reg_block(CTRL_Handle thread, void *block);
//////////////////////////////// ////////////////////////////////
//~ rjf: Module Image Info Functions //~ rjf: Module Image Info Functions
//- rjf: cache lookups //- rjf: cache lookups
internal PE_IntelPdata *ctrl_intel_pdata_from_module_voff(Arena *arena, CTRL_MachineID machine_id, DMN_Handle module_handle, U64 voff); internal PE_IntelPdata *ctrl_intel_pdata_from_module_voff(Arena *arena, CTRL_Handle module_handle, U64 voff);
internal U64 ctrl_entry_point_voff_from_module(CTRL_MachineID machine_id, DMN_Handle module_handle); internal U64 ctrl_entry_point_voff_from_module(CTRL_Handle module_handle);
internal Rng1U64 ctrl_tls_vaddr_range_from_module(CTRL_MachineID machine_id, DMN_Handle module_handle); internal Rng1U64 ctrl_tls_vaddr_range_from_module(CTRL_Handle module_handle);
internal String8 ctrl_initial_debug_info_path_from_module(Arena *arena, CTRL_MachineID machine_id, DMN_Handle module_handle); internal String8 ctrl_initial_debug_info_path_from_module(Arena *arena, CTRL_Handle module_handle);
//////////////////////////////// ////////////////////////////////
//~ rjf: Unwinding Functions //~ rjf: Unwinding Functions
//- rjf: unwind deep copier //- rjf: unwind deep copier
internal CTRL_Unwind ctrl_unwind_deep_copy(Arena *arena, Architecture arch, CTRL_Unwind *src); internal CTRL_Unwind ctrl_unwind_deep_copy(Arena *arena, Arch arch, CTRL_Unwind *src);
//- rjf: [x64] //- rjf: [x64]
internal REGS_Reg64 *ctrl_unwind_reg_from_pe_gpr_reg__pe_x64(REGS_RegBlockX64 *regs, PE_UnwindGprRegX64 gpr_reg); internal REGS_Reg64 *ctrl_unwind_reg_from_pe_gpr_reg__pe_x64(REGS_RegBlockX64 *regs, PE_UnwindGprRegX64 gpr_reg);
internal CTRL_UnwindStepResult ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle process_handle, DMN_Handle module, REGS_RegBlockX64 *regs, U64 endt_us); internal CTRL_UnwindStepResult ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_Handle process_handle, CTRL_Handle module_handle, REGS_RegBlockX64 *regs, U64 endt_us);
//- rjf: abstracted unwind step //- rjf: abstracted unwind step
internal CTRL_UnwindStepResult ctrl_unwind_step(CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle process_handle, DMN_Handle module, Architecture arch, void *reg_block, U64 endt_us); internal CTRL_UnwindStepResult ctrl_unwind_step(CTRL_EntityStore *store, CTRL_Handle process, CTRL_Handle module, Arch arch, void *reg_block, U64 endt_us);
//- rjf: abstracted full unwind //- rjf: abstracted full unwind
internal CTRL_Unwind ctrl_unwind_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle thread, U64 endt_us); internal CTRL_Unwind ctrl_unwind_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_Handle thread, U64 endt_us);
////////////////////////////////
//~ rjf: Call Stack Building Functions
internal CTRL_CallStack ctrl_call_stack_from_unwind(Arena *arena, DI_Scope *di_scope, CTRL_Entity *process, CTRL_Unwind *base_unwind);
//////////////////////////////// ////////////////////////////////
//~ rjf: Halting All Attached Processes //~ rjf: Halting All Attached Processes
@@ -788,8 +1135,8 @@ internal U64 ctrl_mem_gen(void);
internal U64 ctrl_reg_gen(void); internal U64 ctrl_reg_gen(void);
//- rjf: name -> register/alias hash tables, for eval //- rjf: name -> register/alias hash tables, for eval
internal EVAL_String2NumMap *ctrl_string2reg_from_arch(Architecture arch); internal E_String2NumMap *ctrl_string2reg_from_arch(Arch arch);
internal EVAL_String2NumMap *ctrl_string2alias_from_arch(Architecture arch); internal E_String2NumMap *ctrl_string2alias_from_arch(Arch arch);
//////////////////////////////// ////////////////////////////////
//~ rjf: Control-Thread Functions //~ rjf: Control-Thread Functions
@@ -806,18 +1153,18 @@ internal CTRL_EventList ctrl_c2u_pop_events(Arena *arena);
internal void ctrl_thread__entry_point(void *p); internal void ctrl_thread__entry_point(void *p);
//- rjf: breakpoint resolution //- rjf: breakpoint resolution
internal void ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_MachineID machine_id, DMN_Handle process, DMN_Handle module, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out); internal void ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_Handle process, CTRL_Handle module, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out);
internal void ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, CTRL_MachineID machine_id, DMN_Handle process, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out); internal void ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, CTRL_Handle process, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out);
//- rjf: module lifetime open/close work //- rjf: module lifetime open/close work
internal void ctrl_thread__module_open(CTRL_MachineID machine_id, DMN_Handle process, DMN_Handle module, Rng1U64 vaddr_range, String8 path); internal void ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_range, String8 path);
internal void ctrl_thread__module_close(CTRL_MachineID machine_id, DMN_Handle module); internal void ctrl_thread__module_close(CTRL_Handle module);
//- rjf: attached process running/event gathering //- rjf: attached process running/event gathering
internal DMN_Event *ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, DMN_RunCtrls *run_ctrls, CTRL_Spoof *spoof); internal DMN_Event *ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, DMN_RunCtrls *run_ctrls, CTRL_Spoof *spoof);
//- rjf: eval helpers //- rjf: eval helpers
internal B32 ctrl_eval_memory_read(void *u, void *out, U64 addr, U64 size); internal B32 ctrl_eval_space_read(void *u, E_Space space, void *out, Rng1U64 vaddr_range);
//- rjf: log flusher //- rjf: log flusher
internal void ctrl_thread__flush_info_log(String8 string); internal void ctrl_thread__flush_info_log(String8 string);
@@ -827,6 +1174,7 @@ internal void ctrl_thread__end_and_flush_info_log(void);
internal void ctrl_thread__launch(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg); internal void ctrl_thread__launch(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
internal void ctrl_thread__attach(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg); internal void ctrl_thread__attach(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
internal void ctrl_thread__kill(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg); internal void ctrl_thread__kill(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
internal void ctrl_thread__kill_all(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
internal void ctrl_thread__detach(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg); internal void ctrl_thread__detach(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
internal void ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg); internal void ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
internal void ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg); internal void ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
@@ -835,10 +1183,11 @@ internal void ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
//~ rjf: Memory-Stream Thread Functions //~ rjf: Memory-Stream Thread Functions
//- rjf: user -> memory stream communication //- rjf: user -> memory stream communication
internal B32 ctrl_u2ms_enqueue_req(CTRL_MachineID machine_id, DMN_Handle process, Rng1U64 vaddr_range, B32 zero_terminated, U64 endt_us); internal B32 ctrl_u2ms_enqueue_req(CTRL_Handle process, Rng1U64 vaddr_range, B32 zero_terminated, U64 endt_us);
internal void ctrl_u2ms_dequeue_req(CTRL_MachineID *out_machine_id, DMN_Handle *out_process, Rng1U64 *out_vaddr_range, B32 *out_zero_terminated); internal void ctrl_u2ms_dequeue_req(CTRL_Handle *out_process, Rng1U64 *out_vaddr_range, B32 *out_zero_terminated);
//- rjf: entry point //- rjf: entry point
ASYNC_WORK_DEF(ctrl_mem_stream_work);
internal void ctrl_mem_stream_thread__entry_point(void *p); internal void ctrl_mem_stream_thread__entry_point(void *p);
#endif // CTRL_CORE_H #endif // CTRL_CORE_H
+12
View File
@@ -4,6 +4,18 @@
//- GENERATED CODE //- GENERATED CODE
C_LINKAGE_BEGIN C_LINKAGE_BEGIN
String8 ctrl_entity_kind_display_string_table[8] =
{
{0},
str8_lit_comp("Root"),
str8_lit_comp("Machine"),
str8_lit_comp("Process"),
str8_lit_comp("Thread"),
str8_lit_comp("Module"),
str8_lit_comp("EntryPoint"),
str8_lit_comp("DebugInfoPath"),
};
U32 ctrl_exception_code_kind_code_table[38] = U32 ctrl_exception_code_kind_code_table[38] =
{ {
0, 0,
+14
View File
@@ -6,6 +6,19 @@
#ifndef CTRL_META_H #ifndef CTRL_META_H
#define CTRL_META_H #define CTRL_META_H
typedef enum CTRL_EntityKind
{
CTRL_EntityKind_Null,
CTRL_EntityKind_Root,
CTRL_EntityKind_Machine,
CTRL_EntityKind_Process,
CTRL_EntityKind_Thread,
CTRL_EntityKind_Module,
CTRL_EntityKind_EntryPoint,
CTRL_EntityKind_DebugInfoPath,
CTRL_EntityKind_COUNT,
} CTRL_EntityKind;
typedef enum CTRL_ExceptionCodeKind typedef enum CTRL_ExceptionCodeKind
{ {
CTRL_ExceptionCodeKind_Null, CTRL_ExceptionCodeKind_Null,
@@ -50,6 +63,7 @@ CTRL_ExceptionCodeKind_COUNT,
} CTRL_ExceptionCodeKind; } CTRL_ExceptionCodeKind;
C_LINKAGE_BEGIN C_LINKAGE_BEGIN
extern String8 ctrl_entity_kind_display_string_table[8];
extern U32 ctrl_exception_code_kind_code_table[38]; extern U32 ctrl_exception_code_kind_code_table[38];
extern String8 ctrl_exception_code_kind_display_string_table[38]; extern String8 ctrl_exception_code_kind_display_string_table[38];
extern String8 ctrl_exception_code_kind_lowercase_code_string_table[38]; extern String8 ctrl_exception_code_kind_lowercase_code_string_table[38];
+463 -345
View File
@@ -2,16 +2,174 @@
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
//////////////////////////////// ////////////////////////////////
//~ rjf: Third Party Includes //~ rjf: Instruction Decoding/Disassembling Type Functions
#include "third_party/udis86/config.h" #if !defined(ZYDIS_H)
#include "third_party/udis86/udis86.h" #include "third_party/zydis/zydis.h"
#include "third_party/udis86/libudis86/decode.c" #include "third_party/zydis/zydis.c"
#include "third_party/udis86/libudis86/itab.c" #endif
#include "third_party/udis86/libudis86/syn-att.c"
#include "third_party/udis86/libudis86/syn-intel.c" internal DASM_Inst
#include "third_party/udis86/libudis86/syn.c" dasm_inst_from_code(Arena *arena, Arch arch, U64 vaddr, String8 code, DASM_Syntax syntax)
#include "third_party/udis86/libudis86/udis86.c" {
DASM_Inst inst = {0};
switch(arch)
{
default:{}break;
//- rjf: x86/x64 disassembly
case Arch_x86:
case Arch_x64:
{
// rjf: determine zydis formatter style
ZydisFormatterStyle style = ZYDIS_FORMATTER_STYLE_INTEL;
switch(syntax)
{
default:{}break;
case DASM_Syntax_Intel:{style = ZYDIS_FORMATTER_STYLE_INTEL;}break;
case DASM_Syntax_ATT: {style = ZYDIS_FORMATTER_STYLE_ATT;}break;
}
// rjf: disassemble one instruction
ZydisDisassembledInstruction zinst = {0};
ZyanStatus status = ZydisDisassemble(ZYDIS_MACHINE_MODE_LONG_64, vaddr, code.str, code.size, &zinst, style);
// rjf: analyze
DASM_InstFlags flags = 0;
U64 jump_dest_vaddr = 0;
{
ZydisDecodedOperand *first_visible_op = (zinst.info.operand_count_visible > 0 ? &zinst.operands[0] : 0);
ZydisDecodedOperand *first_op = (zinst.info.operand_count > 0 ? &zinst.operands[0] : 0);
ZydisDecodedOperand *second_op = (zinst.info.operand_count > 1 ? &zinst.operands[1] : 0);
if(first_visible_op != 0 &&
(first_visible_op->encoding == ZYDIS_OPERAND_ENCODING_JIMM8 ||
first_visible_op->encoding == ZYDIS_OPERAND_ENCODING_JIMM16 ||
first_visible_op->encoding == ZYDIS_OPERAND_ENCODING_JIMM32 ||
first_visible_op->encoding == ZYDIS_OPERAND_ENCODING_JIMM64 ||
first_visible_op->encoding == ZYDIS_OPERAND_ENCODING_JIMM16_32_64 ||
first_visible_op->encoding == ZYDIS_OPERAND_ENCODING_JIMM32_32_64 ||
first_visible_op->encoding == ZYDIS_OPERAND_ENCODING_JIMM16_32_32))
{
ZydisCalcAbsoluteAddress(&zinst.info, first_visible_op, vaddr, &jump_dest_vaddr);
}
if(first_op != 0 && second_op != 0 && first_op->type == ZYDIS_OPERAND_TYPE_REGISTER &&
(first_op->reg.value == ZYDIS_REGISTER_RSP ||
first_op->reg.value == ZYDIS_REGISTER_ESP ||
first_op->reg.value == ZYDIS_REGISTER_SP))
{
flags |= DASM_InstFlag_ChangesStackPointer;
if(second_op->type != ZYDIS_OPERAND_TYPE_IMMEDIATE)
{
flags |= DASM_InstFlag_ChangesStackPointerVariably;
}
}
if(zinst.info.attributes & (ZYDIS_ATTRIB_HAS_REP|
ZYDIS_ATTRIB_HAS_REPE|
ZYDIS_ATTRIB_HAS_REPZ|
ZYDIS_ATTRIB_HAS_REPNZ|
ZYDIS_ATTRIB_HAS_REPNE))
{
flags |= DASM_InstFlag_Repeats;
}
switch(zinst.info.mnemonic)
{
case ZYDIS_MNEMONIC_CALL:
{
flags |= DASM_InstFlag_Call;
}break;
case ZYDIS_MNEMONIC_JB:
case ZYDIS_MNEMONIC_JBE:
case ZYDIS_MNEMONIC_JCXZ:
case ZYDIS_MNEMONIC_JECXZ:
case ZYDIS_MNEMONIC_JKNZD:
case ZYDIS_MNEMONIC_JKZD:
case ZYDIS_MNEMONIC_JL:
case ZYDIS_MNEMONIC_JLE:
case ZYDIS_MNEMONIC_JNB:
case ZYDIS_MNEMONIC_JNBE:
case ZYDIS_MNEMONIC_JNL:
case ZYDIS_MNEMONIC_JNLE:
case ZYDIS_MNEMONIC_JNO:
case ZYDIS_MNEMONIC_JNP:
case ZYDIS_MNEMONIC_JNS:
case ZYDIS_MNEMONIC_JNZ:
case ZYDIS_MNEMONIC_JO:
case ZYDIS_MNEMONIC_JP:
case ZYDIS_MNEMONIC_JRCXZ:
case ZYDIS_MNEMONIC_JS:
case ZYDIS_MNEMONIC_JZ:
case ZYDIS_MNEMONIC_LOOP:
case ZYDIS_MNEMONIC_LOOPE:
case ZYDIS_MNEMONIC_LOOPNE:
{
flags |= DASM_InstFlag_Branch;
}break;
case ZYDIS_MNEMONIC_JMP:
{
flags |= DASM_InstFlag_UnconditionalJump;
}break;
case ZYDIS_MNEMONIC_RET:
{
flags |= DASM_InstFlag_Return;
}break;
case ZYDIS_MNEMONIC_PUSH:
case ZYDIS_MNEMONIC_POP:
{
flags |= DASM_InstFlag_ChangesStackPointer;
}break;
default:
{
flags |= DASM_InstFlag_NonFlow;
}break;
}
}
// rjf: convert
{
inst.flags = flags;
inst.size = zinst.info.length;
inst.string = push_str8_copy(arena, str8_cstring(zinst.text));
inst.jump_dest_vaddr = jump_dest_vaddr;
}
}break;
}
return inst;
}
////////////////////////////////
//~ rjf: Control Flow Analysis
internal DASM_CtrlFlowInfo
dasm_ctrl_flow_info_from_arch_vaddr_code(Arena *arena, DASM_InstFlags exit_points_mask, Arch arch, U64 vaddr, String8 code)
{
Temp scratch = scratch_begin(&arena, 1);
DASM_CtrlFlowInfo info = {0};
for(U64 offset = 0; offset < code.size;)
{
DASM_Inst inst = dasm_inst_from_code(scratch.arena, arch, vaddr+offset, str8_skip(code, offset), DASM_Syntax_Intel);
U64 inst_vaddr = vaddr+offset;
offset += inst.size;
info.total_size += inst.size;
if(inst.flags & exit_points_mask)
{
DASM_CtrlFlowPoint point = {0};
point.inst_flags = inst.flags;
point.vaddr = inst_vaddr;
point.jump_dest_vaddr = inst.jump_dest_vaddr;
DASM_CtrlFlowPointNode *node = push_array(arena, DASM_CtrlFlowPointNode, 1);
node->v = point;
SLLQueuePush(info.exit_points.first, info.exit_points.last, node);
info.exit_points.count += 1;
}
}
scratch_end(scratch);
return info;
}
//////////////////////////////// ////////////////////////////////
//~ rjf: Parameter Type Functions //~ rjf: Parameter Type Functions
@@ -29,42 +187,42 @@ dasm_params_match(DASM_Params *a, DASM_Params *b)
} }
//////////////////////////////// ////////////////////////////////
//~ rjf: Instruction Type Functions //~ rjf: Line Type Functions
internal void internal void
dasm_inst_chunk_list_push(Arena *arena, DASM_InstChunkList *list, U64 cap, DASM_Inst *inst) dasm_line_chunk_list_push(Arena *arena, DASM_LineChunkList *list, U64 cap, DASM_Line *inst)
{ {
DASM_InstChunkNode *node = list->last; DASM_LineChunkNode *node = list->last;
if(node == 0 || node->count >= node->cap) if(node == 0 || node->count >= node->cap)
{ {
node = push_array(arena, DASM_InstChunkNode, 1); node = push_array(arena, DASM_LineChunkNode, 1);
node->v = push_array_no_zero(arena, DASM_Inst, cap); node->v = push_array_no_zero(arena, DASM_Line, cap);
node->cap = cap; node->cap = cap;
SLLQueuePush(list->first, list->last, node); SLLQueuePush(list->first, list->last, node);
list->node_count += 1; list->node_count += 1;
} }
MemoryCopyStruct(&node->v[node->count], inst); MemoryCopyStruct(&node->v[node->count], inst);
node->count += 1; node->count += 1;
list->inst_count += 1; list->line_count += 1;
} }
internal DASM_InstArray internal DASM_LineArray
dasm_inst_array_from_chunk_list(Arena *arena, DASM_InstChunkList *list) dasm_line_array_from_chunk_list(Arena *arena, DASM_LineChunkList *list)
{ {
DASM_InstArray array = {0}; DASM_LineArray array = {0};
array.count = list->inst_count; array.count = list->line_count;
array.v = push_array_no_zero(arena, DASM_Inst, array.count); array.v = push_array_no_zero(arena, DASM_Line, array.count);
U64 idx = 0; U64 idx = 0;
for(DASM_InstChunkNode *n = list->first; n != 0; n = n->next) for(DASM_LineChunkNode *n = list->first; n != 0; n = n->next)
{ {
MemoryCopy(array.v+idx, n->v, sizeof(DASM_Inst)*n->count); MemoryCopy(array.v+idx, n->v, sizeof(DASM_Line)*n->count);
idx += n->count; idx += n->count;
} }
return array; return array;
} }
internal U64 internal U64
dasm_inst_array_idx_from_code_off__linear_scan(DASM_InstArray *array, U64 off) dasm_line_array_idx_from_code_off__linear_scan(DASM_LineArray *array, U64 off)
{ {
U64 result = 0; U64 result = 0;
for(U64 idx = 0; idx < array->count; idx += 1) for(U64 idx = 0; idx < array->count; idx += 1)
@@ -73,7 +231,7 @@ dasm_inst_array_idx_from_code_off__linear_scan(DASM_InstArray *array, U64 off)
if(array->v[idx].code_off <= off && off < next_off) if(array->v[idx].code_off <= off && off < next_off)
{ {
result = idx; result = idx;
if(!(array->v[idx].flags & DASM_InstFlag_Decorative)) if(!(array->v[idx].flags & DASM_LineFlag_Decorative))
{ {
break; break;
} }
@@ -83,7 +241,7 @@ dasm_inst_array_idx_from_code_off__linear_scan(DASM_InstArray *array, U64 off)
} }
internal U64 internal U64
dasm_inst_array_code_off_from_idx(DASM_InstArray *array, U64 idx) dasm_line_array_code_off_from_idx(DASM_LineArray *array, U64 idx)
{ {
U64 off = 0; U64 off = 0;
if(idx < array->count) if(idx < array->count)
@@ -103,7 +261,7 @@ dasm_init(void)
dasm_shared = push_array(arena, DASM_Shared, 1); dasm_shared = push_array(arena, DASM_Shared, 1);
dasm_shared->arena = arena; dasm_shared->arena = arena;
dasm_shared->slots_count = 1024; dasm_shared->slots_count = 1024;
dasm_shared->stripes_count = Min(dasm_shared->slots_count, os_logical_core_count()); dasm_shared->stripes_count = Min(dasm_shared->slots_count, os_get_system_info()->logical_processor_count);
dasm_shared->slots = push_array(arena, DASM_Slot, dasm_shared->slots_count); dasm_shared->slots = push_array(arena, DASM_Slot, dasm_shared->slots_count);
dasm_shared->stripes = push_array(arena, DASM_Stripe, dasm_shared->stripes_count); dasm_shared->stripes = push_array(arena, DASM_Stripe, dasm_shared->stripes_count);
for(U64 idx = 0; idx < dasm_shared->stripes_count; idx += 1) for(U64 idx = 0; idx < dasm_shared->stripes_count; idx += 1)
@@ -116,29 +274,7 @@ dasm_init(void)
dasm_shared->u2p_ring_base = push_array_no_zero(arena, U8, dasm_shared->u2p_ring_size); dasm_shared->u2p_ring_base = push_array_no_zero(arena, U8, dasm_shared->u2p_ring_size);
dasm_shared->u2p_ring_cv = os_condition_variable_alloc(); dasm_shared->u2p_ring_cv = os_condition_variable_alloc();
dasm_shared->u2p_ring_mutex = os_mutex_alloc(); dasm_shared->u2p_ring_mutex = os_mutex_alloc();
dasm_shared->parse_thread_count = 1; dasm_shared->evictor_detector_thread = os_thread_launch(dasm_evictor_detector_thread__entry_point, 0, 0);
dasm_shared->parse_threads = push_array(arena, OS_Handle, dasm_shared->parse_thread_count);
for(U64 idx = 0; idx < dasm_shared->parse_thread_count; idx += 1)
{
dasm_shared->parse_threads[idx] = os_launch_thread(dasm_parse_thread__entry_point, (void *)idx, 0);
}
dasm_shared->evictor_detector_thread = os_launch_thread(dasm_evictor_detector_thread__entry_point, 0, 0);
}
////////////////////////////////
//~ rjf: User Clock
internal void
dasm_user_clock_tick(void)
{
ins_atomic_u64_inc_eval(&dasm_shared->user_clock_idx);
}
internal U64
dasm_user_clock_idx(void)
{
U64 idx = ins_atomic_u64_eval(&dasm_shared->user_clock_idx);
return idx;
} }
//////////////////////////////// ////////////////////////////////
@@ -190,7 +326,7 @@ dasm_scope_touch_node__stripe_r_guarded(DASM_Scope *scope, DASM_Node *node)
DASM_Touch *touch = push_array(dasm_tctx->arena, DASM_Touch, 1); DASM_Touch *touch = push_array(dasm_tctx->arena, DASM_Touch, 1);
ins_atomic_u64_inc_eval(&node->scope_ref_count); ins_atomic_u64_inc_eval(&node->scope_ref_count);
ins_atomic_u64_eval_assign(&node->last_time_touched_us, os_now_microseconds()); ins_atomic_u64_eval_assign(&node->last_time_touched_us, os_now_microseconds());
ins_atomic_u64_eval_assign(&node->last_user_clock_idx_touched, dasm_user_clock_idx()); ins_atomic_u64_eval_assign(&node->last_user_clock_idx_touched, update_tick_idx());
touch->hash = node->hash; touch->hash = node->hash;
MemoryCopyStruct(&touch->params, &node->params); MemoryCopyStruct(&touch->params, &node->params);
touch->params.dbgi_key = di_key_copy(dasm_tctx->arena, &touch->params.dbgi_key); touch->params.dbgi_key = di_key_copy(dasm_tctx->arena, &touch->params.dbgi_key);
@@ -244,7 +380,7 @@ dasm_info_from_hash_params(DASM_Scope *scope, U128 hash, DASM_Params *params)
{ {
log_infof("hash: [0x%I64x 0x%I64x]\n", hash.u64[0], hash.u64[1]); log_infof("hash: [0x%I64x 0x%I64x]\n", hash.u64[0], hash.u64[1]);
log_infof("vaddr: 0x%I64x\n", params->vaddr); log_infof("vaddr: 0x%I64x\n", params->vaddr);
log_infof("arch: %S\n", string_from_architecture(params->arch)); log_infof("arch: %S\n", string_from_arch(params->arch));
log_infof("style_flags: 0x%x\n", params->style_flags); log_infof("style_flags: 0x%x\n", params->style_flags);
log_infof("syntax: %i\n", params->syntax); log_infof("syntax: %i\n", params->syntax);
log_infof("base_vaddr: 0x%I64x\n", params->base_vaddr); log_infof("base_vaddr: 0x%I64x\n", params->base_vaddr);
@@ -272,6 +408,7 @@ dasm_info_from_hash_params(DASM_Scope *scope, U128 hash, DASM_Params *params)
if(node_is_new) if(node_is_new)
{ {
dasm_u2p_enqueue_req(hash, params, max_U64); dasm_u2p_enqueue_req(hash, params, max_U64);
async_push_work(dasm_parse_work);
} }
} }
return info; return info;
@@ -281,11 +418,11 @@ internal DASM_Info
dasm_info_from_key_params(DASM_Scope *scope, U128 key, DASM_Params *params, U128 *hash_out) dasm_info_from_key_params(DASM_Scope *scope, U128 key, DASM_Params *params, U128 *hash_out)
{ {
DASM_Info result = {0}; DASM_Info result = {0};
for(U64 rewind_idx = 0; rewind_idx < 2; rewind_idx += 1) for(U64 rewind_idx = 0; rewind_idx < HS_KEY_HASH_HISTORY_COUNT; rewind_idx += 1)
{ {
U128 hash = hs_hash_from_key(key, rewind_idx); U128 hash = hs_hash_from_key(key, rewind_idx);
result = dasm_info_from_hash_params(scope, hash, params); result = dasm_info_from_hash_params(scope, hash, params);
if(result.insts.count != 0) if(result.lines.count != 0)
{ {
if(hash_out) if(hash_out)
{ {
@@ -308,7 +445,7 @@ dasm_u2p_enqueue_req(U128 hash, DASM_Params *params, U64 endt_us)
{ {
U64 unconsumed_size = dasm_shared->u2p_ring_write_pos - dasm_shared->u2p_ring_read_pos; U64 unconsumed_size = dasm_shared->u2p_ring_write_pos - dasm_shared->u2p_ring_read_pos;
U64 available_size = dasm_shared->u2p_ring_size - unconsumed_size; U64 available_size = dasm_shared->u2p_ring_size - unconsumed_size;
if(available_size >= sizeof(hash)+sizeof(U64)+sizeof(Architecture)+sizeof(DASM_StyleFlags)+sizeof(DASM_Syntax)+sizeof(U64)+sizeof(U64)+params->dbgi_key.path.size+sizeof(U64)) if(available_size >= sizeof(hash)+sizeof(U64)+sizeof(Arch)+sizeof(DASM_StyleFlags)+sizeof(DASM_Syntax)+sizeof(U64)+sizeof(U64)+params->dbgi_key.path.size+sizeof(U64))
{ {
good = 1; good = 1;
dasm_shared->u2p_ring_write_pos += ring_write_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, &hash); dasm_shared->u2p_ring_write_pos += ring_write_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, &hash);
@@ -320,8 +457,6 @@ dasm_u2p_enqueue_req(U128 hash, DASM_Params *params, U64 endt_us)
dasm_shared->u2p_ring_write_pos += ring_write_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, &params->dbgi_key.path.size); dasm_shared->u2p_ring_write_pos += ring_write_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, &params->dbgi_key.path.size);
dasm_shared->u2p_ring_write_pos += ring_write(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, params->dbgi_key.path.str, params->dbgi_key.path.size); dasm_shared->u2p_ring_write_pos += ring_write(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, params->dbgi_key.path.str, params->dbgi_key.path.size);
dasm_shared->u2p_ring_write_pos += ring_write_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, &params->dbgi_key.min_timestamp); dasm_shared->u2p_ring_write_pos += ring_write_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, &params->dbgi_key.min_timestamp);
dasm_shared->u2p_ring_write_pos += 7;
dasm_shared->u2p_ring_write_pos -= dasm_shared->u2p_ring_write_pos%8;
break; break;
} }
if(os_now_microseconds() >= endt_us) if(os_now_microseconds() >= endt_us)
@@ -343,7 +478,7 @@ dasm_u2p_dequeue_req(Arena *arena, U128 *hash_out, DASM_Params *params_out)
OS_MutexScope(dasm_shared->u2p_ring_mutex) for(;;) OS_MutexScope(dasm_shared->u2p_ring_mutex) for(;;)
{ {
U64 unconsumed_size = dasm_shared->u2p_ring_write_pos - dasm_shared->u2p_ring_read_pos; U64 unconsumed_size = dasm_shared->u2p_ring_write_pos - dasm_shared->u2p_ring_read_pos;
if(unconsumed_size >= sizeof(*hash_out)+sizeof(U64)+sizeof(Architecture)+sizeof(DASM_StyleFlags)+sizeof(DASM_Syntax)+sizeof(U64)+sizeof(U64)+sizeof(U64)) if(unconsumed_size >= sizeof(*hash_out)+sizeof(U64)+sizeof(Arch)+sizeof(DASM_StyleFlags)+sizeof(DASM_Syntax)+sizeof(U64)+sizeof(U64)+sizeof(U64))
{ {
dasm_shared->u2p_ring_read_pos += ring_read_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, hash_out); dasm_shared->u2p_ring_read_pos += ring_read_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, hash_out);
dasm_shared->u2p_ring_read_pos += ring_read_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, &params_out->vaddr); dasm_shared->u2p_ring_read_pos += ring_read_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, &params_out->vaddr);
@@ -355,8 +490,6 @@ dasm_u2p_dequeue_req(Arena *arena, U128 *hash_out, DASM_Params *params_out)
params_out->dbgi_key.path.str = push_array(arena, U8, params_out->dbgi_key.path.size); params_out->dbgi_key.path.str = push_array(arena, U8, params_out->dbgi_key.path.size);
dasm_shared->u2p_ring_read_pos += ring_read(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, params_out->dbgi_key.path.str, params_out->dbgi_key.path.size); dasm_shared->u2p_ring_read_pos += ring_read(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, params_out->dbgi_key.path.str, params_out->dbgi_key.path.size);
dasm_shared->u2p_ring_read_pos += ring_read_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, &params_out->dbgi_key.min_timestamp); dasm_shared->u2p_ring_read_pos += ring_read_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, &params_out->dbgi_key.min_timestamp);
dasm_shared->u2p_ring_read_pos += 7;
dasm_shared->u2p_ring_read_pos -= dasm_shared->u2p_ring_read_pos%8;
break; break;
} }
os_condition_variable_wait(dasm_shared->u2p_ring_cv, dasm_shared->u2p_ring_mutex, max_U64); os_condition_variable_wait(dasm_shared->u2p_ring_cv, dasm_shared->u2p_ring_mutex, max_U64);
@@ -364,298 +497,282 @@ dasm_u2p_dequeue_req(Arena *arena, U128 *hash_out, DASM_Params *params_out)
os_condition_variable_broadcast(dasm_shared->u2p_ring_cv); os_condition_variable_broadcast(dasm_shared->u2p_ring_cv);
} }
internal void ASYNC_WORK_DEF(dasm_parse_work)
dasm_parse_thread__entry_point(void *p)
{ {
ThreadNameF("[dasm] parse thread #%I64u", (U64)p); ProfBeginFunction();
for(;;) Temp scratch = scratch_begin(0, 0);
HS_Scope *hs_scope = hs_scope_open();
DI_Scope *di_scope = di_scope_open();
TXT_Scope *txt_scope = txt_scope_open();
//- rjf: get next request
U128 hash = {0};
DASM_Params params = {0};
dasm_u2p_dequeue_req(scratch.arena, &hash, &params);
U64 change_gen = fs_change_gen();
//- rjf: unpack hash
U64 slot_idx = hash.u64[1]%dasm_shared->slots_count;
U64 stripe_idx = slot_idx%dasm_shared->stripes_count;
DASM_Slot *slot = &dasm_shared->slots[slot_idx];
DASM_Stripe *stripe = &dasm_shared->stripes[stripe_idx];
//- rjf: take task
B32 got_task = 0;
OS_MutexScopeR(stripe->rw_mutex)
{ {
Temp scratch = scratch_begin(0, 0); for(DASM_Node *n = slot->first; n != 0; n = n->next)
//- rjf: get next request
U128 hash = {0};
DASM_Params params = {0};
dasm_u2p_dequeue_req(scratch.arena, &hash, &params);
U64 change_gen = fs_change_gen();
HS_Scope *hs_scope = hs_scope_open();
DI_Scope *di_scope = di_scope_open();
TXT_Scope *txt_scope = txt_scope_open();
//- rjf: unpack hash
U64 slot_idx = hash.u64[1]%dasm_shared->slots_count;
U64 stripe_idx = slot_idx%dasm_shared->stripes_count;
DASM_Slot *slot = &dasm_shared->slots[slot_idx];
DASM_Stripe *stripe = &dasm_shared->stripes[stripe_idx];
//- rjf: take task
B32 got_task = 0;
OS_MutexScopeR(stripe->rw_mutex)
{ {
for(DASM_Node *n = slot->first; n != 0; n = n->next) if(u128_match(n->hash, hash) && dasm_params_match(&n->params, &params))
{ {
if(u128_match(n->hash, hash) && dasm_params_match(&n->params, &params)) got_task = !ins_atomic_u32_eval_cond_assign(&n->is_working, 1, 0);
{ break;
got_task = !ins_atomic_u32_eval_cond_assign(&n->is_working, 1, 0);
break;
}
} }
} }
//- rjf: get dbg info
RDI_Parsed *rdi = &di_rdi_parsed_nil;
if(got_task && params.dbgi_key.path.size != 0)
{
rdi = di_rdi_from_key(di_scope, &params.dbgi_key, max_U64);
}
//- rjf: hash -> data
String8 data = {0};
if(got_task)
{
data = hs_data_from_hash(hs_scope, hash);
}
//- rjf: data * arch * addr * dbg -> decode artifacts
DASM_InstChunkList inst_list = {0};
String8List inst_strings = {0};
if(got_task)
{
switch(params.arch)
{
default:{}break;
//- rjf: x86/x64 decoding
case Architecture_x64:
case Architecture_x86:
{
// rjf: grab context
struct ud udc;
ud_init(&udc);
ud_set_mode(&udc, bit_size_from_arch(params.arch));
ud_set_pc(&udc, params.vaddr);
ud_set_input_buffer(&udc, data.str, data.size);
ud_set_vendor(&udc, UD_VENDOR_ANY);
ud_set_syntax(&udc, params.syntax == DASM_Syntax_Intel ? UD_SYN_INTEL : UD_SYN_ATT);
// rjf: disassemble
RDI_SourceFile *last_file = &rdi_nil_element_union.source_file;
RDI_Line *last_line = 0;
for(U64 off = 0; off < data.size;)
{
// rjf: disassemble one instruction
U64 size = ud_disassemble(&udc);
if(size == 0)
{
break;
}
// rjf: analyze
struct ud_operand *first_op = (struct ud_operand *)ud_insn_opr(&udc, 0);
U64 rel_voff = (first_op != 0 && first_op->type == UD_OP_JIMM) ? ud_syn_rel_target(&udc, first_op) : 0;
U64 jump_dst_vaddr = rel_voff;
// rjf: push strings derived from voff -> line info
if(params.style_flags & (DASM_StyleFlag_SourceFilesNames|DASM_StyleFlag_SourceLines))
{
if(rdi != &di_rdi_parsed_nil)
{
U64 voff = (params.vaddr+off) - params.base_vaddr;
U32 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, voff);
RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx);
RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx);
RDI_ParsedLineTable unit_line_info = {0};
rdi_parsed_from_line_table(rdi, line_table, &unit_line_info);
U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, voff);
if(line_info_idx < unit_line_info.count)
{
RDI_Line *line = &unit_line_info.lines[line_info_idx];
RDI_SourceFile *file = rdi_element_from_name_idx(rdi, SourceFiles, line->file_idx);
String8 file_normalized_full_path = {0};
file_normalized_full_path.str = rdi_string_from_idx(rdi, file->normal_full_path_string_idx, &file_normalized_full_path.size);
if(file != last_file)
{
if(params.style_flags & DASM_StyleFlag_SourceFilesNames &&
file->normal_full_path_string_idx != 0 && file_normalized_full_path.size != 0)
{
String8 inst_string = push_str8f(scratch.arena, "> %S", file_normalized_full_path);
DASM_Inst inst = {u32_from_u64_saturate(off), DASM_InstFlag_Decorative, 0, r1u64(inst_strings.total_size + inst_strings.node_count,
inst_strings.total_size + inst_strings.node_count + inst_string.size)};
dasm_inst_chunk_list_push(scratch.arena, &inst_list, 1024, &inst);
str8_list_push(scratch.arena, &inst_strings, inst_string);
}
if(params.style_flags & DASM_StyleFlag_SourceFilesNames && file->normal_full_path_string_idx == 0)
{
String8 inst_string = str8_lit(">");
DASM_Inst inst = {u32_from_u64_saturate(off), DASM_InstFlag_Decorative, 0, r1u64(inst_strings.total_size + inst_strings.node_count,
inst_strings.total_size + inst_strings.node_count + inst_string.size)};
dasm_inst_chunk_list_push(scratch.arena, &inst_list, 1024, &inst);
str8_list_push(scratch.arena, &inst_strings, inst_string);
}
last_file = file;
}
if(line && line != last_line && file->normal_full_path_string_idx != 0 &&
params.style_flags & DASM_StyleFlag_SourceLines &&
file_normalized_full_path.size != 0)
{
FileProperties props = os_properties_from_file_path(file_normalized_full_path);
if(props.modified != 0)
{
// TODO(rjf): need redirection path - this may map to a different path on the local machine,
// need frontend to communicate path remapping info to this layer
U128 key = fs_key_from_path(file_normalized_full_path);
TXT_LangKind lang_kind = txt_lang_kind_from_extension(file_normalized_full_path);
U64 endt_us = max_U64;
U128 hash = {0};
TXT_TextInfo text_info = {0};
for(;os_now_microseconds() <= endt_us;)
{
text_info = txt_text_info_from_key_lang(txt_scope, key, lang_kind, &hash);
if(!u128_match(hash, u128_zero()))
{
break;
}
}
if(0 < line->line_num && line->line_num < text_info.lines_count)
{
String8 data = hs_data_from_hash(hs_scope, hash);
String8 line_text = str8_skip_chop_whitespace(str8_substr(data, text_info.lines_ranges[line->line_num-1]));
if(line_text.size != 0)
{
String8 inst_string = push_str8f(scratch.arena, "> %S", line_text);
DASM_Inst inst = {u32_from_u64_saturate(off), DASM_InstFlag_Decorative, 0, r1u64(inst_strings.total_size + inst_strings.node_count,
inst_strings.total_size + inst_strings.node_count + inst_string.size)};
dasm_inst_chunk_list_push(scratch.arena, &inst_list, 1024, &inst);
str8_list_push(scratch.arena, &inst_strings, inst_string);
}
}
}
last_line = line;
}
}
}
}
// rjf: push
String8 addr_part = {0};
if(params.style_flags & DASM_StyleFlag_Addresses)
{
addr_part = push_str8f(scratch.arena, "%s0x%016I64x ", rdi != &di_rdi_parsed_nil ? " " : "", params.vaddr+off);
}
String8 code_bytes_part = {0};
if(params.style_flags & DASM_StyleFlag_CodeBytes)
{
String8List code_bytes_strings = {0};
str8_list_push(scratch.arena, &code_bytes_strings, str8_lit("{"));
for(U64 byte_idx = 0; byte_idx < size || byte_idx < 16; byte_idx += 1)
{
if(byte_idx < size)
{
str8_list_pushf(scratch.arena, &code_bytes_strings, "%02x%s ", (U32)data.str[off+byte_idx], byte_idx == size-1 ? "}" : "");
}
else if(byte_idx < 8)
{
str8_list_push(scratch.arena, &code_bytes_strings, str8_lit(" "));
}
}
str8_list_push(scratch.arena, &code_bytes_strings, str8_lit(" "));
code_bytes_part = str8_list_join(scratch.arena, &code_bytes_strings, 0);
}
String8 symbol_part = {0};
if(jump_dst_vaddr != 0 && rdi != &di_rdi_parsed_nil && params.style_flags & DASM_StyleFlag_SymbolNames)
{
RDI_U32 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, jump_dst_vaddr-params.base_vaddr);
if(scope_idx != 0)
{
RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx);
RDI_U32 procedure_idx = scope->proc_idx;
RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_idx);
String8 procedure_name = {0};
procedure_name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &procedure_name.size);
if(procedure_name.size != 0)
{
symbol_part = push_str8f(scratch.arena, " (%S)", procedure_name);
}
}
}
String8 inst_string = push_str8f(scratch.arena, "%S%S%s%S", addr_part, code_bytes_part, udc.asm_buf, symbol_part);
DASM_Inst inst = {u32_from_u64_saturate(off), 0, rel_voff, r1u64(inst_strings.total_size + inst_strings.node_count,
inst_strings.total_size + inst_strings.node_count + inst_string.size)};
dasm_inst_chunk_list_push(scratch.arena, &inst_list, 1024, &inst);
str8_list_push(scratch.arena, &inst_strings, inst_string);
// rjf: increment
off += size;
}
}break;
}
}
//- rjf: artifacts -> value bundle
Arena *info_arena = 0;
DASM_Info info = {0};
if(got_task)
{
//- rjf: produce joined text
Arena *text_arena = arena_alloc();
StringJoin text_join = {0};
text_join.sep = str8_lit("\n");
String8 text = str8_list_join(text_arena, &inst_strings, &text_join);
//- rjf: produce unique key for this disassembly's text
U128 text_key = {0};
{
U64 hash_data[] =
{
hash.u64[0],
hash.u64[1],
params.vaddr,
(U64)params.arch,
(U64)params.style_flags,
(U64)params.syntax,
(U64)rdi,
0x4d534144,
};
text_key = hs_hash_from_data(str8((U8 *)hash_data, sizeof(hash_data)));
}
//- rjf: submit text data to hash store
U128 text_hash = hs_submit_data(text_key, &text_arena, text);
//- rjf: produce value bundle
info_arena = arena_alloc();
info.text_key = text_key;
info.insts = dasm_inst_array_from_chunk_list(info_arena, &inst_list);
}
//- rjf: commit results to cache
if(got_task) OS_MutexScopeW(stripe->rw_mutex)
{
for(DASM_Node *n = slot->first; n != 0; n = n->next)
{
if(u128_match(n->hash, hash) && dasm_params_match(&n->params, &params))
{
n->info_arena = info_arena;
MemoryCopyStruct(&n->info, &info);
if(rdi != &di_rdi_parsed_nil && params.style_flags & (DASM_StyleFlag_SourceLines|DASM_StyleFlag_SourceFilesNames))
{
n->change_gen = change_gen;
}
else
{
n->change_gen = 0;
}
ins_atomic_u32_eval_assign(&n->is_working, 0);
ins_atomic_u64_inc_eval(&n->load_count);
break;
}
}
}
txt_scope_close(txt_scope);
di_scope_close(di_scope);
hs_scope_close(hs_scope);
scratch_end(scratch);
} }
//- rjf: get dbg info
RDI_Parsed *rdi = &di_rdi_parsed_nil;
if(got_task && params.dbgi_key.path.size != 0)
{
rdi = di_rdi_from_key(di_scope, &params.dbgi_key, max_U64);
}
//- rjf: hash -> data
String8 data = {0};
if(got_task)
{
data = hs_data_from_hash(hs_scope, hash);
}
//- rjf: data * arch * addr * dbg -> decode artifacts
DASM_LineChunkList line_list = {0};
String8List inst_strings = {0};
if(got_task)
{
switch(params.arch)
{
default:{}break;
//- rjf: x86/x64 decoding
case Arch_x64:
case Arch_x86:
{
// rjf: disassemble
RDI_SourceFile *last_file = &rdi_nil_element_union.source_file;
RDI_Line *last_line = 0;
for(U64 off = 0; off < data.size;)
{
// rjf: disassemble one instruction
DASM_Inst inst = dasm_inst_from_code(scratch.arena, params.arch, params.vaddr+off, str8_skip(data, off), params.syntax);
if(inst.size == 0)
{
break;
}
// rjf: push strings derived from voff -> line info
if(params.style_flags & (DASM_StyleFlag_SourceFilesNames|DASM_StyleFlag_SourceLines))
{
if(rdi != &di_rdi_parsed_nil)
{
U64 voff = (params.vaddr+off) - params.base_vaddr;
U32 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, voff);
RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx);
RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx);
RDI_ParsedLineTable unit_line_info = {0};
rdi_parsed_from_line_table(rdi, line_table, &unit_line_info);
U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, voff);
if(line_info_idx < unit_line_info.count)
{
RDI_Line *line = &unit_line_info.lines[line_info_idx];
RDI_SourceFile *file = rdi_element_from_name_idx(rdi, SourceFiles, line->file_idx);
String8 file_normalized_full_path = {0};
file_normalized_full_path.str = rdi_string_from_idx(rdi, file->normal_full_path_string_idx, &file_normalized_full_path.size);
if(file != last_file)
{
if(params.style_flags & DASM_StyleFlag_SourceFilesNames &&
file->normal_full_path_string_idx != 0 && file_normalized_full_path.size != 0)
{
String8 inst_string = push_str8f(scratch.arena, "> %S", file_normalized_full_path);
DASM_Line inst = {u32_from_u64_saturate(off), DASM_LineFlag_Decorative, 0, r1u64(inst_strings.total_size + inst_strings.node_count,
inst_strings.total_size + inst_strings.node_count + inst_string.size)};
dasm_line_chunk_list_push(scratch.arena, &line_list, 1024, &inst);
str8_list_push(scratch.arena, &inst_strings, inst_string);
}
if(params.style_flags & DASM_StyleFlag_SourceFilesNames && file->normal_full_path_string_idx == 0)
{
String8 inst_string = str8_lit(">");
DASM_Line inst = {u32_from_u64_saturate(off), DASM_LineFlag_Decorative, 0, r1u64(inst_strings.total_size + inst_strings.node_count,
inst_strings.total_size + inst_strings.node_count + inst_string.size)};
dasm_line_chunk_list_push(scratch.arena, &line_list, 1024, &inst);
str8_list_push(scratch.arena, &inst_strings, inst_string);
}
last_file = file;
}
if(line && line != last_line && file->normal_full_path_string_idx != 0 &&
params.style_flags & DASM_StyleFlag_SourceLines &&
file_normalized_full_path.size != 0)
{
FileProperties props = os_properties_from_file_path(file_normalized_full_path);
if(props.modified != 0)
{
// TODO(rjf): need redirection path - this may map to a different path on the local machine,
// need frontend to communicate path remapping info to this layer
U128 key = fs_key_from_path_range(file_normalized_full_path, r1u64(0, max_U64));
TXT_LangKind lang_kind = txt_lang_kind_from_extension(file_normalized_full_path);
U64 endt_us = max_U64;
U128 hash = {0};
TXT_TextInfo text_info = {0};
for(;os_now_microseconds() <= endt_us;)
{
text_info = txt_text_info_from_key_lang(txt_scope, key, lang_kind, &hash);
if(!u128_match(hash, u128_zero()))
{
break;
}
}
if(0 < line->line_num && line->line_num < text_info.lines_count)
{
String8 data = hs_data_from_hash(hs_scope, hash);
String8 line_text = str8_skip_chop_whitespace(str8_substr(data, text_info.lines_ranges[line->line_num-1]));
if(line_text.size != 0)
{
String8 inst_string = push_str8f(scratch.arena, "> %S", line_text);
DASM_Line inst = {u32_from_u64_saturate(off), DASM_LineFlag_Decorative, 0, r1u64(inst_strings.total_size + inst_strings.node_count,
inst_strings.total_size + inst_strings.node_count + inst_string.size)};
dasm_line_chunk_list_push(scratch.arena, &line_list, 1024, &inst);
str8_list_push(scratch.arena, &inst_strings, inst_string);
}
}
}
last_line = line;
}
}
}
}
// rjf: push line
String8 addr_part = {0};
if(params.style_flags & DASM_StyleFlag_Addresses)
{
addr_part = push_str8f(scratch.arena, "%s0x%016I64x ", rdi != &di_rdi_parsed_nil ? " " : "", params.vaddr+off);
}
String8 code_bytes_part = {0};
if(params.style_flags & DASM_StyleFlag_CodeBytes)
{
String8List code_bytes_strings = {0};
str8_list_push(scratch.arena, &code_bytes_strings, str8_lit("{"));
for(U64 byte_idx = 0; byte_idx < inst.size || byte_idx < 16; byte_idx += 1)
{
if(byte_idx < inst.size)
{
str8_list_pushf(scratch.arena, &code_bytes_strings, "%02x%s ", (U32)data.str[off+byte_idx], byte_idx == inst.size-1 ? "}" : "");
}
else if(byte_idx < 8)
{
str8_list_push(scratch.arena, &code_bytes_strings, str8_lit(" "));
}
}
str8_list_push(scratch.arena, &code_bytes_strings, str8_lit(" "));
code_bytes_part = str8_list_join(scratch.arena, &code_bytes_strings, 0);
}
String8 symbol_part = {0};
if(inst.jump_dest_vaddr != 0 && rdi != &di_rdi_parsed_nil && params.style_flags & DASM_StyleFlag_SymbolNames)
{
RDI_U32 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, inst.jump_dest_vaddr-params.base_vaddr);
if(scope_idx != 0)
{
RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx);
RDI_U32 procedure_idx = scope->proc_idx;
RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_idx);
String8 procedure_name = {0};
procedure_name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &procedure_name.size);
if(procedure_name.size != 0)
{
symbol_part = push_str8f(scratch.arena, " (%S)", procedure_name);
}
}
}
String8 inst_string = push_str8f(scratch.arena, "%S%S%S%S", addr_part, code_bytes_part, inst.string, symbol_part);
DASM_Line line = {u32_from_u64_saturate(off), 0, inst.jump_dest_vaddr, r1u64(inst_strings.total_size + inst_strings.node_count,
inst_strings.total_size + inst_strings.node_count + inst_string.size)};
dasm_line_chunk_list_push(scratch.arena, &line_list, 1024, &line);
str8_list_push(scratch.arena, &inst_strings, inst_string);
// rjf: increment
off += inst.size;
}
}break;
}
}
//- rjf: artifacts -> value bundle
Arena *info_arena = 0;
DASM_Info info = {0};
if(got_task)
{
//- rjf: produce joined text
Arena *text_arena = arena_alloc();
StringJoin text_join = {0};
text_join.sep = str8_lit("\n");
String8 text = str8_list_join(text_arena, &inst_strings, &text_join);
//- rjf: produce unique key for this disassembly's text
U128 text_key = {0};
{
U64 hash_data[] =
{
hash.u64[0],
hash.u64[1],
params.vaddr,
(U64)params.arch,
(U64)params.style_flags,
(U64)params.syntax,
(U64)rdi,
0x4d534144,
};
text_key = hs_hash_from_data(str8((U8 *)hash_data, sizeof(hash_data)));
}
//- rjf: submit text data to hash store
U128 text_hash = hs_submit_data(text_key, &text_arena, text);
//- rjf: produce value bundle
info_arena = arena_alloc();
info.text_key = text_key;
info.lines = dasm_line_array_from_chunk_list(info_arena, &line_list);
}
//- rjf: commit results to cache
if(got_task) OS_MutexScopeW(stripe->rw_mutex)
{
for(DASM_Node *n = slot->first; n != 0; n = n->next)
{
if(u128_match(n->hash, hash) && dasm_params_match(&n->params, &params))
{
n->info_arena = info_arena;
MemoryCopyStruct(&n->info, &info);
if(rdi != &di_rdi_parsed_nil && params.style_flags & (DASM_StyleFlag_SourceLines|DASM_StyleFlag_SourceFilesNames))
{
n->change_gen = change_gen;
}
else
{
n->change_gen = 0;
}
ins_atomic_u32_eval_assign(&n->is_working, 0);
ins_atomic_u64_inc_eval(&n->load_count);
break;
}
}
}
txt_scope_close(txt_scope);
di_scope_close(di_scope);
hs_scope_close(hs_scope);
scratch_end(scratch);
ProfEnd();
return 0;
} }
//////////////////////////////// ////////////////////////////////
@@ -669,7 +786,7 @@ dasm_evictor_detector_thread__entry_point(void *p)
{ {
U64 change_gen = fs_change_gen(); U64 change_gen = fs_change_gen();
U64 check_time_us = os_now_microseconds(); U64 check_time_us = os_now_microseconds();
U64 check_time_user_clocks = dasm_user_clock_idx(); U64 check_time_user_clocks = update_tick_idx();
U64 evict_threshold_us = 10*1000000; U64 evict_threshold_us = 10*1000000;
U64 retry_threshold_us = 1*1000000; U64 retry_threshold_us = 1*1000000;
U64 evict_threshold_user_clocks = 10; U64 evict_threshold_user_clocks = 10;
@@ -726,6 +843,7 @@ dasm_evictor_detector_thread__entry_point(void *p)
{ {
if(dasm_u2p_enqueue_req(n->hash, &n->params, max_U64)) if(dasm_u2p_enqueue_req(n->hash, &n->params, max_U64))
{ {
async_push_work(dasm_parse_work);
n->last_time_requested_us = os_now_microseconds(); n->last_time_requested_us = os_now_microseconds();
n->last_user_clock_idx_requested = check_time_user_clocks; n->last_user_clock_idx_requested = check_time_user_clocks;
} }
+116 -48
View File
@@ -5,7 +5,76 @@
#define DASM_CACHE_H #define DASM_CACHE_H
//////////////////////////////// ////////////////////////////////
//~ rjf: Stringification Types //~ rjf: Disassembly Syntax Types
typedef enum DASM_Syntax
{
DASM_Syntax_Intel,
DASM_Syntax_ATT,
DASM_Syntax_COUNT
}
DASM_Syntax;
////////////////////////////////
//~ rjf: Disassembly Instruction Info Types
typedef U32 DASM_InstFlags;
enum
{
DASM_InstFlag_Call = (1<<0),
DASM_InstFlag_Branch = (1<<1),
DASM_InstFlag_UnconditionalJump = (1<<2),
DASM_InstFlag_Return = (1<<3),
DASM_InstFlag_NonFlow = (1<<4),
DASM_InstFlag_Repeats = (1<<5),
DASM_InstFlag_ChangesStackPointer = (1<<6),
DASM_InstFlag_ChangesStackPointerVariably = (1<<7),
};
typedef struct DASM_Inst DASM_Inst;
struct DASM_Inst
{
DASM_InstFlags flags;
U32 size;
String8 string;
U64 jump_dest_vaddr;
};
////////////////////////////////
//~ rjf: Control Flow Analysis Types
typedef struct DASM_CtrlFlowPoint DASM_CtrlFlowPoint;
struct DASM_CtrlFlowPoint
{
U64 vaddr;
U64 jump_dest_vaddr;
DASM_InstFlags inst_flags;
};
typedef struct DASM_CtrlFlowPointNode DASM_CtrlFlowPointNode;
struct DASM_CtrlFlowPointNode
{
DASM_CtrlFlowPointNode *next;
DASM_CtrlFlowPoint v;
};
typedef struct DASM_CtrlFlowPointList DASM_CtrlFlowPointList;
struct DASM_CtrlFlowPointList
{
DASM_CtrlFlowPointNode *first;
DASM_CtrlFlowPointNode *last;
U64 count;
};
typedef struct DASM_CtrlFlowInfo DASM_CtrlFlowInfo;
struct DASM_CtrlFlowInfo
{
DASM_CtrlFlowPointList exit_points;
U64 total_size;
};
////////////////////////////////
//~ rjf: Disassembly Text Decoration Types
typedef U32 DASM_StyleFlags; typedef U32 DASM_StyleFlags;
enum enum
@@ -17,14 +86,6 @@ enum
DASM_StyleFlag_SymbolNames = (1<<4), DASM_StyleFlag_SymbolNames = (1<<4),
}; };
typedef enum DASM_Syntax
{
DASM_Syntax_Intel,
DASM_Syntax_ATT,
DASM_Syntax_COUNT
}
DASM_Syntax;
//////////////////////////////// ////////////////////////////////
//~ rjf: Disassembling Parameters Bundle //~ rjf: Disassembling Parameters Bundle
@@ -32,7 +93,7 @@ typedef struct DASM_Params DASM_Params;
struct DASM_Params struct DASM_Params
{ {
U64 vaddr; U64 vaddr;
Architecture arch; Arch arch;
DASM_StyleFlags style_flags; DASM_StyleFlags style_flags;
DASM_Syntax syntax; DASM_Syntax syntax;
U64 base_vaddr; U64 base_vaddr;
@@ -40,48 +101,58 @@ struct DASM_Params
}; };
//////////////////////////////// ////////////////////////////////
//~ rjf: Instruction Types //~ rjf: Disassembly Text Line Types
typedef U32 DASM_InstFlags; typedef U32 DASM_LineFlags;
enum enum
{ {
DASM_InstFlag_Decorative = (1<<0), DASM_LineFlag_Decorative = (1<<0),
}; };
typedef struct DASM_Inst DASM_Inst; typedef struct DASM_Line DASM_Line;
struct DASM_Inst struct DASM_Line
{ {
U32 code_off; U32 code_off;
DASM_InstFlags flags; DASM_LineFlags flags;
U64 addr; U64 addr;
Rng1U64 text_range; Rng1U64 text_range;
}; };
typedef struct DASM_InstChunkNode DASM_InstChunkNode; typedef struct DASM_LineChunkNode DASM_LineChunkNode;
struct DASM_InstChunkNode struct DASM_LineChunkNode
{ {
DASM_InstChunkNode *next; DASM_LineChunkNode *next;
DASM_Inst *v; DASM_Line *v;
U64 cap; U64 cap;
U64 count; U64 count;
}; };
typedef struct DASM_InstChunkList DASM_InstChunkList; typedef struct DASM_LineChunkList DASM_LineChunkList;
struct DASM_InstChunkList struct DASM_LineChunkList
{ {
DASM_InstChunkNode *first; DASM_LineChunkNode *first;
DASM_InstChunkNode *last; DASM_LineChunkNode *last;
U64 node_count; U64 node_count;
U64 inst_count; U64 line_count;
}; };
typedef struct DASM_InstArray DASM_InstArray; typedef struct DASM_LineArray DASM_LineArray;
struct DASM_InstArray struct DASM_LineArray
{ {
DASM_Inst *v; DASM_Line *v;
U64 count; U64 count;
}; };
////////////////////////////////
//~ rjf: Disassembly Result Bundle
typedef struct DASM_Result DASM_Result;
struct DASM_Result
{
String8 text;
DASM_LineArray lines;
};
//////////////////////////////// ////////////////////////////////
//~ rjf: Value Bundle Type //~ rjf: Value Bundle Type
@@ -89,7 +160,7 @@ typedef struct DASM_Info DASM_Info;
struct DASM_Info struct DASM_Info
{ {
U128 text_key; U128 text_key;
DASM_InstArray insts; DASM_LineArray lines;
}; };
//////////////////////////////// ////////////////////////////////
@@ -175,9 +246,6 @@ struct DASM_Shared
{ {
Arena *arena; Arena *arena;
// rjf: user clock
U64 user_clock_idx;
// rjf: cache // rjf: cache
U64 slots_count; U64 slots_count;
U64 stripes_count; U64 stripes_count;
@@ -192,10 +260,6 @@ struct DASM_Shared
OS_Handle u2p_ring_cv; OS_Handle u2p_ring_cv;
OS_Handle u2p_ring_mutex; OS_Handle u2p_ring_mutex;
// rjf: parse threads
U64 parse_thread_count;
OS_Handle *parse_threads;
// rjf: evictor/detector thread // rjf: evictor/detector thread
OS_Handle evictor_detector_thread; OS_Handle evictor_detector_thread;
}; };
@@ -206,30 +270,34 @@ struct DASM_Shared
thread_static DASM_TCTX *dasm_tctx = 0; thread_static DASM_TCTX *dasm_tctx = 0;
global DASM_Shared *dasm_shared = 0; global DASM_Shared *dasm_shared = 0;
////////////////////////////////
//~ rjf: Instruction Decoding/Disassembling Type Functions
internal DASM_Inst dasm_inst_from_code(Arena *arena, Arch arch, U64 vaddr, String8 code, DASM_Syntax syntax);
////////////////////////////////
//~ rjf: Control Flow Analysis
internal DASM_CtrlFlowInfo dasm_ctrl_flow_info_from_arch_vaddr_code(Arena *arena, DASM_InstFlags exit_points_mask, Arch arch, U64 vaddr, String8 code);
//////////////////////////////// ////////////////////////////////
//~ rjf: Parameter Type Functions //~ rjf: Parameter Type Functions
internal B32 dasm_params_match(DASM_Params *a, DASM_Params *b); internal B32 dasm_params_match(DASM_Params *a, DASM_Params *b);
//////////////////////////////// ////////////////////////////////
//~ rjf: Instruction Type Functions //~ rjf: Line Type Functions
internal void dasm_inst_chunk_list_push(Arena *arena, DASM_InstChunkList *list, U64 cap, DASM_Inst *inst); internal void dasm_line_chunk_list_push(Arena *arena, DASM_LineChunkList *list, U64 cap, DASM_Line *line);
internal DASM_InstArray dasm_inst_array_from_chunk_list(Arena *arena, DASM_InstChunkList *list); internal DASM_LineArray dasm_line_array_from_chunk_list(Arena *arena, DASM_LineChunkList *list);
internal U64 dasm_inst_array_idx_from_code_off__linear_scan(DASM_InstArray *array, U64 off); internal U64 dasm_line_array_idx_from_code_off__linear_scan(DASM_LineArray *array, U64 off);
internal U64 dasm_inst_array_code_off_from_idx(DASM_InstArray *array, U64 idx); internal U64 dasm_line_array_code_off_from_idx(DASM_LineArray *array, U64 idx);
//////////////////////////////// ////////////////////////////////
//~ rjf: Main Layer Initialization //~ rjf: Main Layer Initialization
internal void dasm_init(void); internal void dasm_init(void);
////////////////////////////////
//~ rjf: User Clock
internal void dasm_user_clock_tick(void);
internal U64 dasm_user_clock_idx(void);
//////////////////////////////// ////////////////////////////////
//~ rjf: Scoped Access //~ rjf: Scoped Access
@@ -248,7 +316,7 @@ internal DASM_Info dasm_info_from_key_params(DASM_Scope *scope, U128 key, DASM_P
internal B32 dasm_u2p_enqueue_req(U128 hash, DASM_Params *params, U64 endt_us); internal B32 dasm_u2p_enqueue_req(U128 hash, DASM_Params *params, U64 endt_us);
internal void dasm_u2p_dequeue_req(Arena *arena, U128 *hash_out, DASM_Params *params_out); internal void dasm_u2p_dequeue_req(Arena *arena, U128 *hash_out, DASM_Params *params_out);
internal void dasm_parse_thread__entry_point(void *p); ASYNC_WORK_DEF(dasm_parse_work);
//////////////////////////////// ////////////////////////////////
//~ rjf: Evictor/Detector Thread //~ rjf: Evictor/Detector Thread
+132
View File
@@ -0,0 +1,132 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Built-In Command Tables
@table(name ui_vis ipc_docs_vis q_slot q_view q_ent_kind q_ctrl_ent_kind q_allow_files q_allow_folders q_keep_oi q_select_oi q_is_code q_required canonical_icon string display_name desc search_tags )
// / | | | \___ _________________________________/ | | | | |
// / | | | \ / | | | | |
D_CmdTable: // | | | | | | | | | |
{
//- rjf: low-level target control operations
{LaunchAndRun 1 1 Entity null Target Null 0 0 0 0 0 1 Play "launch_and_run" "Launch and Run" "Starts debugging a new instance of a target, then runs." "launch,start,run,target" }
{LaunchAndInit 1 1 Entity null Target Null 0 0 0 0 0 1 PlayStepForward "launch_and_init" "Launch and Initialize" "Starts debugging a new instance of a target, then stops at the program's entry point." "launch,start,entry,point" }
{Kill 1 1 Process null Nil Process 0 0 0 0 0 1 X "kill" "Kill" "Kills the specified existing attached process(es)." "stop,kill" }
{KillAll 1 1 Null null Nil Null 0 0 0 0 0 0 Stop "kill_all" "Kill All" "Kills all attached processes." "stop,kill,all" }
{Detach 1 1 Process null Nil Process 0 0 0 0 0 1 Null "detach" "Detach" "Detaches the specified attached process(es)." "detach" }
{Continue 1 1 Null null Nil Null 0 0 0 0 0 0 Play "continue" "Continue" "Continues executing all attached processes." "" }
{StepIntoInst 1 1 Null null Nil Null 0 0 0 0 0 0 StepInto "step_into_inst" "Step Into (Assembly)" "Performs a step that goes into calls, at the instruction level." "single,step,thread" }
{StepOverInst 1 1 Null null Nil Null 0 0 0 0 0 0 StepOver "step_over_inst" "Step Over (Assembly)" "Performs a step that skips calls, at the instruction level." "single,step,thread" }
{StepIntoLine 1 1 Null null Nil Null 0 0 0 0 0 0 StepInto "step_into_line" "Step Into (Line)" "Performs a step that goes into calls, at the source code line level." "step,thread" }
{StepOverLine 1 1 Null null Nil Null 0 0 0 0 0 0 StepOver "step_over_line" "Step Over (Line)" "Performs a step that skips calls, at the source code line level." "step,thread" }
{StepOut 1 1 Null null Nil Null 0 0 0 0 0 0 StepOut "step_out" "Step Out" "Runs to the end of the current function and exits it." "" }
{Halt 1 1 Null null Nil Null 0 0 0 0 0 0 Pause "halt" "Halt" "Halts all attached processes." "pause" }
{SoftHaltRefresh 1 1 Null null Nil Null 0 0 0 0 0 0 Refresh "soft_halt_refresh" "Soft Halt Refresh" "Interrupts all attached processes to collect data, and then resumes them." "" }
{SetThreadIP 0 1 Vaddr null Nil Null 0 0 0 0 1 1 Null "set_thread_ip" "Set Thread IP" "Sets the specified thread's instruction pointer at the specified address." "" }
//- rjf: high-level composite target control operations
{RunToLine 0 1 Null null Nil Null 0 0 0 0 0 0 Play "run_to_line" "Run To Line" "Runs until a particular source line is hit." "" }
{RunToAddress 1 1 Vaddr null Nil Null 0 0 0 0 1 1 PlayStepForward "run_to_address" "Run To Address" "Runs until a particular address is hit." "" }
{Run 1 1 Null null Nil Null 0 0 0 0 0 0 Play "run" "Run" "Runs all targets after starting them if they have not been started yet." "play" }
{Restart 1 1 Null null Nil Null 0 0 0 0 0 0 Redo "restart" "Restart" "Kills all attached processes, then launches all active targets." "restart,retry" }
{StepInto 1 1 Null null Nil Null 0 0 0 0 0 0 StepInto "step_into" "Step Into" "Steps once, possibly into function calls, for either source lines or instructions (whichever is selected)." "" }
{StepOver 1 1 Null null Nil Null 0 0 0 0 0 0 StepOver "step_over" "Step Over" "Steps once, always over function calls, for either source lines or instructions." "" }
//- rjf: debug control context management operations
{FreezeThread 1 1 Thread null Nil Thread 0 0 0 0 0 1 Locked "freeze_thread" "Freeze Thread" "Freezes the passed thread." "callstack,unwind" }
{ThawThread 1 1 Thread null Nil Thread 0 0 0 0 0 1 Unlocked "thaw_thread" "Thaw Thread" "Thaws the passed thread." "" }
{FreezeProcess 1 1 Process null Nil Process 0 0 0 0 0 1 Locked "freeze_process" "Freeze Process" "Freezes the passed process." "" }
{ThawProcess 1 1 Process null Nil Process 0 0 0 0 0 1 Unlocked "thaw_process" "Thaw Process" "Thaws the passed process." "" }
{FreezeMachine 0 1 Machine null Nil Machine 0 0 0 0 0 1 Locked "freeze_machine" "Freeze Machine" "Freezes the passed machine." "" }
{ThawMachine 0 1 Machine null Nil Machine 0 0 0 0 0 1 Unlocked "thaw_machine" "Thaw Machine" "Thaws the passed machine." "" }
{FreezeLocalMachine 1 1 Null null Nil Null 0 0 0 0 0 0 Machine "freeze_local_machine" "Freeze Local Machine" "Freezes the local machine." "" }
{ThawLocalMachine 1 1 Null null Nil Null 0 0 0 0 0 0 Machine "thaw_local_machine" "Thaw Local Machine" "Thaws the local machine." "" }
{FreezeEntity 0 0 Null null Nil Null 0 0 0 0 0 0 Null "freeze_entity" "Freeze Entity" "Freezes an entity." "" }
{ThawEntity 0 0 Null null Nil Null 0 0 0 0 0 0 Null "thaw_entity" "Thaw Entity" "Thaws an entity." "" }
//- rjf: entity decoration
{SetEntityColor 0 0 Null null Nil Null 0 0 0 0 0 0 Null "set_entity_color" "Set Entity Color" "Sets the passed entity's color." "" }
{SetEntityName 0 0 Null null Nil Null 0 0 0 0 0 0 Null "set_entity_name" "Set Entity Name" "Sets the passed entity's name." "" }
//- rjf: attaching
{Attach 1 1 PID null Nil Null 0 0 0 0 0 1 Null "attach" "Attach" "Attaches to a process that is already running on the local machine." "" }
}
@enum D_CmdKind:
{
Null,
@expand(D_CmdTable, a) `$(a.name)`,
COUNT,
}
////////////////////////////////
//~ rjf: Built-In VieNull w Rules
@table(coverage_check name name_lower string ih ex xp vb display_name docs schema description)
D_ViewRuleTable:
{
{x Default default "default" - - - x "Default" - "" "" }
{x Array array "array" - - x - "Array" x "x:{expr}" "Specifies that a pointer points to N elements, rather than only 1." }
{x Slice slice "slice" - - x - "Slice" x "" "Specifies that a pointer within a struct, also containing an integer, points to the number of elements encoded by the integer." }
{- List list "list" - - - x "List" - "x:{member}" "Specifies that some struct, union, or class forms the top of a linked list, and the member which points at the following element in the list." }
{x ByteSwap bswap "bswap" x - x - "Byte Swap" x "" "Specifies that all integral evaluations should be byte-swapped, such that their endianness is reversed." }
{x Cast cast "cast" - - x - "Cast" x "x:{type}" "Specifies that the expression to which the view rule is applied should be casted to the provided type." }
{- BaseDec base_dec "dec" x - - - "Decimal Base (Base 10)" x "" "Specifies that all integral evaluations should appear in base-10 form." }
{- BaseBin base_bin "bin" x - - - "Binary Base (Base 2)" x "" "Specifies that all integral evaluations should appear in base-2 form." }
{- BaseOct base_oct "oct" x - - - "Octal Base (Base 8)" x "" "Specifies that all integral evaluations should appear in base-8 form." }
{- BaseHex base_hex "hex" x - - - "Hexadecimal Base (Base 16)" x "" "Specifies that all integral evaluations should appear in base-16 form." }
{- Only only "only" x - - x "Only Specified Members" x "x:{member}" "Specifies that only the specified members should appear in struct, union, or class evaluations." }
{- Omit omit "omit" x - - x "Omit Specified Members" x "x:{member}" "Omits a list of member names from appearing in struct, union, or class evaluations." }
{- NoAddr no_addr "no_addr" x - - - "Disable Address Values" x "" "Displays only what pointers point to, if possible, without the pointer's address value." }
{x Checkbox checkbox "checkbox" - - - - "Checkbox" x "" "Displays simple integer values as checkboxes, encoding zero or nonzero values." }
{- ColorRGBA color_rgba "color_rgba" - x - x "Color (RGBA)" x "" "Displays as a color, interpreting the data as encoding R, G, B, and A values." }
{x Text text "text" - x - x "Text" x "x:{'lang':lang, 'size':expr}" "Displays as text." }
{x Disasm disasm "disasm" - x - x "Disassembly" x "x:{'arch':arch, 'size':expr}" "Displays as disassembled instructions, interpreting the data as raw machine code." }
{x Memory memory "memory" - x - x "Memory" x "x:{'size':expr}" "Displays as a raw memory grid." }
{- Graph graph "graph" - x - x "Graph" x "" "Displays as a pointer graph, visualizing nodes and edges formed by pointers directly." }
{x Bitmap bitmap "bitmap" - x - x "Bitmap" x "x:{'w':expr, 'h':expr, 'fmt':tex2dformat}" "Displays as a bitmap, interpreting the data as raw pixel data." }
{- Geo3D geo3d "geo3d" - x - x "Geometry (3D)" x "x:{'count':expr, 'vtx':expr, 'vtx_size':expr}" "Displays as geometry, interpreting the data as index or vertex data." }
}
@enum D_ViewRuleKind:
{
@expand(D_ViewRuleTable a) `$(a.name)`,
COUNT,
}
@data(D_ViewRuleSpecInfo) @c_file d_core_view_rule_spec_info_table:
{
@expand(D_ViewRuleTable a)
```{str8_lit_comp("$(a.string)"), str8_lit_comp("$(a.display_name)"), str8_lit_comp("$(a.schema)"), str8_lit_comp("$(a.description)"), (D_ViewRuleSpecInfoFlag_Inherited*$(a.ih == "x"))|(D_ViewRuleSpecInfoFlag_Expandable*$(a.ex == "x"))|(D_ViewRuleSpecInfoFlag_ExprResolution*$(a.xp == "x"))|(D_ViewRuleSpecInfoFlag_VizBlockProd*$(a.vb == "x")), }```;
}
////////////////////////////////
//~ rjf: Developer Toggles
@table(name)
D_DevToggleTable:
{
{simulate_lag}
{draw_ui_text_pos}
{draw_ui_focus_debug}
{draw_ui_box_heatmap}
{eval_compiler_tooltips}
{eval_watch_key_tooltips}
{cmd_context_tooltips}
{scratch_mouse_draw}
{updating_indicator}
}
@gen
{
@expand(D_DevToggleTable a) `global B32 DEV_$(a.name) = 0;`
}
@gen
{
`struct {B32 *value_ptr; String8 name;} DEV_toggle_table[] =`;
`{`;
@expand(D_DevToggleTable a) `{&DEV_$(a.name), str8_lit_comp("$(a.name)")},`
`};`;
}
File diff suppressed because it is too large Load Diff
+499
View File
@@ -0,0 +1,499 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef DBG_ENGINE_CORE_H
#define DBG_ENGINE_CORE_H
////////////////////////////////
//~ rjf: Tick Input Types
typedef struct D_Target D_Target;
struct D_Target
{
String8 exe;
String8 args;
String8 working_directory;
String8 custom_entry_point_name;
String8 stdout_path;
String8 stderr_path;
String8 stdin_path;
B32 debug_subprocesses;
String8List env;
};
typedef struct D_TargetArray D_TargetArray;
struct D_TargetArray
{
D_Target *v;
U64 count;
};
typedef struct D_Breakpoint D_Breakpoint;
struct D_Breakpoint
{
String8 file_path;
TxtPt pt;
String8 symbol_name;
U64 vaddr;
String8 condition;
};
typedef struct D_BreakpointArray D_BreakpointArray;
struct D_BreakpointArray
{
D_Breakpoint *v;
U64 count;
};
typedef struct D_PathMap D_PathMap;
struct D_PathMap
{
String8 src;
String8 dst;
};
typedef struct D_PathMapArray D_PathMapArray;
struct D_PathMapArray
{
D_PathMap *v;
U64 count;
};
////////////////////////////////
//~ rjf: Tick Output Types
typedef enum D_EventKind
{
D_EventKind_Null,
D_EventKind_ProcessEnd,
D_EventKind_Stop,
D_EventKind_COUNT
}
D_EventKind;
typedef enum D_EventCause
{
D_EventCause_Null,
D_EventCause_UserBreakpoint,
D_EventCause_Halt,
D_EventCause_COUNT
}
D_EventCause;
typedef struct D_Event D_Event;
struct D_Event
{
D_EventKind kind;
D_EventCause cause;
CTRL_Handle thread;
U64 vaddr;
U64 code;
};
typedef struct D_EventNode D_EventNode;
struct D_EventNode
{
D_EventNode *next;
D_Event v;
};
typedef struct D_EventList D_EventList;
struct D_EventList
{
D_EventNode *first;
D_EventNode *last;
U64 count;
};
////////////////////////////////
//~ rjf: Line Info Types
typedef struct D_Line D_Line;
struct D_Line
{
String8 file_path;
TxtPt pt;
Rng1U64 voff_range;
DI_Key dbgi_key;
};
typedef struct D_LineNode D_LineNode;
struct D_LineNode
{
D_LineNode *next;
D_Line v;
};
typedef struct D_LineList D_LineList;
struct D_LineList
{
D_LineNode *first;
D_LineNode *last;
U64 count;
};
typedef struct D_LineListArray D_LineListArray;
struct D_LineListArray
{
D_LineList *v;
U64 count;
DI_KeyList dbgi_keys;
};
////////////////////////////////
//~ rjf: Debug Engine Control Communication Types
typedef enum D_RunKind
{
D_RunKind_Run,
D_RunKind_SingleStep,
D_RunKind_Step,
D_RunKind_COUNT
}
D_RunKind;
////////////////////////////////
//~ rjf: Generated Code
#include "dbg_engine/generated/dbg_engine.meta.h"
////////////////////////////////
//~ rjf: View Rules
typedef U32 D_ViewRuleSpecInfoFlags; // NOTE(rjf): see @view_rule_info
enum
{
D_ViewRuleSpecInfoFlag_Inherited = (1<<0),
D_ViewRuleSpecInfoFlag_Expandable = (1<<1),
D_ViewRuleSpecInfoFlag_ExprResolution = (1<<2),
D_ViewRuleSpecInfoFlag_VizBlockProd = (1<<3),
};
typedef struct D_ViewRuleSpecInfo D_ViewRuleSpecInfo;
struct D_ViewRuleSpecInfo
{
String8 string;
String8 display_string;
String8 schema;
String8 description;
D_ViewRuleSpecInfoFlags flags;
};
typedef struct D_ViewRuleSpecInfoArray D_ViewRuleSpecInfoArray;
struct D_ViewRuleSpecInfoArray
{
D_ViewRuleSpecInfo *v;
U64 count;
};
typedef struct D_ViewRuleSpec D_ViewRuleSpec;
struct D_ViewRuleSpec
{
D_ViewRuleSpec *hash_next;
D_ViewRuleSpecInfo info;
};
////////////////////////////////
//~ rjf: Command Types
typedef struct D_CmdParams D_CmdParams;
struct D_CmdParams
{
CTRL_Handle machine;
CTRL_Handle process;
CTRL_Handle thread;
CTRL_Handle entity;
String8 string;
String8 file_path;
TxtPt cursor;
U64 vaddr;
B32 prefer_disasm;
U32 pid;
U32 rgba;
D_TargetArray targets;
};
typedef struct D_Cmd D_Cmd;
struct D_Cmd
{
D_CmdKind kind;
D_CmdParams params;
};
typedef struct D_CmdNode D_CmdNode;
struct D_CmdNode
{
D_CmdNode *next;
D_CmdNode *prev;
D_Cmd cmd;
};
typedef struct D_CmdList D_CmdList;
struct D_CmdList
{
D_CmdNode *first;
D_CmdNode *last;
U64 count;
};
////////////////////////////////
//~ rjf: Main State Caches
//- rjf: per-thread unwind cache
typedef struct D_UnwindCacheNode D_UnwindCacheNode;
struct D_UnwindCacheNode
{
D_UnwindCacheNode *next;
D_UnwindCacheNode *prev;
U64 reggen;
U64 memgen;
Arena *arena;
CTRL_Handle thread;
CTRL_Unwind unwind;
};
typedef struct D_UnwindCacheSlot D_UnwindCacheSlot;
struct D_UnwindCacheSlot
{
D_UnwindCacheNode *first;
D_UnwindCacheNode *last;
};
typedef struct D_UnwindCache D_UnwindCache;
struct D_UnwindCache
{
U64 slots_count;
D_UnwindCacheSlot *slots;
D_UnwindCacheNode *free_node;
};
//- rjf: per-run tls-base-vaddr cache
typedef struct D_RunTLSBaseCacheNode D_RunTLSBaseCacheNode;
struct D_RunTLSBaseCacheNode
{
D_RunTLSBaseCacheNode *hash_next;
CTRL_Handle process;
U64 root_vaddr;
U64 rip_vaddr;
U64 tls_base_vaddr;
};
typedef struct D_RunTLSBaseCacheSlot D_RunTLSBaseCacheSlot;
struct D_RunTLSBaseCacheSlot
{
D_RunTLSBaseCacheNode *first;
D_RunTLSBaseCacheNode *last;
};
typedef struct D_RunTLSBaseCache D_RunTLSBaseCache;
struct D_RunTLSBaseCache
{
Arena *arena;
U64 slots_count;
D_RunTLSBaseCacheSlot *slots;
};
//- rjf: per-run locals cache
typedef struct D_RunLocalsCacheNode D_RunLocalsCacheNode;
struct D_RunLocalsCacheNode
{
D_RunLocalsCacheNode *hash_next;
DI_Key dbgi_key;
U64 voff;
E_String2NumMap *locals_map;
};
typedef struct D_RunLocalsCacheSlot D_RunLocalsCacheSlot;
struct D_RunLocalsCacheSlot
{
D_RunLocalsCacheNode *first;
D_RunLocalsCacheNode *last;
};
typedef struct D_RunLocalsCache D_RunLocalsCache;
struct D_RunLocalsCache
{
Arena *arena;
U64 table_size;
D_RunLocalsCacheSlot *table;
};
////////////////////////////////
//~ rjf: Main State Types
typedef struct D_State D_State;
struct D_State
{
// rjf: top-level state
Arena *arena;
U64 frame_index;
U64 frame_eval_memread_endt_us;
// rjf: commands
Arena *cmds_arena;
D_CmdList cmds;
// rjf: output log key
U128 output_log_key;
// rjf: per-run caches
D_UnwindCache unwind_cache;
U64 tls_base_cache_reggen_idx;
U64 tls_base_cache_memgen_idx;
D_RunTLSBaseCache tls_base_caches[2];
U64 tls_base_cache_gen;
U64 locals_cache_reggen_idx;
D_RunLocalsCache locals_caches[2];
U64 locals_cache_gen;
U64 member_cache_reggen_idx;
D_RunLocalsCache member_caches[2];
U64 member_cache_gen;
// rjf: view rule specification table
U64 view_rule_spec_table_size;
D_ViewRuleSpec **view_rule_spec_table;
// rjf: user -> ctrl driving state
Arena *ctrl_last_run_arena;
D_RunKind ctrl_last_run_kind;
U64 ctrl_last_run_frame_idx;
CTRL_Handle ctrl_last_run_thread_handle;
CTRL_RunFlags ctrl_last_run_flags;
CTRL_TrapList ctrl_last_run_traps;
D_BreakpointArray ctrl_last_run_extra_bps;
U128 ctrl_last_run_param_state_hash;
B32 ctrl_is_running;
B32 ctrl_thread_run_state;
B32 ctrl_soft_halt_issued;
Arena *ctrl_msg_arena;
CTRL_MsgList ctrl_msgs;
// rjf: ctrl -> user reading state
CTRL_EntityStore *ctrl_entity_store;
Arena *ctrl_stop_arena;
CTRL_Event ctrl_last_stop_event;
};
////////////////////////////////
//~ rjf: Globals
read_only global D_ViewRuleSpec d_nil_core_view_rule_spec = {0};
global D_State *d_state = 0;
////////////////////////////////
//~ rjf: Basic Helpers
internal U64 d_hash_from_seed_string(U64 seed, String8 string);
internal U64 d_hash_from_string(String8 string);
internal U64 d_hash_from_seed_string__case_insensitive(U64 seed, String8 string);
internal U64 d_hash_from_string__case_insensitive(String8 string);
////////////////////////////////
//~ rjf: Breakpoints
internal D_BreakpointArray d_breakpoint_array_copy(Arena *arena, D_BreakpointArray *src);
////////////////////////////////
//~ rjf: Path Map Application
internal String8List d_possible_path_overrides_from_maps_path(Arena *arena, D_PathMapArray *path_maps, String8 file_path);
////////////////////////////////
//~ rjf: Debug Info Extraction Type Pure Functions
internal D_LineList d_line_list_copy(Arena *arena, D_LineList *list);
////////////////////////////////
//~ rjf: Command Type Functions
//- rjf: command parameters
internal D_CmdParams d_cmd_params_copy(Arena *arena, D_CmdParams *src);
//- rjf: command lists
internal void d_cmd_list_push_new(Arena *arena, D_CmdList *cmds, D_CmdKind kind, D_CmdParams *params);
////////////////////////////////
//~ rjf: View Rule Spec Stateful Functions
internal void d_register_view_rule_specs(D_ViewRuleSpecInfoArray specs);
internal D_ViewRuleSpec *d_view_rule_spec_from_string(String8 string);
////////////////////////////////
//~ rjf: Stepping "Trap Net" Builders
internal CTRL_TrapList d_trap_net_from_thread__step_over_inst(Arena *arena, CTRL_Entity *thread);
internal CTRL_TrapList d_trap_net_from_thread__step_over_line(Arena *arena, CTRL_Entity *thread);
internal CTRL_TrapList d_trap_net_from_thread__step_into_line(Arena *arena, CTRL_Entity *thread);
////////////////////////////////
//~ rjf: Debug Info Lookups
//- rjf: voff|vaddr -> symbol lookups
internal String8 d_symbol_name_from_dbgi_key_voff(Arena *arena, DI_Key *dbgi_key, U64 voff, B32 decorated);
internal String8 d_symbol_name_from_process_vaddr(Arena *arena, CTRL_Entity *process, U64 vaddr, B32 decorated);
//- rjf: symbol -> voff lookups
internal U64 d_voff_from_dbgi_key_symbol_name(DI_Key *dbgi_key, String8 symbol_name);
internal U64 d_type_num_from_dbgi_key_name(DI_Key *dbgi_key, String8 name);
//- rjf: voff -> line info
internal D_LineList d_lines_from_dbgi_key_voff(Arena *arena, DI_Key *dbgi_key, U64 voff);
//- rjf: file:line -> line info
// TODO(rjf): this depends on file path maps, needs to move
// TODO(rjf): need to clean this up & dedup
internal D_LineListArray d_lines_array_from_dbgi_key_file_path_line_range(Arena *arena, DI_Key dbgi_key, String8 file_path, Rng1S64 line_num_range);
internal D_LineListArray d_lines_array_from_file_path_line_range(Arena *arena, String8 file_path, Rng1S64 line_num_range);
internal D_LineList d_lines_from_dbgi_key_file_path_line_num(Arena *arena, DI_Key dbgi_key, String8 file_path, S64 line_num);
internal D_LineList d_lines_from_file_path_line_num(Arena *arena, String8 file_path, S64 line_num);
////////////////////////////////
//~ rjf: Process/Thread/Module Info Lookups
internal U64 d_tls_base_vaddr_from_process_root_rip(CTRL_Entity *process, U64 root_vaddr, U64 rip_vaddr);
////////////////////////////////
//~ rjf: Target Controls
//- rjf: stopped info from the control thread
internal CTRL_Event d_ctrl_last_stop_event(void);
////////////////////////////////
//~ rjf: Main State Accessors/Mutators
//- rjf: frame data
internal U64 d_frame_index(void);
//- rjf: control state
internal D_RunKind d_ctrl_last_run_kind(void);
internal U64 d_ctrl_last_run_frame_idx(void);
internal B32 d_ctrl_targets_running(void);
//- rjf: active entity based queries
internal DI_KeyList d_push_active_dbgi_key_list(Arena *arena);
//- rjf: per-run caches
internal CTRL_Unwind d_query_cached_unwind_from_thread(CTRL_Entity *thread);
internal U64 d_query_cached_rip_from_thread(CTRL_Entity *thread);
internal U64 d_query_cached_rip_from_thread_unwind(CTRL_Entity *thread, U64 unwind_count);
internal U64 d_query_cached_tls_base_vaddr_from_process_root_rip(CTRL_Entity *process, U64 root_vaddr, U64 rip_vaddr);
internal E_String2NumMap *d_query_cached_locals_map_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff);
internal E_String2NumMap *d_query_cached_member_map_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff);
//- rjf: top-level command dispatch
internal void d_push_cmd(D_CmdKind kind, D_CmdParams *params);
#define d_cmd(kind, ...) d_push_cmd((kind), &(D_CmdParams){.thread = {0}, __VA_ARGS__})
//- rjf: command iteration
internal B32 d_next_cmd(D_Cmd **cmd);
////////////////////////////////
//~ rjf: Main Layer Top-Level Calls
internal void d_init(void);
internal D_EventList d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_PathMapArray *path_maps, U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64], CTRL_MetaEvalArray *meta_evals);
#endif // DBG_ENGINE_CORE_H
+4
View File
@@ -0,0 +1,4 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#include "dbg_engine_core.c"
+9
View File
@@ -0,0 +1,9 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef DBG_ENGINE_INC_H
#define DBG_ENGINE_INC_H
#include "dbg_engine_core.h"
#endif // DBG_ENGINE_INC_H
@@ -0,0 +1,33 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
//- GENERATED CODE
C_LINKAGE_BEGIN
D_ViewRuleSpecInfo d_core_view_rule_spec_info_table[21] =
{
{str8_lit_comp("default"), str8_lit_comp("Default"), str8_lit_comp(""), str8_lit_comp(""), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("array"), str8_lit_comp("Array"), str8_lit_comp("x:{expr}"), str8_lit_comp("Specifies that a pointer points to N elements, rather than only 1."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*1)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("slice"), str8_lit_comp("Slice"), str8_lit_comp(""), str8_lit_comp("Specifies that a pointer within a struct, also containing an integer, points to the number of elements encoded by the integer."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*1)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("list"), str8_lit_comp("List"), str8_lit_comp("x:{member}"), str8_lit_comp("Specifies that some struct, union, or class forms the top of a linked list, and the member which points at the following element in the list."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("bswap"), str8_lit_comp("Byte Swap"), str8_lit_comp(""), str8_lit_comp("Specifies that all integral evaluations should be byte-swapped, such that their endianness is reversed."), (D_ViewRuleSpecInfoFlag_Inherited*1)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*1)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("cast"), str8_lit_comp("Cast"), str8_lit_comp("x:{type}"), str8_lit_comp("Specifies that the expression to which the view rule is applied should be casted to the provided type."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*1)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("dec"), str8_lit_comp("Decimal Base (Base 10)"), str8_lit_comp(""), str8_lit_comp("Specifies that all integral evaluations should appear in base-10 form."), (D_ViewRuleSpecInfoFlag_Inherited*1)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("bin"), str8_lit_comp("Binary Base (Base 2)"), str8_lit_comp(""), str8_lit_comp("Specifies that all integral evaluations should appear in base-2 form."), (D_ViewRuleSpecInfoFlag_Inherited*1)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("oct"), str8_lit_comp("Octal Base (Base 8)"), str8_lit_comp(""), str8_lit_comp("Specifies that all integral evaluations should appear in base-8 form."), (D_ViewRuleSpecInfoFlag_Inherited*1)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("hex"), str8_lit_comp("Hexadecimal Base (Base 16)"), str8_lit_comp(""), str8_lit_comp("Specifies that all integral evaluations should appear in base-16 form."), (D_ViewRuleSpecInfoFlag_Inherited*1)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("only"), str8_lit_comp("Only Specified Members"), str8_lit_comp("x:{member}"), str8_lit_comp("Specifies that only the specified members should appear in struct, union, or class evaluations."), (D_ViewRuleSpecInfoFlag_Inherited*1)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("omit"), str8_lit_comp("Omit Specified Members"), str8_lit_comp("x:{member}"), str8_lit_comp("Omits a list of member names from appearing in struct, union, or class evaluations."), (D_ViewRuleSpecInfoFlag_Inherited*1)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("no_addr"), str8_lit_comp("Disable Address Values"), str8_lit_comp(""), str8_lit_comp("Displays only what pointers point to, if possible, without the pointer's address value."), (D_ViewRuleSpecInfoFlag_Inherited*1)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("checkbox"), str8_lit_comp("Checkbox"), str8_lit_comp(""), str8_lit_comp("Displays simple integer values as checkboxes, encoding zero or nonzero values."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("color_rgba"), str8_lit_comp("Color (RGBA)"), str8_lit_comp(""), str8_lit_comp("Displays as a color, interpreting the data as encoding R, G, B, and A values."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*1)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("text"), str8_lit_comp("Text"), str8_lit_comp("x:{'lang':lang, 'size':expr}"), str8_lit_comp("Displays as text."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*1)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("disasm"), str8_lit_comp("Disassembly"), str8_lit_comp("x:{'arch':arch, 'size':expr}"), str8_lit_comp("Displays as disassembled instructions, interpreting the data as raw machine code."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*1)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("memory"), str8_lit_comp("Memory"), str8_lit_comp("x:{'size':expr}"), str8_lit_comp("Displays as a raw memory grid."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*1)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("graph"), str8_lit_comp("Graph"), str8_lit_comp(""), str8_lit_comp("Displays as a pointer graph, visualizing nodes and edges formed by pointers directly."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*1)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("bitmap"), str8_lit_comp("Bitmap"), str8_lit_comp("x:{'w':expr, 'h':expr, 'fmt':tex2dformat}"), str8_lit_comp("Displays as a bitmap, interpreting the data as raw pixel data."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*1)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("geo3d"), str8_lit_comp("Geometry (3D)"), str8_lit_comp("x:{'count':expr, 'vtx':expr, 'vtx_size':expr}"), str8_lit_comp("Displays as geometry, interpreting the data as index or vertex data."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*1)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
};
C_LINKAGE_END
@@ -0,0 +1,95 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
//- GENERATED CODE
#ifndef DBG_ENGINE_META_H
#define DBG_ENGINE_META_H
typedef enum D_CmdKind
{
D_CmdKind_Null,
D_CmdKind_LaunchAndRun,
D_CmdKind_LaunchAndInit,
D_CmdKind_Kill,
D_CmdKind_KillAll,
D_CmdKind_Detach,
D_CmdKind_Continue,
D_CmdKind_StepIntoInst,
D_CmdKind_StepOverInst,
D_CmdKind_StepIntoLine,
D_CmdKind_StepOverLine,
D_CmdKind_StepOut,
D_CmdKind_Halt,
D_CmdKind_SoftHaltRefresh,
D_CmdKind_SetThreadIP,
D_CmdKind_RunToLine,
D_CmdKind_RunToAddress,
D_CmdKind_Run,
D_CmdKind_Restart,
D_CmdKind_StepInto,
D_CmdKind_StepOver,
D_CmdKind_FreezeThread,
D_CmdKind_ThawThread,
D_CmdKind_FreezeProcess,
D_CmdKind_ThawProcess,
D_CmdKind_FreezeMachine,
D_CmdKind_ThawMachine,
D_CmdKind_FreezeLocalMachine,
D_CmdKind_ThawLocalMachine,
D_CmdKind_FreezeEntity,
D_CmdKind_ThawEntity,
D_CmdKind_SetEntityColor,
D_CmdKind_SetEntityName,
D_CmdKind_Attach,
D_CmdKind_COUNT,
} D_CmdKind;
typedef enum D_ViewRuleKind
{
D_ViewRuleKind_Default,
D_ViewRuleKind_Array,
D_ViewRuleKind_Slice,
D_ViewRuleKind_List,
D_ViewRuleKind_ByteSwap,
D_ViewRuleKind_Cast,
D_ViewRuleKind_BaseDec,
D_ViewRuleKind_BaseBin,
D_ViewRuleKind_BaseOct,
D_ViewRuleKind_BaseHex,
D_ViewRuleKind_Only,
D_ViewRuleKind_Omit,
D_ViewRuleKind_NoAddr,
D_ViewRuleKind_Checkbox,
D_ViewRuleKind_ColorRGBA,
D_ViewRuleKind_Text,
D_ViewRuleKind_Disasm,
D_ViewRuleKind_Memory,
D_ViewRuleKind_Graph,
D_ViewRuleKind_Bitmap,
D_ViewRuleKind_Geo3D,
D_ViewRuleKind_COUNT,
} D_ViewRuleKind;
global B32 DEV_simulate_lag = 0;
global B32 DEV_draw_ui_text_pos = 0;
global B32 DEV_draw_ui_focus_debug = 0;
global B32 DEV_draw_ui_box_heatmap = 0;
global B32 DEV_eval_compiler_tooltips = 0;
global B32 DEV_eval_watch_key_tooltips = 0;
global B32 DEV_cmd_context_tooltips = 0;
global B32 DEV_scratch_mouse_draw = 0;
global B32 DEV_updating_indicator = 0;
struct {B32 *value_ptr; String8 name;} DEV_toggle_table[] =
{
{&DEV_simulate_lag, str8_lit_comp("simulate_lag")},
{&DEV_draw_ui_text_pos, str8_lit_comp("draw_ui_text_pos")},
{&DEV_draw_ui_focus_debug, str8_lit_comp("draw_ui_focus_debug")},
{&DEV_draw_ui_box_heatmap, str8_lit_comp("draw_ui_box_heatmap")},
{&DEV_eval_compiler_tooltips, str8_lit_comp("eval_compiler_tooltips")},
{&DEV_eval_watch_key_tooltips, str8_lit_comp("eval_watch_key_tooltips")},
{&DEV_cmd_context_tooltips, str8_lit_comp("cmd_context_tooltips")},
{&DEV_scratch_mouse_draw, str8_lit_comp("scratch_mouse_draw")},
{&DEV_updating_indicator, str8_lit_comp("updating_indicator")},
};
#endif // DBG_ENGINE_META_H
+1208 -291
View File
File diff suppressed because it is too large Load Diff
+229 -12
View File
@@ -1,8 +1,8 @@
// Copyright (c) 2024 Epic Games Tools // Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef DI_H #ifndef DBGI_H
#define DI_H #define DBGI_H
//////////////////////////////// ////////////////////////////////
//~ rjf: Cache Key Type //~ rjf: Cache Key Type
@@ -72,7 +72,7 @@ struct DI_EventList
}; };
//////////////////////////////// ////////////////////////////////
//~ rjf: Cache Types //~ rjf: Debug Info Cache Types
typedef struct DI_StringChunkNode DI_StringChunkNode; typedef struct DI_StringChunkNode DI_StringChunkNode;
struct DI_StringChunkNode struct DI_StringChunkNode
@@ -92,7 +92,6 @@ struct DI_Node
U64 ref_count; U64 ref_count;
U64 touch_count; U64 touch_count;
U64 is_working; U64 is_working;
U64 last_time_requested_us;
// rjf: key // rjf: key
DI_Key key; DI_Key key;
@@ -126,6 +125,91 @@ struct DI_Stripe
OS_Handle cv; OS_Handle cv;
}; };
////////////////////////////////
//~ rjf: Search Cache Types
typedef struct DI_SearchItem DI_SearchItem;
struct DI_SearchItem
{
U64 idx;
U64 dbgi_idx;
U64 missed_size;
FuzzyMatchRangeList match_ranges;
};
typedef struct DI_SearchItemChunk DI_SearchItemChunk;
struct DI_SearchItemChunk
{
DI_SearchItemChunk *next;
DI_SearchItem *v;
U64 count;
U64 cap;
};
typedef struct DI_SearchItemChunkList DI_SearchItemChunkList;
struct DI_SearchItemChunkList
{
DI_SearchItemChunk *first;
DI_SearchItemChunk *last;
U64 chunk_count;
U64 total_count;
};
typedef struct DI_SearchItemArray DI_SearchItemArray;
struct DI_SearchItemArray
{
DI_SearchItem *v;
U64 count;
};
typedef struct DI_SearchParams DI_SearchParams;
struct DI_SearchParams
{
RDI_SectionKind target;
DI_KeyArray dbgi_keys;
};
typedef struct DI_SearchBucket DI_SearchBucket;
struct DI_SearchBucket
{
Arena *arena;
String8 query;
U64 params_hash;
DI_SearchParams params;
};
typedef struct DI_SearchNode DI_SearchNode;
struct DI_SearchNode
{
DI_SearchNode *next;
DI_SearchNode *prev;
U128 key;
U64 scope_refcount;
U64 work_refcount;
U64 last_update_tick_idx;
U64 bucket_read_gen;
U64 bucket_write_gen;
U64 bucket_items_gen;
DI_SearchBucket buckets[6];
DI_SearchItemArray items;
};
typedef struct DI_SearchSlot DI_SearchSlot;
struct DI_SearchSlot
{
DI_SearchNode *first;
DI_SearchNode *last;
};
typedef struct DI_SearchStripe DI_SearchStripe;
struct DI_SearchStripe
{
Arena *arena;
DI_SearchNode *free_node;
OS_Handle rw_mutex;
OS_Handle cv;
};
//////////////////////////////// ////////////////////////////////
//~ rjf: Scoped Access Types //~ rjf: Scoped Access Types
@@ -134,6 +218,7 @@ struct DI_Touch
{ {
DI_Touch *next; DI_Touch *next;
DI_Node *node; DI_Node *node;
DI_SearchNode *search_node;
}; };
typedef struct DI_Scope DI_Scope; typedef struct DI_Scope DI_Scope;
@@ -152,6 +237,98 @@ struct DI_TCTX
DI_Touch *free_touch; DI_Touch *free_touch;
}; };
////////////////////////////////
//~ rjf: Search Thread State Types
typedef struct DI_SearchThread DI_SearchThread;
struct DI_SearchThread
{
OS_Handle thread;
OS_Handle ring_mutex;
OS_Handle ring_cv;
U64 ring_size;
U8 *ring_base;
U64 ring_write_pos;
U64 ring_read_pos;
};
////////////////////////////////
//~ rjf: Match Cache State Types
typedef struct DI_Match DI_Match;
struct DI_Match
{
DI_Match *next;
DI_Match *prev;
U64 dbgi_idx;
RDI_SectionKind section;
U32 idx;
};
typedef struct DI_MatchNameNode DI_MatchNameNode;
struct DI_MatchNameNode
{
// rjf: synchronously written by usage code
DI_MatchNameNode *next;
DI_MatchNameNode *prev;
DI_MatchNameNode *lru_next;
DI_MatchNameNode *lru_prev;
U64 alloc_gen;
U64 first_gen_touched;
U64 last_gen_touched;
U64 req_params_hash;
U64 req_count;
String8 name;
U64 hash;
// rjf: atomically written by match work
U64 cmp_count;
U64 cmp_params_hash;
RDI_SectionKind section_kind;
// DI_Match *first_match;
// DI_Match *last_match;
};
typedef struct DI_MatchNameSlot DI_MatchNameSlot;
struct DI_MatchNameSlot
{
DI_MatchNameNode *first;
DI_MatchNameNode *last;
};
typedef struct DI_MatchStore DI_MatchStore;
struct DI_MatchStore
{
Arena *arena;
U64 gen;
Arena *gen_arenas[2];
// rjf: parameters
Arena *params_arena;
OS_Handle params_rw_mutex;
U64 params_hash;
DI_KeyArray params_keys;
// rjf: match cache
U64 match_name_slots_count;
DI_MatchNameSlot *match_name_slots;
DI_MatchNameNode *first_free_match_name;
DI_Match *first_free_match;
DI_MatchNameNode *first_lru_match_name;
DI_MatchNameNode *last_lru_match_name;
U64 active_match_name_nodes_count;
OS_Handle match_rw_mutex;
OS_Handle match_cv;
// rjf: user -> match work ring buffer
OS_Handle u2m_ring_cv;
OS_Handle u2m_ring_mutex;
U64 u2m_ring_size;
U8 *u2m_ring_base;
U64 u2m_ring_write_pos;
U64 u2m_ring_read_pos;
};
//////////////////////////////// ////////////////////////////////
//~ rjf: Shared State Types //~ rjf: Shared State Types
@@ -160,12 +337,18 @@ struct DI_Shared
{ {
Arena *arena; Arena *arena;
// rjf: node cache // rjf: debug info cache
U64 slots_count; U64 slots_count;
DI_Slot *slots; DI_Slot *slots;
U64 stripes_count; U64 stripes_count;
DI_Stripe *stripes; DI_Stripe *stripes;
// rjf: search cache
U64 search_slots_count;
DI_SearchSlot *search_slots;
U64 search_stripes_count;
DI_SearchStripe *search_stripes;
// rjf: user -> parse ring // rjf: user -> parse ring
OS_Handle u2p_ring_mutex; OS_Handle u2p_ring_mutex;
OS_Handle u2p_ring_cv; OS_Handle u2p_ring_cv;
@@ -182,9 +365,10 @@ struct DI_Shared
U64 p2u_ring_write_pos; U64 p2u_ring_write_pos;
U64 p2u_ring_read_pos; U64 p2u_ring_read_pos;
// rjf: threads // rjf: search threads
U64 parse_thread_count; U64 search_threads_count;
OS_Handle *parse_threads; DI_SearchThread *search_threads;
OS_Handle search_evictor_thread;
}; };
//////////////////////////////// ////////////////////////////////
@@ -197,6 +381,7 @@ global RDI_Parsed di_rdi_parsed_nil = {0};
//////////////////////////////// ////////////////////////////////
//~ rjf: Basic Helpers //~ rjf: Basic Helpers
internal U64 di_hash_from_seed_string(U64 seed, String8 string, StringMatchFlags match_flags);
internal U64 di_hash_from_string(String8 string, StringMatchFlags match_flags); internal U64 di_hash_from_string(String8 string, StringMatchFlags match_flags);
internal U64 di_hash_from_key(DI_Key *k); internal U64 di_hash_from_key(DI_Key *k);
internal DI_Key di_key_zero(void); internal DI_Key di_key_zero(void);
@@ -205,6 +390,12 @@ internal DI_Key di_key_copy(Arena *arena, DI_Key *src);
internal DI_Key di_normalized_key_from_key(Arena *arena, DI_Key *src); internal DI_Key di_normalized_key_from_key(Arena *arena, DI_Key *src);
internal void di_key_list_push(Arena *arena, DI_KeyList *list, DI_Key *key); internal void di_key_list_push(Arena *arena, DI_KeyList *list, DI_Key *key);
internal DI_KeyArray di_key_array_from_list(Arena *arena, DI_KeyList *list); internal DI_KeyArray di_key_array_from_list(Arena *arena, DI_KeyList *list);
internal DI_KeyArray di_key_array_copy(Arena *arena, DI_KeyArray *src);
internal DI_SearchParams di_search_params_copy(Arena *arena, DI_SearchParams *src);
internal U64 di_hash_from_search_params(DI_SearchParams *params);
internal void di_search_item_chunk_list_concat_in_place(DI_SearchItemChunkList *dst, DI_SearchItemChunkList *to_push);
internal U64 di_search_item_num_from_array_element_idx__linear_search(DI_SearchItemArray *array, U64 element_idx);
internal String8 di_search_item_string_from_rdi_target_element_idx(RDI_Parsed *rdi, RDI_SectionKind target, U64 element_idx);
//////////////////////////////// ////////////////////////////////
//~ rjf: Main Layer Initialization //~ rjf: Main Layer Initialization
@@ -217,6 +408,7 @@ internal void di_init(void);
internal DI_Scope *di_scope_open(void); internal DI_Scope *di_scope_open(void);
internal void di_scope_close(DI_Scope *scope); internal void di_scope_close(DI_Scope *scope);
internal void di_scope_touch_node__stripe_mutex_r_guarded(DI_Scope *scope, DI_Node *node); internal void di_scope_touch_node__stripe_mutex_r_guarded(DI_Scope *scope, DI_Node *node);
internal void di_scope_touch_search_node__stripe_mutex_r_guarded(DI_Scope *scope, DI_SearchNode *node);
//////////////////////////////// ////////////////////////////////
//~ rjf: Per-Slot Functions //~ rjf: Per-Slot Functions
@@ -237,12 +429,17 @@ internal void di_open(DI_Key *key);
internal void di_close(DI_Key *key); internal void di_close(DI_Key *key);
//////////////////////////////// ////////////////////////////////
//~ rjf: Cache Lookups //~ rjf: Debug Info Cache Lookups
internal RDI_Parsed *di_rdi_from_key(DI_Scope *scope, DI_Key *key, U64 endt_us); internal RDI_Parsed *di_rdi_from_key(DI_Scope *scope, DI_Key *key, U64 endt_us);
//////////////////////////////// ////////////////////////////////
//~ rjf: Parse Threads //~ rjf: Search Cache Lookups
internal DI_SearchItemArray di_search_items_from_key_params_query(DI_Scope *scope, U128 key, DI_SearchParams *params, String8 query, U64 endt_us, B32 *stale_out);
////////////////////////////////
//~ rjf: Asynchronous Parse Work
internal B32 di_u2p_enqueue_key(DI_Key *key, U64 endt_us); internal B32 di_u2p_enqueue_key(DI_Key *key, U64 endt_us);
internal void di_u2p_dequeue_key(Arena *arena, DI_Key *out_key); internal void di_u2p_dequeue_key(Arena *arena, DI_Key *out_key);
@@ -250,6 +447,26 @@ internal void di_u2p_dequeue_key(Arena *arena, DI_Key *out_key);
internal void di_p2u_push_event(DI_Event *event); internal void di_p2u_push_event(DI_Event *event);
internal DI_EventList di_p2u_pop_events(Arena *arena, U64 endt_us); internal DI_EventList di_p2u_pop_events(Arena *arena, U64 endt_us);
internal void di_parse_thread__entry_point(void *p); ASYNC_WORK_DEF(di_parse_work);
#endif // DI_H ////////////////////////////////
//~ rjf: Search Threads
internal B32 di_u2s_enqueue_req(U128 key, U64 endt_us);
internal U128 di_u2s_dequeue_req(U64 thread_idx);
ASYNC_WORK_DEF(di_search_work);
internal int di_qsort_compare_search_items(DI_SearchItem *a, DI_SearchItem *b);
internal void di_search_thread__entry_point(void *p);
internal void di_search_evictor_thread__entry_point(void *p);
////////////////////////////////
//~ rjf: Match Store
internal DI_MatchStore *di_match_store_alloc(void);
internal void di_match_store_begin(DI_MatchStore *store, DI_KeyArray keys);
internal RDI_SectionKind di_match_store_section_kind_from_name(DI_MatchStore *store, String8 name, U64 endt_us);
ASYNC_WORK_DEF(di_match_work);
#endif // DBGI_H
+34 -4
View File
@@ -131,8 +131,8 @@ dmn_rip_from_thread(DMN_Handle thread)
U64 result = 0; U64 result = 0;
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
{ {
Architecture arch = dmn_arch_from_thread(thread); Arch arch = dmn_arch_from_thread(thread);
U64 reg_block_size = regs_block_size_from_architecture(arch); U64 reg_block_size = regs_block_size_from_arch(arch);
void *reg_block = push_array(scratch.arena, U8, reg_block_size); void *reg_block = push_array(scratch.arena, U8, reg_block_size);
dmn_thread_read_reg_block(thread, reg_block); dmn_thread_read_reg_block(thread, reg_block);
result = regs_rip_from_arch_block(arch, reg_block); result = regs_rip_from_arch_block(arch, reg_block);
@@ -147,8 +147,8 @@ dmn_rsp_from_thread(DMN_Handle thread)
U64 result = 0; U64 result = 0;
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
{ {
Architecture arch = dmn_arch_from_thread(thread); Arch arch = dmn_arch_from_thread(thread);
U64 reg_block_size = regs_block_size_from_architecture(arch); U64 reg_block_size = regs_block_size_from_arch(arch);
void *reg_block = push_array(scratch.arena, U8, reg_block_size); void *reg_block = push_array(scratch.arena, U8, reg_block_size);
dmn_thread_read_reg_block(thread, reg_block); dmn_thread_read_reg_block(thread, reg_block);
result = regs_rsp_from_arch_block(arch, reg_block); result = regs_rsp_from_arch_block(arch, reg_block);
@@ -156,3 +156,33 @@ dmn_rsp_from_thread(DMN_Handle thread)
scratch_end(scratch); scratch_end(scratch);
return result; return result;
} }
////////////////////////////////
//~ Memory Helpers
internal String8
dmn_process_read_cstring(Arena *arena, DMN_Handle process, U64 addr)
{
Temp scratch = scratch_begin(&arena, 1);
String8List block_list = {0};
for(U64 cursor = addr, stride = 256; ; cursor += stride)
{
U8 *raw_block = push_array_no_zero(scratch.arena, U8, stride);
U64 read_size = dmn_process_read(process, r1u64(cursor, cursor + stride), raw_block);
String8 block = str8_cstring_capped(raw_block, raw_block + read_size);
str8_list_push(scratch.arena, &block_list, block);
if(read_size != stride || (block.size+1 <= read_size && block.str[block.size] == 0))
{
break;
}
}
String8 result = str8_list_join(arena, &block_list, 0);
scratch_end(scratch);
return result;
}
+4 -3
View File
@@ -68,7 +68,7 @@ struct DMN_Event
DMN_Handle process; DMN_Handle process;
DMN_Handle thread; DMN_Handle thread;
DMN_Handle module; DMN_Handle module;
Architecture arch; Arch arch;
U64 address; U64 address;
U64 size; U64 size;
String8 string; String8 string;
@@ -192,7 +192,7 @@ internal DMN_CtrlCtx *dmn_ctrl_begin(void);
internal void dmn_ctrl_exclusive_access_begin(void); internal void dmn_ctrl_exclusive_access_begin(void);
internal void dmn_ctrl_exclusive_access_end(void); internal void dmn_ctrl_exclusive_access_end(void);
#define DMN_CtrlExclusiveAccessScope DeferLoop(dmn_ctrl_exclusive_access_begin(), dmn_ctrl_exclusive_access_end()) #define DMN_CtrlExclusiveAccessScope DeferLoop(dmn_ctrl_exclusive_access_begin(), dmn_ctrl_exclusive_access_end())
internal U32 dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_LaunchOptions *options); internal U32 dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_ProcessLaunchParams *params);
internal B32 dmn_ctrl_attach(DMN_CtrlCtx *ctx, U32 pid); internal B32 dmn_ctrl_attach(DMN_CtrlCtx *ctx, U32 pid);
internal B32 dmn_ctrl_kill(DMN_CtrlCtx *ctx, DMN_Handle process, U32 exit_code); internal B32 dmn_ctrl_kill(DMN_CtrlCtx *ctx, DMN_Handle process, U32 exit_code);
internal B32 dmn_ctrl_detach(DMN_CtrlCtx *ctx, DMN_Handle process); internal B32 dmn_ctrl_detach(DMN_CtrlCtx *ctx, DMN_Handle process);
@@ -226,9 +226,10 @@ internal U64 dmn_process_read(DMN_Handle process, Rng1U64 range, void *dst);
internal B32 dmn_process_write(DMN_Handle process, Rng1U64 range, void *src); internal B32 dmn_process_write(DMN_Handle process, Rng1U64 range, void *src);
#define dmn_process_read_struct(process, vaddr, ptr) dmn_process_read((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr) #define dmn_process_read_struct(process, vaddr, ptr) dmn_process_read((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr)
#define dmn_process_write_struct(process, vaddr, ptr) dmn_process_write((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr) #define dmn_process_write_struct(process, vaddr, ptr) dmn_process_write((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr)
internal String8 dmn_process_read_cstring(Arena *arena, DMN_Handle process, U64 addr);
//- rjf: threads //- rjf: threads
internal Architecture dmn_arch_from_thread(DMN_Handle handle); internal Arch dmn_arch_from_thread(DMN_Handle handle);
internal U64 dmn_stack_base_vaddr_from_thread(DMN_Handle handle); internal U64 dmn_stack_base_vaddr_from_thread(DMN_Handle handle);
internal U64 dmn_tls_root_vaddr_from_thread(DMN_Handle handle); internal U64 dmn_tls_root_vaddr_from_thread(DMN_Handle handle);
internal B32 dmn_thread_read_reg_block(DMN_Handle handle, void *reg_block); internal B32 dmn_thread_read_reg_block(DMN_Handle handle, void *reg_block);
+4 -2
View File
@@ -1,10 +1,12 @@
// Copyright (c) 2024 Epic Games Tools // Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
#include "demon_core.c" #include "demon/demon_core.c"
#if OS_WINDOWS #if OS_WINDOWS
# include "win32/demon_core_win32.c" # include "demon/win32/demon_core_win32.c"
#elif OS_LINUX
# include "demon/linux/demon_core_linux.c"
#else #else
# error Demon layer backend not defined for this operating system. # error Demon layer backend not defined for this operating system.
#endif #endif
+4 -2
View File
@@ -4,10 +4,12 @@
#ifndef DEMON_INC_H #ifndef DEMON_INC_H
#define DEMON_INC_H #define DEMON_INC_H
#include "demon_core.h" #include "demon/demon_core.h"
#if OS_WINDOWS #if OS_WINDOWS
# include "win32/demon_core_win32.h" # include "demon/win32/demon_core_win32.h"
#elif OS_LINUX
# include "demon/linux/demon_core_linux.h"
#else #else
# error Demon layer backend not defined for this operating system. # error Demon layer backend not defined for this operating system.
#endif #endif
+174
View File
@@ -0,0 +1,174 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: @dmn_os_hooks Main Layer Initialization (Implemented Per-OS)
internal void
dmn_init(void)
{
}
////////////////////////////////
//~ rjf: @dmn_os_hooks Blocking Control Thread Operations (Implemented Per-OS)
internal DMN_CtrlCtx *
dmn_ctrl_begin(void)
{
}
internal void
dmn_ctrl_exclusive_access_begin(void)
{
}
internal void
dmn_ctrl_exclusive_access_end(void)
{
}
internal U32
dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_ProcessLaunchParams *params)
{
}
internal B32
dmn_ctrl_attach(DMN_CtrlCtx *ctx, U32 pid)
{
}
internal B32
dmn_ctrl_kill(DMN_CtrlCtx *ctx, DMN_Handle process, U32 exit_code)
{
}
internal B32
dmn_ctrl_detach(DMN_CtrlCtx *ctx, DMN_Handle process)
{
}
internal DMN_EventList
dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
{
}
////////////////////////////////
//~ rjf: @dmn_os_hooks Halting (Implemented Per-OS)
internal void
dmn_halt(U64 code, U64 user_data)
{
}
////////////////////////////////
//~ rjf: @dmn_os_hooks Introspection Functions (Implemented Per-OS)
//- rjf: run/memory/register counters
internal U64
dmn_run_gen(void)
{
}
internal U64
dmn_mem_gen(void)
{
}
internal U64
dmn_reg_gen(void)
{
}
//- rjf: non-blocking-control-thread access barriers
internal B32
dmn_access_open(void)
{
}
internal void
dmn_access_close(void)
{
}
//- rjf: processes
internal U64
dmn_process_memory_reserve(DMN_Handle process, U64 vaddr, U64 size)
{
}
internal void
dmn_process_memory_commit(DMN_Handle process, U64 vaddr, U64 size)
{
}
internal void
dmn_process_memory_decommit(DMN_Handle process, U64 vaddr, U64 size)
{
}
internal void
dmn_process_memory_release(DMN_Handle process, U64 vaddr, U64 size)
{
}
internal void
dmn_process_memory_protect(DMN_Handle process, U64 vaddr, U64 size, OS_AccessFlags flags)
{
}
internal U64
dmn_process_read(DMN_Handle process, Rng1U64 range, void *dst)
{
}
internal B32
dmn_process_write(DMN_Handle process, Rng1U64 range, void *src)
{
}
//- rjf: threads
internal Arch
dmn_arch_from_thread(DMN_Handle handle)
{
}
internal U64
dmn_stack_base_vaddr_from_thread(DMN_Handle handle)
{
}
internal U64
dmn_tls_root_vaddr_from_thread(DMN_Handle handle)
{
}
internal B32
dmn_thread_read_reg_block(DMN_Handle handle, void *reg_block)
{
}
internal B32
dmn_thread_write_reg_block(DMN_Handle handle, void *reg_block)
{
}
//- rjf: system process listing
internal void
dmn_process_iter_begin(DMN_ProcessIter *iter)
{
}
internal B32
dmn_process_iter_next(Arena *arena, DMN_ProcessIter *iter, DMN_ProcessInfo *info_out)
{
}
internal void
dmn_process_iter_end(DMN_ProcessIter *iter)
{
}
+7
View File
@@ -0,0 +1,7 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef DEMON_CORE_LINUX_H
#define DEMON_CORE_LINUX_H
#endif // DEMON_CORE_LINUX_H
+29 -29
View File
@@ -98,7 +98,7 @@ demon_lnx_executable_path_from_pid(Arena *arena, pid_t pid){
temp_end(restore_point); temp_end(restore_point);
} }
else{ else{
arena_put_back(arena, (cap - size - 1)); arena_pop(arena, (cap - size - 1));
result = str8(buffer, size + 1); result = str8(buffer, size + 1);
} }
@@ -115,10 +115,10 @@ demon_lnx_open_memory_fd_for_pid(pid_t pid){
return(result); return(result);
} }
internal Architecture internal Arch
demon_lnx_arch_from_pid(pid_t pid){ demon_lnx_arch_from_pid(pid_t pid){
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
Architecture result = Architecture_Null; Arch result = Arch_Null;
// exe path // exe path
String8 exe_path = demon_lnx_executable_path_from_pid(scratch.arena, pid); String8 exe_path = demon_lnx_executable_path_from_pid(scratch.arena, pid);
@@ -168,22 +168,22 @@ demon_lnx_arch_from_pid(pid_t pid){
switch (ehdr.e_machine){ switch (ehdr.e_machine){
case SYMS_ElfMachineKind_386: case SYMS_ElfMachineKind_386:
{ {
result = Architecture_x86; result = Arch_x86;
}break; }break;
case SYMS_ElfMachineKind_ARM: case SYMS_ElfMachineKind_ARM:
{ {
result = Architecture_arm32; result = Arch_arm32;
}break; }break;
case SYMS_ElfMachineKind_X86_64: case SYMS_ElfMachineKind_X86_64:
{ {
result = Architecture_x64; result = Arch_x64;
}break; }break;
case SYMS_ElfMachineKind_AARCH64: case SYMS_ElfMachineKind_AARCH64:
{ {
result = Architecture_arm64; result = Arch_arm64;
}break; }break;
} }
@@ -192,9 +192,9 @@ demon_lnx_arch_from_pid(pid_t pid){
} }
internal DEMON_LNX_ProcessAux internal DEMON_LNX_ProcessAux
demon_lnx_aux_from_pid(pid_t pid, Architecture arch){ demon_lnx_aux_from_pid(pid_t pid, Arch arch){
DEMON_LNX_ProcessAux result = {0}; DEMON_LNX_ProcessAux result = {0};
B32 addr_32bit = (arch == Architecture_x86 || arch == Architecture_arm32); B32 addr_32bit = (arch == Arch_x86 || arch == Arch_arm32);
// open aux data // open aux data
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
@@ -300,8 +300,8 @@ demon_lnx_phdr_info_from_memory(int memory_fd, B32 is_32bit, U64 phvaddr, U64 ph
internal DEMON_LNX_ModuleNode* internal DEMON_LNX_ModuleNode*
demon_lnx_module_list_from_process(Arena *arena, DEMON_Entity *process){ demon_lnx_module_list_from_process(Arena *arena, DEMON_Entity *process){
Architecture arch = (Architecture)process->arch; Arch arch = (Arch)process->arch;
B32 is_32bit = (arch == Architecture_x86 || arch == Architecture_arm32); B32 is_32bit = (arch == Arch_x86 || arch == Arch_arm32);
int memory_fd = (int)process->ext_u64; int memory_fd = (int)process->ext_u64;
// aux from pid // aux from pid
@@ -839,11 +839,11 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *controls){
U8 *trap_swap_bytes = 0; U8 *trap_swap_bytes = 0;
if (result.first == 0){ if (result.first == 0){
// TODO(allen): per-Architecture implementation of single steps // TODO(allen): per-Arch implementation of single steps
// set single step bit // set single step bit
if (single_step_thread != 0){ if (single_step_thread != 0){
switch (single_step_thread->arch){ switch (single_step_thread->arch){
case Architecture_x86: case Arch_x86:
{ {
// TODO(allen): possibly buggy // TODO(allen): possibly buggy
SYMS_RegX86 regs = {0}; SYMS_RegX86 regs = {0};
@@ -852,7 +852,7 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *controls){
demon_os_write_regs_x86(single_step_thread, &regs); demon_os_write_regs_x86(single_step_thread, &regs);
}break; }break;
case Architecture_x64: case Arch_x64:
{ {
// TODO(allen): possibly buggy // TODO(allen): possibly buggy
SYMS_RegX64 regs = {0}; SYMS_RegX64 regs = {0};
@@ -863,7 +863,7 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *controls){
} }
} }
// TODO(allen): per-Architecture implementation of traps // TODO(allen): per-Arch implementation of traps
trap_swap_bytes = push_array_no_zero(scratch.arena, U8, controls->trap_count); trap_swap_bytes = push_array_no_zero(scratch.arena, U8, controls->trap_count);
{ {
@@ -980,13 +980,13 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *controls){
union{ SYMS_RegX86 x86; SYMS_RegX64 x64; } regs = {0}; union{ SYMS_RegX86 x86; SYMS_RegX64 x64; } regs = {0};
switch (thread->arch){ switch (thread->arch){
case Architecture_x86: case Arch_x86:
{ {
demon_os_read_regs_x86(thread, &regs.x86); demon_os_read_regs_x86(thread, &regs.x86);
instruction_pointer = regs.x86.eip.u32; instruction_pointer = regs.x86.eip.u32;
}break; }break;
case Architecture_x64: case Arch_x64:
{ {
demon_os_read_regs_x64(thread, &regs.x64); demon_os_read_regs_x64(thread, &regs.x64);
instruction_pointer = regs.x64.rip.u64; instruction_pointer = regs.x64.rip.u64;
@@ -1052,7 +1052,7 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *controls){
// this stuff in the log to make sense of it still. // this stuff in the log to make sense of it still.
} }
else{ else{
Architecture arch = demon_lnx_arch_from_pid(new_pid); Arch arch = demon_lnx_arch_from_pid(new_pid);
// process entity // process entity
DEMON_Entity *new_process = demon_ent_new(demon_ent_root, DEMON_EntityKind_Process, new_pid); DEMON_Entity *new_process = demon_ent_new(demon_ent_root, DEMON_EntityKind_Process, new_pid);
@@ -1105,14 +1105,14 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *controls){
if (e_kind == DEMON_EventKind_Breakpoint){ if (e_kind == DEMON_EventKind_Breakpoint){
// TODO(allen): possibly buggy // TODO(allen): possibly buggy
switch (thread->arch){ switch (thread->arch){
case Architecture_x86: case Arch_x86:
{ {
instruction_pointer -= 1; instruction_pointer -= 1;
regs.x86.eip.u32 = instruction_pointer; regs.x86.eip.u32 = instruction_pointer;
demon_os_write_regs_x86(thread, &regs.x86); demon_os_write_regs_x86(thread, &regs.x86);
}break; }break;
case Architecture_x64: case Arch_x64:
{ {
instruction_pointer -= 1; instruction_pointer -= 1;
regs.x64.rip.u64 = instruction_pointer; regs.x64.rip.u64 = instruction_pointer;
@@ -1336,7 +1336,7 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *controls){
// cleanup // cleanup
if (did_run){ if (did_run){
// TODO(allen): per-Architecture // TODO(allen): per-Arch
// unset traps // unset traps
{ {
DEMON_OS_Trap *trap = controls->traps; DEMON_OS_Trap *trap = controls->traps;
@@ -1348,7 +1348,7 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *controls){
} }
} }
// TODO(allen): per-Architecture // TODO(allen): per-Arch
// unset single step bit // unset single step bit
// the single step bit is automatically unset whenever we single step // the single step bit is automatically unset whenever we single step
// but if *something else* happened, it will still be there ready to // but if *something else* happened, it will still be there ready to
@@ -1356,7 +1356,7 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *controls){
if (single_step_thread != 0){ if (single_step_thread != 0){
// TODO(allen): possibly buggy // TODO(allen): possibly buggy
switch (single_step_thread->arch){ switch (single_step_thread->arch){
case Architecture_x86: case Arch_x86:
{ {
SYMS_RegX86 regs = {0}; SYMS_RegX86 regs = {0};
demon_os_read_regs_x86(single_step_thread, &regs); demon_os_read_regs_x86(single_step_thread, &regs);
@@ -1364,7 +1364,7 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *controls){
demon_os_write_regs_x86(single_step_thread, &regs); demon_os_write_regs_x86(single_step_thread, &regs);
}break; }break;
case Architecture_x64: case Arch_x64:
{ {
SYMS_RegX64 regs = {0}; SYMS_RegX64 regs = {0};
demon_os_read_regs_x64(single_step_thread, &regs); demon_os_read_regs_x64(single_step_thread, &regs);
@@ -1555,7 +1555,7 @@ demon_os_launch_process(OS_LaunchOptions *options){
else{ else{
result = pid; result = pid;
Architecture arch = demon_lnx_arch_from_pid(pid); Arch arch = demon_lnx_arch_from_pid(pid);
// process entity // process entity
DEMON_Entity *process = demon_ent_new(demon_ent_root, DEMON_EntityKind_Process, pid); DEMON_Entity *process = demon_ent_new(demon_ent_root, DEMON_EntityKind_Process, pid);
@@ -1688,7 +1688,7 @@ demon_os_attach_process(U32 pid){
// initialize new entities on success // initialize new entities on success
if (result){ if (result){
Architecture arch = demon_lnx_arch_from_pid(the_process->pid); Arch arch = demon_lnx_arch_from_pid(the_process->pid);
// process entity // process entity
DEMON_Entity *process = demon_ent_new(demon_ent_root, DEMON_EntityKind_Process, the_process->pid); DEMON_Entity *process = demon_ent_new(demon_ent_root, DEMON_EntityKind_Process, the_process->pid);
@@ -1816,15 +1816,15 @@ internal U64
demon_os_tls_root_vaddr_from_thread(DEMON_Entity *thread){ demon_os_tls_root_vaddr_from_thread(DEMON_Entity *thread){
U64 result = 0; U64 result = 0;
switch (thread->arch){ switch (thread->arch){
case Architecture_x64: case Arch_x64:
case Architecture_x86: case Arch_x86:
{ {
U32 fsbase = 0; U32 fsbase = 0;
pid_t tid = (pid_t)thread->id; pid_t tid = (pid_t)thread->id;
if (ptrace(PT_GETFSBASE, tid, (void*)&fsbase, 0) != -1){ if (ptrace(PT_GETFSBASE, tid, (void*)&fsbase, 0) != -1){
result = (U64)fsbase; result = (U64)fsbase;
} }
if (thread->arch == Architecture_x64){ if (thread->arch == Arch_x64){
result += 8; result += 8;
} }
else{ else{
+2 -2
View File
@@ -198,8 +198,8 @@ internal B32 demon_lnx_attach_pid(Arena *arena, pid_t pid, DEM
internal String8 demon_lnx_executable_path_from_pid(Arena *arena, pid_t pid); internal String8 demon_lnx_executable_path_from_pid(Arena *arena, pid_t pid);
internal int demon_lnx_open_memory_fd_for_pid(pid_t pid); internal int demon_lnx_open_memory_fd_for_pid(pid_t pid);
internal Architecture demon_lnx_arch_from_pid(pid_t pid); internal Arch demon_lnx_arch_from_pid(pid_t pid);
internal DEMON_LNX_ProcessAux demon_lnx_aux_from_pid(pid_t pid, Architecture arch); internal DEMON_LNX_ProcessAux demon_lnx_aux_from_pid(pid_t pid, Arch arch);
internal DEMON_LNX_PhdrInfo demon_lnx_phdr_info_from_memory(int memory_fd, B32 is_32bit, internal DEMON_LNX_PhdrInfo demon_lnx_phdr_info_from_memory(int memory_fd, B32 is_32bit,
U64 phvaddr, U64 phstride, U64 phcount); U64 phvaddr, U64 phstride, U64 phcount);
internal DEMON_LNX_ModuleNode* demon_lnx_module_list_from_process(Arena *arena, DEMON_Entity *process); internal DEMON_LNX_ModuleNode* demon_lnx_module_list_from_process(Arena *arena, DEMON_Entity *process);
+230 -140
View File
@@ -492,23 +492,23 @@ dmn_w32_image_info_from_process_base_vaddr(HANDLE process, U64 base_vaddr)
if(got_coff_header) if(got_coff_header)
{ {
U64 optional_size_off = 0; U64 optional_size_off = 0;
Architecture arch = Architecture_Null; Arch arch = Arch_Null;
switch(coff_header.machine) switch(coff_header.machine)
{ {
case COFF_MachineType_X86: case COFF_MachineType_X86:
{ {
arch = Architecture_x86; arch = Arch_x86;
optional_size_off = OffsetOf(PE_OptionalHeader32, sizeof_image); optional_size_off = OffsetOf(PE_OptionalHeader32, sizeof_image);
}break; }break;
case COFF_MachineType_X64: case COFF_MachineType_X64:
{ {
arch = Architecture_x64; arch = Arch_x64;
optional_size_off = OffsetOf(PE_OptionalHeader32Plus, sizeof_image); optional_size_off = OffsetOf(PE_OptionalHeader32Plus, sizeof_image);
}break; }break;
default: default:
{}break; {}break;
} }
if(arch != Architecture_Null) if(arch != Arch_Null)
{ {
U64 optional_off = coff_header_off + sizeof(coff_header); U64 optional_off = coff_header_off + sizeof(coff_header);
U32 size = 0; U32 size = 0;
@@ -577,7 +577,7 @@ dmn_w32_xsave_tag_word_from_real_tag_word(U16 ftw)
} }
internal B32 internal B32
dmn_w32_thread_read_reg_block(Architecture arch, HANDLE thread, void *reg_block) dmn_w32_thread_read_reg_block(Arch arch, HANDLE thread, void *reg_block)
{ {
B32 result = 0; B32 result = 0;
ProfBeginFunction(); ProfBeginFunction();
@@ -586,17 +586,17 @@ dmn_w32_thread_read_reg_block(Architecture arch, HANDLE thread, void *reg_block)
//////////////////////////// ////////////////////////////
//- rjf: unimplemented win32/arch combos //- rjf: unimplemented win32/arch combos
// //
case Architecture_Null: case Arch_Null:
case Architecture_COUNT: case Arch_COUNT:
{}break; {}break;
case Architecture_arm64: case Arch_arm64:
case Architecture_arm32: case Arch_arm32:
{NotImplemented;}break; {NotImplemented;}break;
//////////////////////////// ////////////////////////////
//- rjf: x86 //- rjf: x86
// //
case Architecture_x86: case Arch_x86:
{ {
REGS_RegBlockX86 *dst = (REGS_RegBlockX86 *)reg_block; REGS_RegBlockX86 *dst = (REGS_RegBlockX86 *)reg_block;
@@ -679,22 +679,18 @@ dmn_w32_thread_read_reg_block(Architecture arch, HANDLE thread, void *reg_block)
//////////////////////////// ////////////////////////////
//- rjf: x64 //- rjf: x64
// //
case Architecture_x64: case Arch_x64:
{ {
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
REGS_RegBlockX64 *dst = (REGS_RegBlockX64 *)reg_block; REGS_RegBlockX64 *dst = (REGS_RegBlockX64 *)reg_block;
//- rjf: unpack info about available features //- rjf: unpack info about available features
U32 feature_mask = GetEnabledXStateFeatures(); U32 feature_mask = GetEnabledXStateFeatures();
B32 avx_enabled = !!(feature_mask & XSTATE_MASK_AVX); B32 xstate_enabled = (feature_mask & (XSTATE_MASK_AVX | XSTATE_MASK_AVX512)) != 0;
//- rjf: set up context //- rjf: set up context
CONTEXT *ctx = 0; CONTEXT *ctx = 0;
U32 ctx_flags = DMN_W32_CTX_X64_ALL; U32 ctx_flags = DMN_W32_CTX_X64_ALL | (xstate_enabled ? DMN_W32_CTX_INTEL_XSTATE : 0);
if(avx_enabled)
{
ctx_flags |= DMN_W32_CTX_INTEL_XSTATE;
}
DWORD size = 0; DWORD size = 0;
InitializeContext(0, ctx_flags, 0, &size); InitializeContext(0, ctx_flags, 0, &size);
if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
@@ -707,18 +703,9 @@ dmn_w32_thread_read_reg_block(Architecture arch, HANDLE thread, void *reg_block)
} }
//- rjf: unpack features available on this context //- rjf: unpack features available on this context
B32 avx_available = 0; if (xstate_enabled)
if(ctx != 0)
{ {
if(avx_enabled) SetXStateFeaturesMask(ctx, XSTATE_MASK_AVX | XSTATE_MASK_AVX512);
{
SetXStateFeaturesMask(ctx, XSTATE_MASK_AVX);
}
DWORD64 xstate_flags = 0;
if(GetXStateFeaturesMask(ctx, &xstate_flags))
{
avx_available = !!(xstate_flags & XSTATE_MASK_AVX);
}
} }
//- rjf: get thread context //- rjf: get thread context
@@ -734,6 +721,9 @@ dmn_w32_thread_read_reg_block(Architecture arch, HANDLE thread, void *reg_block)
} }
result = 1; result = 1;
DWORD64 xstate_mask = 0;
GetXStateFeaturesMask(ctx, &xstate_mask);
//- rjf: convert context -> REGS_RegBlockX64 //- rjf: convert context -> REGS_RegBlockX64
XSAVE_FORMAT *xsave = &ctx->FltSave; XSAVE_FORMAT *xsave = &ctx->FltSave;
dst->rax.u64 = ctx->Rax; dst->rax.u64 = ctx->Rax;
@@ -786,32 +776,90 @@ dmn_w32_thread_read_reg_block(Architecture arch, HANDLE thread, void *reg_block)
MemoryCopy(float_d, float_s, sizeof(*float_d)); MemoryCopy(float_d, float_s, sizeof(*float_d));
} }
} }
if(!avx_available)
// SSE registers are always available in x64
{ {
M128A *xmm_s = xsave->XmmRegisters; M128A *xmm_s = xsave->XmmRegisters;
REGS_Reg256 *xmm_d = &dst->ymm0; REGS_Reg512 *zmm_d = &dst->zmm0;
for(U32 n = 0; n < 16; n += 1, xmm_s += 1, xmm_d += 1) for(U32 n = 0; n < 16; n += 1, xmm_s += 1, zmm_d += 1)
{ {
MemoryCopy(xmm_d, xmm_s, sizeof(*xmm_s)); MemoryCopy(zmm_d, xmm_s, sizeof(*xmm_s));
} }
} }
if(avx_available)
// AVX
if(xstate_mask & XSTATE_MASK_AVX)
{ {
DWORD part0_length = 0; DWORD avx_length = 0;
M128A *part0 = (M128A*)LocateXStateFeature(ctx, XSTATE_LEGACY_SSE, &part0_length); U8* avx_s = (U8*)LocateXStateFeature(ctx, XSTATE_AVX, &avx_length);
DWORD part1_length = 0; Assert(avx_length == 16 * sizeof(REGS_Reg128));
M128A *part1 = (M128A*)LocateXStateFeature(ctx, XSTATE_AVX, &part1_length);
Assert(part0_length == part1_length); REGS_Reg512 *zmm_d = &dst->zmm0;
DWORD count = part0_length/sizeof(part0[0]); for(U32 n = 0; n < 16; n += 1, avx_s += sizeof(REGS_Reg128), zmm_d += 1)
count = ClampTop(count, 16);
REGS_Reg256 *ymm_d = &dst->ymm0;
for (DWORD i = 0; i < count; i += 1, part0 += 1, part1 += 1, ymm_d += 1)
{ {
// TODO(rjf): confirm ordering of writes MemoryCopy(&zmm_d->v[16], avx_s, sizeof(REGS_Reg128));
ymm_d->u64[3] = part0->Low; }
ymm_d->u64[2] = part0->High; }
ymm_d->u64[1] = part1->Low; else
ymm_d->u64[0] = part1->High; {
REGS_Reg512 *zmm_d = &dst->zmm0;
for(U32 n = 0; n < 16; n += 1, zmm_d += 1)
{
MemoryZero(&zmm_d->v[16], sizeof(REGS_Reg128));
}
}
// AVX-512
if(xstate_mask & XSTATE_MASK_AVX512)
{
DWORD kmask_length = 0;
U64* kmask_s = (U64*)LocateXStateFeature(ctx, XSTATE_AVX512_KMASK, &kmask_length);
Assert(kmask_length == 8 * sizeof(U64));
REGS_Reg64 *kmask_d = &dst->k0;
for(U32 n = 0; n < 8; n += 1, kmask_s += 1, kmask_d += 1)
{
MemoryCopy(kmask_d, kmask_s, sizeof(*kmask_s));
}
DWORD avx512h_length = 0;
U8* avx512h_s = (U8*)LocateXStateFeature(ctx, XSTATE_AVX512_ZMM_H, &avx512h_length);
Assert(avx512h_length == 16 * sizeof(REGS_Reg256));
REGS_Reg512 *zmmh_d = &dst->zmm0;
for(U32 n = 0; n < 16; n += 1, avx512h_s += sizeof(REGS_Reg256), zmmh_d += 1)
{
MemoryCopy(&zmmh_d->v[32], avx512h_s, sizeof(REGS_Reg256));
}
DWORD avx512_length = 0;
U8* avx512_s = (U8*)LocateXStateFeature(ctx, XSTATE_AVX512_ZMM, &avx512_length);
Assert(avx512_length == 16 * sizeof(REGS_Reg512));
REGS_Reg512 *zmm_d = &dst->zmm16;
for(U32 n = 0; n < 16; n += 1, avx512_s += sizeof(REGS_Reg512), zmm_d += 1)
{
MemoryCopy(zmm_d, avx512_s, sizeof(REGS_Reg512));
}
}
else
{
REGS_Reg64 *kmask_d = &dst->k0;
for(U32 n = 0; n < 8; n += 1, kmask_d += 1)
{
MemoryZero(kmask_d, sizeof(*kmask_d));
}
REGS_Reg512 *zmmh_d = &dst->zmm0;
for(U32 n = 0; n < 16; n += 1, zmmh_d += 1)
{
MemoryZero(&zmmh_d->v[32], sizeof(REGS_Reg256));
}
REGS_Reg512 *zmm_d = &dst->zmm16;
for(U32 n = 0; n < 16; n += 1, zmm_d += 1)
{
MemoryZero(zmm_d, sizeof(*zmm_d));
} }
} }
@@ -823,7 +871,7 @@ dmn_w32_thread_read_reg_block(Architecture arch, HANDLE thread, void *reg_block)
} }
internal B32 internal B32
dmn_w32_thread_write_reg_block(Architecture arch, HANDLE thread, void *reg_block) dmn_w32_thread_write_reg_block(Arch arch, HANDLE thread, void *reg_block)
{ {
B32 result = 0; B32 result = 0;
ProfBeginFunction(); ProfBeginFunction();
@@ -832,17 +880,17 @@ dmn_w32_thread_write_reg_block(Architecture arch, HANDLE thread, void *reg_block
//////////////////////////// ////////////////////////////
//- rjf: unimplemented win32/arch combos //- rjf: unimplemented win32/arch combos
// //
case Architecture_Null: case Arch_Null:
case Architecture_COUNT: case Arch_COUNT:
{}break; {}break;
case Architecture_arm64: case Arch_arm64:
case Architecture_arm32: case Arch_arm32:
{NotImplemented;}break; {NotImplemented;}break;
//////////////////////////// ////////////////////////////
//- rjf: x86 //- rjf: x86
// //
case Architecture_x86: case Arch_x86:
{ {
REGS_RegBlockX86 *src = (REGS_RegBlockX86 *)reg_block; REGS_RegBlockX86 *src = (REGS_RegBlockX86 *)reg_block;
@@ -910,22 +958,18 @@ dmn_w32_thread_write_reg_block(Architecture arch, HANDLE thread, void *reg_block
//////////////////////////// ////////////////////////////
//- rjf: x64 //- rjf: x64
// //
case Architecture_x64: case Arch_x64:
{ {
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
REGS_RegBlockX64 *src = (REGS_RegBlockX64 *)reg_block; REGS_RegBlockX64 *src = (REGS_RegBlockX64 *)reg_block;
//- rjf: unpack info about available features //- rjf: unpack info about available features
U32 feature_mask = GetEnabledXStateFeatures(); U32 feature_mask = GetEnabledXStateFeatures();
B32 avx_enabled = !!(feature_mask & XSTATE_MASK_AVX); B32 xstate_enabled = (feature_mask & (XSTATE_MASK_AVX | XSTATE_MASK_AVX512)) != 0;
//- rjf: set up context //- rjf: set up context
CONTEXT *ctx = 0; CONTEXT *ctx = 0;
U32 ctx_flags = DMN_W32_CTX_X64_ALL; U32 ctx_flags = DMN_W32_CTX_X64_ALL | (xstate_enabled ? DMN_W32_CTX_INTEL_XSTATE : 0);
if(avx_enabled)
{
ctx_flags |= DMN_W32_CTX_INTEL_XSTATE;
}
DWORD size = 0; DWORD size = 0;
InitializeContext(0, ctx_flags, 0, &size); InitializeContext(0, ctx_flags, 0, &size);
if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
@@ -938,30 +982,14 @@ dmn_w32_thread_write_reg_block(Architecture arch, HANDLE thread, void *reg_block
} }
//- rjf: unpack features available on this context //- rjf: unpack features available on this context
B32 avx_available = 0; if (xstate_enabled)
if(ctx != 0)
{ {
if(avx_enabled) SetXStateFeaturesMask(ctx, XSTATE_MASK_AVX | XSTATE_MASK_AVX512);
{
SetXStateFeaturesMask(ctx, XSTATE_MASK_AVX);
}
DWORD64 xstate_flags = 0;
if(GetXStateFeaturesMask(ctx, &xstate_flags))
{
avx_available = !!(xstate_flags & XSTATE_MASK_AVX);
}
}
//- rjf: get thread context
if(!GetThreadContext(thread, ctx))
{
ctx = 0;
} }
//- rjf: bad context -> abort //- rjf: bad context -> abort
if(ctx == 0) if(ctx == 0)
{ {
DWORD error = GetLastError();
break; break;
} }
@@ -1015,32 +1043,62 @@ dmn_w32_thread_write_reg_block(Architecture arch, HANDLE thread, void *reg_block
MemoryCopy(float_d, float_s, 10); MemoryCopy(float_d, float_s, 10);
} }
} }
if(!avx_available)
// SSE registers are always available in x64
{ {
M128A *xmm_d = fxsave->XmmRegisters; M128A *xmm_d = fxsave->XmmRegisters;
REGS_Reg256 *xmm_s = &src->ymm0; REGS_Reg512 *zmm_s = &src->zmm0;
for(U32 n = 0; n < 8; n += 1, xmm_d += 1, xmm_s += 1) for(U32 n = 0; n < 16; n += 1, xmm_d += 1, zmm_s += 1)
{ {
MemoryCopy(xmm_d, xmm_s, sizeof(*xmm_d)); MemoryCopy(xmm_d, zmm_s, sizeof(*xmm_d));
} }
} }
if(avx_available)
// AVX
if(feature_mask & XSTATE_MASK_AVX)
{ {
DWORD part0_length = 0; DWORD avx_length = 0;
M128A *part0 = (M128A*)LocateXStateFeature(ctx, XSTATE_LEGACY_SSE, &part0_length); U8* avx_d = (U8*)LocateXStateFeature(ctx, XSTATE_AVX, &avx_length);
DWORD part1_length = 0; Assert(avx_length == 16 * sizeof(REGS_Reg128));
M128A *part1 = (M128A*)LocateXStateFeature(ctx, XSTATE_AVX, &part1_length);
Assert(part0_length == part1_length); REGS_Reg512 *zmm_s = &src->zmm0;
DWORD count = part0_length/sizeof(part0[0]); for(U32 n = 0; n < 16; n += 1, avx_d += sizeof(REGS_Reg128), zmm_s += 1)
count = ClampTop(count, 16);
REGS_Reg256 *ymm_d = &src->ymm0;
for(DWORD i = 0; i < count; i += 1, part0 += 1, part1 += 1, ymm_d += 1)
{ {
// TODO(allen): Are we writing these out in the right order? Seems weird right? MemoryCopy(avx_d, &zmm_s->v[16], sizeof(REGS_Reg128));
part0->Low = ymm_d->u64[3]; }
part0->High = ymm_d->u64[2]; }
part1->Low = ymm_d->u64[1];
part1->High = ymm_d->u64[0]; // AVX-512
if(feature_mask & XSTATE_MASK_AVX512)
{
DWORD kmask_length = 0;
U64* kmask_d = (U64*)LocateXStateFeature(ctx, XSTATE_AVX512_KMASK, &kmask_length);
Assert(kmask_length == 8 * sizeof(*kmask_d));
REGS_Reg64 *kmask_s = &src->k0;
for(U32 n = 0; n < 8; n += 1, kmask_s += 1, kmask_d += 1)
{
MemoryCopy(kmask_d, kmask_s, sizeof(*kmask_d));
}
DWORD avx512h_length = 0;
U8* avx512h_d = (U8*)LocateXStateFeature(ctx, XSTATE_AVX512_ZMM_H, &avx512h_length);
Assert(avx512h_length == 16 * sizeof(REGS_Reg256));
REGS_Reg512 *zmmh_s = &src->zmm0;
for(U32 n = 0; n < 16; n += 1, avx512h_d += sizeof(REGS_Reg256), zmmh_s += 1)
{
MemoryCopy(avx512h_d, &zmmh_s->v[32], sizeof(REGS_Reg256));
}
DWORD avx512_length = 0;
U8* avx512_d = (U8*)LocateXStateFeature(ctx, XSTATE_AVX512_ZMM, &avx512_length);
Assert(avx512_length == 16 * sizeof(REGS_Reg512));
REGS_Reg512 *zmm_s = &src->zmm16;
for(U32 n = 0; n < 16; n += 1, avx512_d += sizeof(REGS_Reg512), zmm_s += 1)
{
MemoryCopy(avx512_d, zmm_s, sizeof(REGS_Reg512));
} }
} }
@@ -1083,7 +1141,7 @@ dmn_init(void)
dmn_w32_shared->arena = arena; dmn_w32_shared->arena = arena;
dmn_w32_shared->access_mutex = os_mutex_alloc(); dmn_w32_shared->access_mutex = os_mutex_alloc();
dmn_w32_shared->detach_arena = arena_alloc(); dmn_w32_shared->detach_arena = arena_alloc();
dmn_w32_shared->entities_arena = arena_alloc__sized(GB(8), KB(64)); dmn_w32_shared->entities_arena = arena_alloc(.reserve_size = GB(8), .commit_size = KB(64));
dmn_w32_shared->entities_base = dmn_w32_entity_alloc(&dmn_w32_entity_nil, DMN_W32_EntityKind_Root, 0); dmn_w32_shared->entities_base = dmn_w32_entity_alloc(&dmn_w32_entity_nil, DMN_W32_EntityKind_Root, 0);
dmn_w32_shared->entities_id_hash_slots_count = 4096; dmn_w32_shared->entities_id_hash_slots_count = 4096;
dmn_w32_shared->entities_id_hash_slots = push_array(arena, DMN_W32_EntityIDHashSlot, dmn_w32_shared->entities_id_hash_slots_count); dmn_w32_shared->entities_id_hash_slots = push_array(arena, DMN_W32_EntityIDHashSlot, dmn_w32_shared->entities_id_hash_slots_count);
@@ -1147,7 +1205,7 @@ dmn_ctrl_exclusive_access_end(void)
} }
internal U32 internal U32
dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_LaunchOptions *options) dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_ProcessLaunchParams *params)
{ {
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
U32 result = 0; U32 result = 0;
@@ -1155,12 +1213,14 @@ dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_LaunchOptions *options)
{ {
//- rjf: produce exe / arguments string //- rjf: produce exe / arguments string
String8 cmd = {0}; String8 cmd = {0};
if(options->cmd_line.first != 0) if(params->cmd_line.first != 0)
{ {
String8List args = {0}; String8List args = {0};
String8 exe_path = options->cmd_line.first->string; String8 exe_path = params->cmd_line.first->string;
String8List exe_path_parts = str8_split_path(scratch.arena, exe_path);
exe_path = str8_list_join(scratch.arena, &exe_path_parts, &(StringJoin){.sep = str8_lit("\\")});
str8_list_pushf(scratch.arena, &args, "\"%S\"", exe_path); str8_list_pushf(scratch.arena, &args, "\"%S\"", exe_path);
for(String8Node *n = options->cmd_line.first->next; n != 0; n = n->next) for(String8Node *n = params->cmd_line.first->next; n != 0; n = n->next)
{ {
str8_list_push(scratch.arena, &args, n->string); str8_list_push(scratch.arena, &args, n->string);
} }
@@ -1172,12 +1232,12 @@ dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_LaunchOptions *options)
//- rjf: produce environment strings //- rjf: produce environment strings
String8 env = {0}; String8 env = {0};
{ {
String8List all_opts = options->env; String8List all_opts = params->env;
if(options->inherit_env != 0) if(params->inherit_env != 0)
{ {
MemoryZeroStruct(&all_opts); MemoryZeroStruct(&all_opts);
str8_list_push(scratch.arena, &all_opts, str8_lit("_NO_DEBUG_HEAP=1")); str8_list_push(scratch.arena, &all_opts, str8_lit("_NO_DEBUG_HEAP=1"));
for(String8Node *n = options->env.first; n != 0; n = n->next) for(String8Node *n = params->env.first; n != 0; n = n->next)
{ {
str8_list_push(scratch.arena, &all_opts, n->string); str8_list_push(scratch.arena, &all_opts, n->string);
} }
@@ -1194,15 +1254,45 @@ dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_LaunchOptions *options)
//- rjf: produce utf-16 strings //- rjf: produce utf-16 strings
String16 cmd16 = str16_from_8(scratch.arena, cmd); String16 cmd16 = str16_from_8(scratch.arena, cmd);
String16 dir16 = str16_from_8(scratch.arena, options->path); String16 dir16 = str16_from_8(scratch.arena, params->path);
String16 env16 = str16_from_8(scratch.arena, env); String16 env16 = str16_from_8(scratch.arena, env);
//- rjf: launch //- rjf: launch
DWORD access_flags = CREATE_UNICODE_ENVIRONMENT|DEBUG_PROCESS; DWORD creation_flags = CREATE_UNICODE_ENVIRONMENT;
if(params->debug_subprocesses)
{
creation_flags |= DEBUG_PROCESS;
}
else
{
creation_flags |= DEBUG_ONLY_THIS_PROCESS;
}
BOOL inherit_handles = 0;
STARTUPINFOW startup_info = {sizeof(startup_info)}; STARTUPINFOW startup_info = {sizeof(startup_info)};
if(!os_handle_match(params->stdout_file, os_handle_zero()))
{
HANDLE stdout_handle = (HANDLE)params->stdout_file.u64[0];
startup_info.hStdOutput = stdout_handle;
startup_info.dwFlags |= STARTF_USESTDHANDLES;
inherit_handles = 1;
}
if(!os_handle_match(params->stderr_file, os_handle_zero()))
{
HANDLE stderr_handle = (HANDLE)params->stderr_file.u64[0];
startup_info.hStdError = stderr_handle;
startup_info.dwFlags |= STARTF_USESTDHANDLES;
inherit_handles = 1;
}
if(!os_handle_match(params->stdin_file, os_handle_zero()))
{
HANDLE stdin_handle = (HANDLE)params->stdin_file.u64[0];
startup_info.hStdInput = stdin_handle;
startup_info.dwFlags |= STARTF_USESTDHANDLES;
inherit_handles = 1;
}
PROCESS_INFORMATION process_info = {0}; PROCESS_INFORMATION process_info = {0};
AllocConsole(); AllocConsole();
if(CreateProcessW(0, (WCHAR*)cmd16.str, 0, 0, 1, access_flags, (WCHAR*)env16.str, (WCHAR*)dir16.str, &startup_info, &process_info)) if(CreateProcessW(0, (WCHAR*)cmd16.str, 0, 0, 1, creation_flags, (WCHAR*)env16.str, (WCHAR*)dir16.str, &startup_info, &process_info))
{ {
// check if we are 32-bit app, and just close it immediately // check if we are 32-bit app, and just close it immediately
BOOL is_wow = 0; BOOL is_wow = 0;
@@ -1392,11 +1482,11 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
if(!dmn_handle_match(ctrls->single_step_thread, dmn_handle_zero())) if(!dmn_handle_match(ctrls->single_step_thread, dmn_handle_zero()))
{ {
DMN_W32_Entity *thread = dmn_w32_entity_from_handle(ctrls->single_step_thread); DMN_W32_Entity *thread = dmn_w32_entity_from_handle(ctrls->single_step_thread);
Architecture arch = thread->arch; Arch arch = thread->arch;
switch(arch) switch(arch)
{ {
default:{}break; default:{}break;
case Architecture_x64: case Arch_x64:
{ {
U32 ctx_flags = DMN_W32_CTX_X64|DMN_W32_CTX_INTEL_CONTROL; U32 ctx_flags = DMN_W32_CTX_X64|DMN_W32_CTX_INTEL_CONTROL;
DWORD size = 0; DWORD size = 0;
@@ -1419,19 +1509,19 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
if(!dmn_handle_match(ctrls->single_step_thread, dmn_handle_zero())) ProfScope("set single step bit") if(!dmn_handle_match(ctrls->single_step_thread, dmn_handle_zero())) ProfScope("set single step bit")
{ {
DMN_W32_Entity *thread = dmn_w32_entity_from_handle(ctrls->single_step_thread); DMN_W32_Entity *thread = dmn_w32_entity_from_handle(ctrls->single_step_thread);
Architecture arch = thread->arch; Arch arch = thread->arch;
switch(arch) switch(arch)
{ {
//- rjf: unimplemented win32/arch combos //- rjf: unimplemented win32/arch combos
case Architecture_Null: case Arch_Null:
case Architecture_COUNT: case Arch_COUNT:
{}break; {}break;
case Architecture_arm64: case Arch_arm64:
case Architecture_arm32: case Arch_arm32:
{NotImplemented;}break; {NotImplemented;}break;
//- rjf: x86 //- rjf: x86
case Architecture_x86: case Arch_x86:
{ {
REGS_RegBlockX86 regs = {0}; REGS_RegBlockX86 regs = {0};
dmn_thread_read_reg_block(ctrls->single_step_thread, &regs); dmn_thread_read_reg_block(ctrls->single_step_thread, &regs);
@@ -1440,7 +1530,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
}break; }break;
//- rjf: x64 //- rjf: x64
case Architecture_x64: case Arch_x64:
{ {
if(!GetThreadContext(thread->handle, single_step_thread_ctx)) if(!GetThreadContext(thread->handle, single_step_thread_ctx))
{ {
@@ -2037,7 +2127,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
default: default:
{ {
Temp temp = temp_begin(scratch.arena); Temp temp = temp_begin(scratch.arena);
U64 regs_block_size = regs_block_size_from_architecture(thread->arch); U64 regs_block_size = regs_block_size_from_arch(thread->arch);
void *regs_block = push_array(scratch.arena, U8, regs_block_size); void *regs_block = push_array(scratch.arena, U8, regs_block_size);
if(dmn_w32_thread_read_reg_block(thread->arch, thread->handle, regs_block)) if(dmn_w32_thread_read_reg_block(thread->arch, thread->handle, regs_block))
{ {
@@ -2048,7 +2138,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
}break; }break;
//- rjf: x64 (fastpath) //- rjf: x64 (fastpath)
case Architecture_x64: case Arch_x64:
{ {
CONTEXT *ctx = 0; CONTEXT *ctx = 0;
U32 ctx_flags = DMN_W32_CTX_X64|DMN_W32_CTX_INTEL_CONTROL; U32 ctx_flags = DMN_W32_CTX_X64|DMN_W32_CTX_INTEL_CONTROL;
@@ -2406,26 +2496,26 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
if(!dmn_handle_match(ctrls->single_step_thread, dmn_handle_zero())) ProfScope("unset single step bit") if(!dmn_handle_match(ctrls->single_step_thread, dmn_handle_zero())) ProfScope("unset single step bit")
{ {
DMN_W32_Entity *thread = dmn_w32_entity_from_handle(ctrls->single_step_thread); DMN_W32_Entity *thread = dmn_w32_entity_from_handle(ctrls->single_step_thread);
Architecture arch = thread->arch; Arch arch = thread->arch;
switch(arch) switch(arch)
{ {
//- rjf: unimplemented win32/arch combos //- rjf: unimplemented win32/arch combos
case Architecture_Null: case Arch_Null:
case Architecture_COUNT: case Arch_COUNT:
{}break; {}break;
case Architecture_arm64: case Arch_arm64:
case Architecture_arm32: case Arch_arm32:
{NotImplemented;}break; {NotImplemented;}break;
//- rjf: x86/64 //- rjf: x86/64
case Architecture_x86: case Arch_x86:
{ {
REGS_RegBlockX86 regs = {0}; REGS_RegBlockX86 regs = {0};
dmn_thread_read_reg_block(ctrls->single_step_thread, &regs); dmn_thread_read_reg_block(ctrls->single_step_thread, &regs);
regs.eflags.u32 &= ~0x100; regs.eflags.u32 &= ~0x100;
dmn_thread_write_reg_block(ctrls->single_step_thread, &regs); dmn_thread_write_reg_block(ctrls->single_step_thread, &regs);
}break; }break;
case Architecture_x64: case Arch_x64:
{ {
if(!GetThreadContext(thread->handle, single_step_thread_ctx)) if(!GetThreadContext(thread->handle, single_step_thread_ctx))
{ {
@@ -2679,10 +2769,10 @@ dmn_process_write(DMN_Handle process, Rng1U64 range, void *src)
//- rjf: threads //- rjf: threads
internal Architecture internal Arch
dmn_arch_from_thread(DMN_Handle handle) dmn_arch_from_thread(DMN_Handle handle)
{ {
Architecture arch = Architecture_Null; Arch arch = Arch_Null;
DMN_AccessScope DMN_AccessScope
{ {
DMN_W32_Entity *entity = dmn_w32_entity_from_handle(handle); DMN_W32_Entity *entity = dmn_w32_entity_from_handle(handle);
@@ -2704,18 +2794,18 @@ dmn_stack_base_vaddr_from_thread(DMN_Handle handle)
U64 tlb = thread->thread.thread_local_base; U64 tlb = thread->thread.thread_local_base;
switch(thread->arch) switch(thread->arch)
{ {
case Architecture_Null: case Arch_Null:
case Architecture_COUNT: case Arch_COUNT:
{}break; {}break;
case Architecture_arm64: case Arch_arm64:
case Architecture_arm32: case Arch_arm32:
{NotImplemented;}break; {NotImplemented;}break;
case Architecture_x64: case Arch_x64:
{ {
U64 stack_base_addr = tlb + 0x8; U64 stack_base_addr = tlb + 0x8;
dmn_w32_process_read(process->handle, r1u64(stack_base_addr, stack_base_addr+8), &result); dmn_w32_process_read(process->handle, r1u64(stack_base_addr, stack_base_addr+8), &result);
}break; }break;
case Architecture_x86: case Arch_x86:
{ {
U64 stack_base_addr = tlb + 0x4; U64 stack_base_addr = tlb + 0x4;
dmn_w32_process_read(process->handle, r1u64(stack_base_addr, stack_base_addr+4), &result); dmn_w32_process_read(process->handle, r1u64(stack_base_addr, stack_base_addr+4), &result);
@@ -2738,17 +2828,17 @@ dmn_tls_root_vaddr_from_thread(DMN_Handle handle)
result = entity->thread.thread_local_base; result = entity->thread.thread_local_base;
switch(entity->arch) switch(entity->arch)
{ {
case Architecture_Null: case Arch_Null:
case Architecture_COUNT: case Arch_COUNT:
{}break; {}break;
case Architecture_arm64: case Arch_arm64:
case Architecture_arm32: case Arch_arm32:
{NotImplemented;}break; {NotImplemented;}break;
case Architecture_x64: case Arch_x64:
{ {
result += 88; result += 88;
}break; }break;
case Architecture_x86: case Arch_x86:
{ {
result += 44; result += 44;
}break; }break;
+4 -4
View File
@@ -106,7 +106,7 @@ struct DMN_W32_Entity
U32 gen; U32 gen;
U64 id; U64 id;
HANDLE handle; HANDLE handle;
Architecture arch; Arch arch;
union union
{ {
struct struct
@@ -174,7 +174,7 @@ struct DMN_W32_InjectedBreak
typedef struct DMN_W32_ImageInfo DMN_W32_ImageInfo; typedef struct DMN_W32_ImageInfo DMN_W32_ImageInfo;
struct DMN_W32_ImageInfo struct DMN_W32_ImageInfo
{ {
Architecture arch; Arch arch;
U32 size; U32 size;
}; };
@@ -277,8 +277,8 @@ internal DMN_W32_ImageInfo dmn_w32_image_info_from_process_base_vaddr(HANDLE pro
//- rjf: threads //- rjf: threads
internal U16 dmn_w32_real_tag_word_from_xsave(XSAVE_FORMAT *fxsave); internal U16 dmn_w32_real_tag_word_from_xsave(XSAVE_FORMAT *fxsave);
internal U16 dmn_w32_xsave_tag_word_from_real_tag_word(U16 ftw); internal U16 dmn_w32_xsave_tag_word_from_real_tag_word(U16 ftw);
internal B32 dmn_w32_thread_read_reg_block(Architecture arch, HANDLE thread, void *reg_block); internal B32 dmn_w32_thread_read_reg_block(Arch arch, HANDLE thread, void *reg_block);
internal B32 dmn_w32_thread_write_reg_block(Architecture arch, HANDLE thread, void *reg_block); internal B32 dmn_w32_thread_write_reg_block(Arch arch, HANDLE thread, void *reg_block);
//- rjf: remote thread injection //- rjf: remote thread injection
internal DWORD dmn_w32_inject_thread(HANDLE process, U64 start_address); internal DWORD dmn_w32_inject_thread(HANDLE process, U64 start_address);
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-535
View File
@@ -1,535 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
//- GENERATED CODE
C_LINKAGE_BEGIN
Rng1U64 df_g_cmd_param_slot_range_table[24] =
{
{0},
{OffsetOf(DF_CmdParams, window), OffsetOf(DF_CmdParams, window) + sizeof(DF_Handle)},
{OffsetOf(DF_CmdParams, panel), OffsetOf(DF_CmdParams, panel) + sizeof(DF_Handle)},
{OffsetOf(DF_CmdParams, dest_panel), OffsetOf(DF_CmdParams, dest_panel) + sizeof(DF_Handle)},
{OffsetOf(DF_CmdParams, prev_view), OffsetOf(DF_CmdParams, prev_view) + sizeof(DF_Handle)},
{OffsetOf(DF_CmdParams, view), OffsetOf(DF_CmdParams, view) + sizeof(DF_Handle)},
{OffsetOf(DF_CmdParams, entity), OffsetOf(DF_CmdParams, entity) + sizeof(DF_Handle)},
{OffsetOf(DF_CmdParams, entity_list), OffsetOf(DF_CmdParams, entity_list) + sizeof(DF_HandleList)},
{OffsetOf(DF_CmdParams, string), OffsetOf(DF_CmdParams, string) + sizeof(String8)},
{OffsetOf(DF_CmdParams, file_path), OffsetOf(DF_CmdParams, file_path) + sizeof(String8)},
{OffsetOf(DF_CmdParams, text_point), OffsetOf(DF_CmdParams, text_point) + sizeof(TxtPt)},
{OffsetOf(DF_CmdParams, cmd_spec), OffsetOf(DF_CmdParams, cmd_spec) + sizeof(struct DF_CmdSpec *)},
{OffsetOf(DF_CmdParams, view_spec), OffsetOf(DF_CmdParams, view_spec) + sizeof(struct DF_ViewSpec *)},
{OffsetOf(DF_CmdParams, cfg_node), OffsetOf(DF_CmdParams, cfg_node) + sizeof(struct DF_CfgNode *)},
{OffsetOf(DF_CmdParams, os_event), OffsetOf(DF_CmdParams, os_event) + sizeof(struct OS_Event *)},
{OffsetOf(DF_CmdParams, vaddr), OffsetOf(DF_CmdParams, vaddr) + sizeof(U64)},
{OffsetOf(DF_CmdParams, voff), OffsetOf(DF_CmdParams, voff) + sizeof(U64)},
{OffsetOf(DF_CmdParams, index), OffsetOf(DF_CmdParams, index) + sizeof(U64)},
{OffsetOf(DF_CmdParams, id), OffsetOf(DF_CmdParams, id) + sizeof(U64)},
{OffsetOf(DF_CmdParams, prefer_dasm), OffsetOf(DF_CmdParams, prefer_dasm) + sizeof(B32)},
{OffsetOf(DF_CmdParams, force_confirm), OffsetOf(DF_CmdParams, force_confirm) + sizeof(B32)},
{OffsetOf(DF_CmdParams, dir2), OffsetOf(DF_CmdParams, dir2) + sizeof(Dir2)},
{OffsetOf(DF_CmdParams, base_unwind_index), OffsetOf(DF_CmdParams, base_unwind_index) + sizeof(U64)},
{OffsetOf(DF_CmdParams, inline_unwind_index), OffsetOf(DF_CmdParams, inline_unwind_index) + sizeof(U64)},
};
DF_IconKind df_g_entity_kind_icon_kind_table[25] =
{
DF_IconKind_Null,
DF_IconKind_Null,
DF_IconKind_Machine,
DF_IconKind_FileOutline,
DF_IconKind_FileOutline,
DF_IconKind_Binoculars,
DF_IconKind_Pin,
DF_IconKind_CircleFilled,
DF_IconKind_CircleFilled,
DF_IconKind_Target,
DF_IconKind_Null,
DF_IconKind_Null,
DF_IconKind_Null,
DF_IconKind_Null,
DF_IconKind_Briefcase,
DF_IconKind_Null,
DF_IconKind_Null,
DF_IconKind_Threads,
DF_IconKind_Thread,
DF_IconKind_Module,
DF_IconKind_Threads,
DF_IconKind_Module,
DF_IconKind_Null,
DF_IconKind_Null,
DF_IconKind_Null,
};
String8 df_g_entity_kind_display_string_table[25] =
{
str8_lit_comp("Nil"),
str8_lit_comp("Root"),
str8_lit_comp("Machine"),
str8_lit_comp("File"),
str8_lit_comp("Override File Link"),
str8_lit_comp("Auto View Rule"),
str8_lit_comp("Watch Pin"),
str8_lit_comp("Breakpoint"),
str8_lit_comp("Condition"),
str8_lit_comp("Target"),
str8_lit_comp("Executable"),
str8_lit_comp("Arguments"),
str8_lit_comp("Execution Path"),
str8_lit_comp("Entry Point Name"),
str8_lit_comp("Recent Project"),
str8_lit_comp("Source"),
str8_lit_comp("Destination"),
str8_lit_comp("Process"),
str8_lit_comp("Thread"),
str8_lit_comp("Module"),
str8_lit_comp("Pending Thread Name"),
str8_lit_comp("Debug Info Path"),
str8_lit_comp("Conversion Task"),
str8_lit_comp("Conversion Failure"),
str8_lit_comp("EndedProcess"),
};
String8 df_g_entity_kind_name_label_table[25] =
{
str8_lit_comp("Label"),
str8_lit_comp("Label"),
str8_lit_comp("Label"),
str8_lit_comp("Label"),
str8_lit_comp("Label"),
str8_lit_comp("Label"),
str8_lit_comp("Expression"),
str8_lit_comp("Label"),
str8_lit_comp("Expression"),
str8_lit_comp("Label"),
str8_lit_comp("Executable"),
str8_lit_comp("Arguments"),
str8_lit_comp("Execution Path"),
str8_lit_comp("Symbol Name"),
str8_lit_comp("Path"),
str8_lit_comp("Path"),
str8_lit_comp("Path"),
str8_lit_comp("Label"),
str8_lit_comp("Label"),
str8_lit_comp("Label"),
str8_lit_comp("Label"),
str8_lit_comp("Label"),
str8_lit_comp("Label"),
str8_lit_comp("Label"),
str8_lit_comp("Label"),
};
DF_EntityKindFlags df_g_entity_kind_flags_table[25] =
{
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(1*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 1*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 1*DF_EntityKindFlag_NameIsCode | 1*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 1*DF_EntityKindFlag_LeafMutationProjectConfig | 1*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 1*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 1*DF_EntityKindFlag_LeafMutationProjectConfig | 1*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 1*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 1*DF_EntityKindFlag_NameIsCode | 1*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 1*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 1*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 1*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 1*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 1*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 1*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 1*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 1*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 1*DF_EntityKindFlag_LeafMutationProjectConfig | 1*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 1*DF_EntityKindFlag_UserDefinedLifetime),
(1*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 1*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProjectConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProjectConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
};
DF_EntityOpFlags df_g_entity_kind_op_flags_table[25] =
{
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (1*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (1*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(1*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (1*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (1*DF_EntityOpFlag_Duplicate),
(1*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (1*DF_EntityOpFlag_Rename) | (1*DF_EntityOpFlag_Enable) | (1*DF_EntityOpFlag_Condition) | (1*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(1*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (1*DF_EntityOpFlag_Edit) | (1*DF_EntityOpFlag_Rename) | (1*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (1*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (1*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (1*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (1*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (1*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (1*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (1*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(1*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (1*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
};
String8 df_g_cfg_src_string_table[4] =
{
str8_lit_comp("user"),
str8_lit_comp("project"),
str8_lit_comp("command_line"),
str8_lit_comp("transient"),
};
DF_CoreCmdKind df_g_cfg_src_load_cmd_kind_table[4] =
{
DF_CoreCmdKind_OpenUser,
DF_CoreCmdKind_OpenProject,
DF_CoreCmdKind_Null,
DF_CoreCmdKind_Null,
};
DF_CoreCmdKind df_g_cfg_src_write_cmd_kind_table[4] =
{
DF_CoreCmdKind_WriteUserData,
DF_CoreCmdKind_WriteProjectData,
DF_CoreCmdKind_Null,
DF_CoreCmdKind_Null,
};
DF_CoreCmdKind df_g_cfg_src_apply_cmd_kind_table[4] =
{
DF_CoreCmdKind_ApplyUserData,
DF_CoreCmdKind_ApplyProjectData,
DF_CoreCmdKind_Null,
DF_CoreCmdKind_Null,
};
DF_CmdSpecInfo df_g_core_cmd_kind_spec_info_table[221] =
{
{ str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("exit"), str8_lit_comp("Exits the debugger."), str8_lit_comp("quit,close,abort"), str8_lit_comp("Exit"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_X},
{ str8_lit_comp("run_command"), str8_lit_comp("Runs a command from the command palette."), str8_lit_comp("help,cmd"), str8_lit_comp("Run Command"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_CmdSpec, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("error"), str8_lit_comp("Notifies of an error."), str8_lit_comp(""), str8_lit_comp("Error"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("os_event"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("OS Event"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("launch_and_run"), str8_lit_comp("Starts debugging a new instance of a target, then runs."), str8_lit_comp("launch,start,run,target"), str8_lit_comp("Launch and Run"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_EntityList, DF_EntityKind_Target, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Play},
{ str8_lit_comp("launch_and_init"), str8_lit_comp("Starts debugging a new instance of a target, then stops at the program's entry point."), str8_lit_comp("launch,start,entry,point"), str8_lit_comp("Launch and Initialize"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_EntityList, DF_EntityKind_Target, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_PlayStepForward},
{ str8_lit_comp("kill"), str8_lit_comp("Kills the specified existing debugged process(es)."), str8_lit_comp("stop,kill"), str8_lit_comp("Kill"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_EntityList, DF_EntityKind_Process, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Stop},
{ str8_lit_comp("kill_all"), str8_lit_comp("Kills all debugged child processes."), str8_lit_comp("stop,kill,all"), str8_lit_comp("Kill All"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Stop},
{ str8_lit_comp("detach"), str8_lit_comp("Detaches the specified debugged process."), str8_lit_comp("detach"), str8_lit_comp("Detach"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_EntityList, DF_EntityKind_Process, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Null},
{ str8_lit_comp("continue"), str8_lit_comp("Continues all halted threads."), str8_lit_comp(""), str8_lit_comp("Continue"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Play},
{ str8_lit_comp("step_into_inst"), str8_lit_comp("Performs a step that goes into calls, at the instruction level."), str8_lit_comp("single,step,thread"), str8_lit_comp("Step Into (Assembly)"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_StepInto},
{ str8_lit_comp("step_over_inst"), str8_lit_comp("Performs a step that skips calls, at the instruction level."), str8_lit_comp("single,step,thread"), str8_lit_comp("Step Over (Assembly)"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_StepOver},
{ str8_lit_comp("step_into_line"), str8_lit_comp("Performs a step that goes into calls, at the source code line level."), str8_lit_comp("step,thread"), str8_lit_comp("Step Into (Line)"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_StepInto},
{ str8_lit_comp("step_over_line"), str8_lit_comp("Performs a step that skips calls, at the source code line level."), str8_lit_comp("step,thread"), str8_lit_comp("Step Over (Line)"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_StepOver},
{ str8_lit_comp("step_out"), str8_lit_comp("Runs to the end of the current function and exits it."), str8_lit_comp(""), str8_lit_comp("Step Out"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_StepOut},
{ str8_lit_comp("halt"), str8_lit_comp("Halts all running processes."), str8_lit_comp("pause"), str8_lit_comp("Halt"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Pause},
{ str8_lit_comp("soft_halt_refresh"), str8_lit_comp("Interrupts all running processes to collect data, and then resumes them."), str8_lit_comp(""), str8_lit_comp("Soft Halt Refresh"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Refresh},
{ str8_lit_comp("set_thread_ip"), str8_lit_comp("Sets the passed thread's instruction pointer at the passed address."), str8_lit_comp(""), str8_lit_comp("Set Thread IP"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_VirtualAddr, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*1)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Null},
{ str8_lit_comp("run_to_line"), str8_lit_comp("Runs until a particular source line is hit."), str8_lit_comp(""), str8_lit_comp("Run To Line"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Play},
{ str8_lit_comp("run_to_address"), str8_lit_comp("Runs until a particular address is hit."), str8_lit_comp(""), str8_lit_comp("Run To Address"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_VirtualAddr, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*1)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_PlayStepForward},
{ str8_lit_comp("run"), str8_lit_comp("Runs all targets after starting them if they have not been started yet."), str8_lit_comp("play"), str8_lit_comp("Run"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Play},
{ str8_lit_comp("restart"), str8_lit_comp("Kills all running processes, then restarts the targets which were used to launch all current processes (if any)."), str8_lit_comp("restart,retry"), str8_lit_comp("Restart"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Redo},
{ str8_lit_comp("step_into"), str8_lit_comp("Steps once, possibly into function calls, for either line or instructions."), str8_lit_comp(""), str8_lit_comp("Step Into"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_StepInto},
{ str8_lit_comp("step_over"), str8_lit_comp("Steps once, always over function calls, for either line or instructions."), str8_lit_comp(""), str8_lit_comp("Step Over"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_StepOver},
{ str8_lit_comp("run_to_cursor"), str8_lit_comp("Runs the selected thread to the current cursor."), str8_lit_comp(""), str8_lit_comp("Run To Cursor"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Play},
{ str8_lit_comp("set_next_statement"), str8_lit_comp("Sets the selected thread's instruction pointer to the cursor's position."), str8_lit_comp(""), str8_lit_comp("Set Next Statement"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_RightArrow},
{ str8_lit_comp("select_thread"), str8_lit_comp("Selects a thread."), str8_lit_comp(""), str8_lit_comp("Select Thread"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Thread, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Null},
{ str8_lit_comp("select_thread_window"), str8_lit_comp("Selects a thread for the active window, overriding the global selected thread."), str8_lit_comp(""), str8_lit_comp("Select Thread On Window"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Thread, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Null},
{ str8_lit_comp("select_thread_view"), str8_lit_comp("Selects a thread for the active view, overriding the global and per-window selected threads."), str8_lit_comp(""), str8_lit_comp("Select Thread On View"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Thread, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Null},
{ str8_lit_comp("select_unwind"), str8_lit_comp("Selects an unwind frame number for the selected thread."), str8_lit_comp(""), str8_lit_comp("Select Unwind"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("up_one_frame"), str8_lit_comp("Selects the call stack frame above the currently selected."), str8_lit_comp(""), str8_lit_comp("Up One Frame"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_UpArrow},
{ str8_lit_comp("down_one_frame"), str8_lit_comp("Selects the call stack frame below the currently selected."), str8_lit_comp("callstack,unwind"), str8_lit_comp("Down One Frame"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_DownArrow},
{ str8_lit_comp("freeze_thread"), str8_lit_comp("Freezes the passed thread."), str8_lit_comp("callstack,unwind"), str8_lit_comp("Freeze Thread"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Thread, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Locked},
{ str8_lit_comp("thaw_thread"), str8_lit_comp("Thaws the passed thread."), str8_lit_comp(""), str8_lit_comp("Thaw Thread"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Thread, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Unlocked},
{ str8_lit_comp("freeze_process"), str8_lit_comp("Freezes the passed process."), str8_lit_comp(""), str8_lit_comp("Freeze Process"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Process, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Locked},
{ str8_lit_comp("thaw_process"), str8_lit_comp("Thaws the passed process."), str8_lit_comp(""), str8_lit_comp("Thaw Process"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Process, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Unlocked},
{ str8_lit_comp("freeze_machine"), str8_lit_comp("Freezes the passed machine."), str8_lit_comp(""), str8_lit_comp("Freeze Machine"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Entity, DF_EntityKind_Machine, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Locked},
{ str8_lit_comp("thaw_machine"), str8_lit_comp("Thaws the passed machine."), str8_lit_comp(""), str8_lit_comp("Thaw Machine"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Entity, DF_EntityKind_Machine, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Unlocked},
{ str8_lit_comp("freeze_local_machine"), str8_lit_comp("Freezes the local machine."), str8_lit_comp(""), str8_lit_comp("Freeze Local Machine"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Machine},
{ str8_lit_comp("thaw_local_machine"), str8_lit_comp("Thaws the local machine."), str8_lit_comp(""), str8_lit_comp("Thaw Local Machine"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Machine},
{ str8_lit_comp("inc_ui_font_scale"), str8_lit_comp("Increases the font size used for UI."), str8_lit_comp(""), str8_lit_comp("Increase UI Font Scale"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("dec_ui_font_scale"), str8_lit_comp("Decreases the font size used for UI."), str8_lit_comp(""), str8_lit_comp("Decrease UI Font Scale"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("inc_code_font_scale"), str8_lit_comp("Increases the font size used for code."), str8_lit_comp(""), str8_lit_comp("Increase Code Font Scale"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("dec_code_font_scale"), str8_lit_comp("Decreases the font size used for code."), str8_lit_comp(""), str8_lit_comp("Decrease Code Font Scale"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("open_window"), str8_lit_comp("Opens a new window."), str8_lit_comp(""), str8_lit_comp("Open New Window"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Window},
{ str8_lit_comp("close_window"), str8_lit_comp("Closes an opened window."), str8_lit_comp(""), str8_lit_comp("Close Window"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Window},
{ str8_lit_comp("toggle_fullscreen"), str8_lit_comp("Toggles fullscreen view on the active window."), str8_lit_comp(""), str8_lit_comp("Toggle Fullscreen"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Window},
{ str8_lit_comp("confirm_accept"), str8_lit_comp("Accepts the active confirmation prompt."), str8_lit_comp(""), str8_lit_comp("Confirm Accept"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("confirm_cancel"), str8_lit_comp("Cancels the active confirmation prompt."), str8_lit_comp(""), str8_lit_comp("Confirm Cancel"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("reset_to_default_panels"), str8_lit_comp("Resets the window to the default panel layout."), str8_lit_comp("panel"), str8_lit_comp("Reset To Default Panel Layout"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Window},
{ str8_lit_comp("reset_to_compact_panels"), str8_lit_comp("Resets the window to the compact panel layout."), str8_lit_comp("panel"), str8_lit_comp("Reset To Compact Panel Layout"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Window},
{ str8_lit_comp("new_panel_left"), str8_lit_comp("Creates a new panel to the left of the active panel."), str8_lit_comp("panel"), str8_lit_comp("Split Panel Left"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_XSplit},
{ str8_lit_comp("new_panel_up"), str8_lit_comp("Creates a new panel at the top of the active panel."), str8_lit_comp("panel"), str8_lit_comp("Split Panel Up"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_YSplit},
{ str8_lit_comp("new_panel_right"), str8_lit_comp("Creates a new panel to the right of the active panel."), str8_lit_comp("panel"), str8_lit_comp("Split Panel Right"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_XSplit},
{ str8_lit_comp("new_panel_down"), str8_lit_comp("Creates a new panel at the bottom of the active panel."), str8_lit_comp("panel"), str8_lit_comp("Split Panel Down"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_YSplit},
{ str8_lit_comp("split_panel"), str8_lit_comp("Creates a new panel in a given direction, and moves a tab to it, if specified."), str8_lit_comp(""), str8_lit_comp("Split Panel"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("rotate_panel_columns"), str8_lit_comp("Rotates all panels at the closest column level of the panel hierarchy."), str8_lit_comp(""), str8_lit_comp("Rotate Panel Columns"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("next_panel"), str8_lit_comp("Cycles the active panel forward."), str8_lit_comp(""), str8_lit_comp("Focus Next Panel"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_RightArrow},
{ str8_lit_comp("prev_panel"), str8_lit_comp("Cycles the active panel backwards."), str8_lit_comp(""), str8_lit_comp("Focus Previous Panel"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_LeftArrow},
{ str8_lit_comp("focus_panel"), str8_lit_comp("Focuses a new panel."), str8_lit_comp(""), str8_lit_comp("Focus Panel"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("focus_panel_right"), str8_lit_comp("Focuses a panel rightward of the currently focused panel."), str8_lit_comp(""), str8_lit_comp("Focus Panel Right"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_RightArrow},
{ str8_lit_comp("focus_panel_left"), str8_lit_comp("Focuses a panel leftward of the currently focused panel."), str8_lit_comp(""), str8_lit_comp("Focus Panel Left"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_LeftArrow},
{ str8_lit_comp("focus_panel_up"), str8_lit_comp("Focuses a panel upward of the currently focused panel."), str8_lit_comp(""), str8_lit_comp("Focus Panel Up"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_UpArrow},
{ str8_lit_comp("focus_panel_down"), str8_lit_comp("Focuses a panel downward of the currently focused panel."), str8_lit_comp(""), str8_lit_comp("Focus Panel Down"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_DownArrow},
{ str8_lit_comp("undo"), str8_lit_comp("Undoes the previous action."), str8_lit_comp(""), str8_lit_comp("Undo"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Undo},
{ str8_lit_comp("redo"), str8_lit_comp("Redoes the first previously undone action."), str8_lit_comp(""), str8_lit_comp("Redo"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Redo},
{ str8_lit_comp("go_back"), str8_lit_comp("Returns to the previously selected panel and tab in recorded history."), str8_lit_comp(""), str8_lit_comp("Go Back"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_LeftArrow},
{ str8_lit_comp("go_forward"), str8_lit_comp("Returns to the next selected panel and tab in recorded history."), str8_lit_comp(""), str8_lit_comp("Go Forward"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_RightArrow},
{ str8_lit_comp("close_panel"), str8_lit_comp("Closes the currently active panel."), str8_lit_comp(""), str8_lit_comp("Close Panel"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_ClosePanel},
{ str8_lit_comp("next_tab"), str8_lit_comp("Focuses the next tab on the active panel."), str8_lit_comp(""), str8_lit_comp("Focus Next Tab"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_RightArrow},
{ str8_lit_comp("prev_tab"), str8_lit_comp("Focuses the previous tab on the active panel."), str8_lit_comp(""), str8_lit_comp("Focus Previous Tab"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_LeftArrow},
{ str8_lit_comp("move_tab_right"), str8_lit_comp("Moves the selected tab right one slot."), str8_lit_comp(""), str8_lit_comp("Move Tab Right"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_RightArrow},
{ str8_lit_comp("move_tab_left"), str8_lit_comp("Moves the selected tab left one slot."), str8_lit_comp(""), str8_lit_comp("Move Tab Left"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_LeftArrow},
{ str8_lit_comp("open_tab"), str8_lit_comp("Opens a new tab with the parameterized view specification."), str8_lit_comp(""), str8_lit_comp("Open Tab"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("close_tab"), str8_lit_comp("Closes the currently opened tab."), str8_lit_comp(""), str8_lit_comp("Close Tab"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_X},
{ str8_lit_comp("move_tab"), str8_lit_comp("Moves a tab to a new panel."), str8_lit_comp(""), str8_lit_comp("Move Tab"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("tab_bar_top"), str8_lit_comp("Anchors a panel's tab bar to the top of the panel."), str8_lit_comp(""), str8_lit_comp("Anchor Tab Bar To Top"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_UpArrow},
{ str8_lit_comp("tab_bar_bottom"), str8_lit_comp("Anchors a panel's tab bar to the bottom of the panel."), str8_lit_comp(""), str8_lit_comp("Anchor Tab Bar To Bottom"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_DownArrow},
{ str8_lit_comp("set_current_path"), str8_lit_comp("Sets the debugger's current path, which is used as a starting point when browsing for files."), str8_lit_comp(""), str8_lit_comp("Set Current Path"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_FileOutline},
{ str8_lit_comp("open"), str8_lit_comp("Opens a file."), str8_lit_comp("code,source,file"), str8_lit_comp("Open"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_FilePath, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*1)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_FileOutline},
{ str8_lit_comp("switch"), str8_lit_comp("Switches to a loaded file."), str8_lit_comp("code,source,file"), str8_lit_comp("Switch"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_File, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_FileOutline},
{ str8_lit_comp("switch_to_partner_file"), str8_lit_comp("Switches to the focused file's partner; or from header to implementation or vice versa."), str8_lit_comp("code,source,file"), str8_lit_comp("Switch To Partner File"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_FileOutline},
{ str8_lit_comp("go_to_disassembly"), str8_lit_comp("Goes to the disassembly, if any, for a given source code line."), str8_lit_comp("code,source,disassembly,disasm"), str8_lit_comp("Go To Disassembly"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Glasses},
{ str8_lit_comp("go_to_source"), str8_lit_comp("Goes to the source code, if any, for a given disassembly line."), str8_lit_comp("code,source,disassembly,disasm"), str8_lit_comp("Go To Source"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_FileOutline},
{ str8_lit_comp("set_file_override_link_src"), str8_lit_comp("Sets the source path for an override file link."), str8_lit_comp(""), str8_lit_comp("Set File Override Link Source"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("set_file_override_link_dst"), str8_lit_comp("Sets the destination path for an override file link."), str8_lit_comp(""), str8_lit_comp("Set File Override Link Destination"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("set_file_replacement_path"), str8_lit_comp("Sets the path which should be used as the replacement for the passed file."), str8_lit_comp(""), str8_lit_comp("Set File Replacement Path"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("set_auto_view_rule_type"), str8_lit_comp("Sets the type for an auto view rule."), str8_lit_comp(""), str8_lit_comp("Set Auto View Rule Type"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("set_auto_view_rule_view_rule"), str8_lit_comp("Sets the view rule string for an auto view rule."), str8_lit_comp(""), str8_lit_comp("Set Auto View Rule View Rule"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("open_user"), str8_lit_comp("Opens a user file path, immediately loading it, and begins autosaving to it."), str8_lit_comp("load,user,project,layout"), str8_lit_comp("Open User"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_FilePath, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*1)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Person},
{ str8_lit_comp("open_project"), str8_lit_comp("Opens a project file path, immediately loading it, and begins autosaving to it."), str8_lit_comp("project,project,session"), str8_lit_comp("Open Project"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_FilePath, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*1)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Briefcase},
{ str8_lit_comp("open_recent_project"), str8_lit_comp("Opens a recently used project file."), str8_lit_comp("project,project,session"), str8_lit_comp("Open Recent Project"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_RecentProject, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Briefcase},
{ str8_lit_comp("apply_user_data"), str8_lit_comp("Applies user data from the active user file."), str8_lit_comp(""), str8_lit_comp("Apply User Data"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("apply_project_data"), str8_lit_comp("Applies project data from the active project file."), str8_lit_comp(""), str8_lit_comp("Apply Project Data"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("write_user_data"), str8_lit_comp("Writes user data to the active user file."), str8_lit_comp(""), str8_lit_comp("Write User Data"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("write_project_data"), str8_lit_comp("Writes project data to the active project file."), str8_lit_comp(""), str8_lit_comp("Write Project Data"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("edit"), str8_lit_comp("Edits the current selection."), str8_lit_comp(""), str8_lit_comp("Edit"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Pencil},
{ str8_lit_comp("accept"), str8_lit_comp("Accepts current changes, or answers prompts in the affirmative."), str8_lit_comp(""), str8_lit_comp("Accept"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_CheckFilled},
{ str8_lit_comp("cancel"), str8_lit_comp("Rejects current changes, exits temporary menus, or answers prompts in the negative."), str8_lit_comp(""), str8_lit_comp("Cancel"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_X},
{ str8_lit_comp("move_left"), str8_lit_comp("Moves the cursor or selection left."), str8_lit_comp(""), str8_lit_comp("Move Left"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_right"), str8_lit_comp("Moves the cursor or selection right."), str8_lit_comp(""), str8_lit_comp("Move Right"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_up"), str8_lit_comp("Moves the cursor or selection up."), str8_lit_comp(""), str8_lit_comp("Move Up"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_down"), str8_lit_comp("Moves the cursor or selection down."), str8_lit_comp(""), str8_lit_comp("Move Down"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_left_select"), str8_lit_comp("Moves the cursor or selection left, while selecting."), str8_lit_comp(""), str8_lit_comp("Move Left Select"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_right_select"), str8_lit_comp("Moves the cursor or selection right, while selecting."), str8_lit_comp(""), str8_lit_comp("Move Right Select"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_up_select"), str8_lit_comp("Moves the cursor or selection up, while selecting."), str8_lit_comp(""), str8_lit_comp("Move Up Select"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_down_select"), str8_lit_comp("Moves the cursor or selection down, while selecting."), str8_lit_comp(""), str8_lit_comp("Move Down Select"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_left_chunk"), str8_lit_comp("Moves the cursor or selection left one chunk."), str8_lit_comp(""), str8_lit_comp("Move Left Select"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_right_chunk"), str8_lit_comp("Moves the cursor or selection right one chunk."), str8_lit_comp(""), str8_lit_comp("Move Right Select"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_up_chunk"), str8_lit_comp("Moves the cursor or selection up one chunk."), str8_lit_comp(""), str8_lit_comp("Move Up Chunk"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_down_chunk"), str8_lit_comp("Moves the cursor or selection down one chunk."), str8_lit_comp(""), str8_lit_comp("Move Down Chunk"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_up_page"), str8_lit_comp("Moves the cursor or selection up one page."), str8_lit_comp(""), str8_lit_comp("Move Up Page"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_down_page"), str8_lit_comp("Moves the cursor or selection down one page."), str8_lit_comp(""), str8_lit_comp("Move Down Page"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_up_whole"), str8_lit_comp("Moves the cursor or selection to the beginning of the relevant content."), str8_lit_comp(""), str8_lit_comp("Move Up Whole"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_down_whole"), str8_lit_comp("Moves the cursor or selection to the end of the relevant content."), str8_lit_comp(""), str8_lit_comp("Move Down Whole"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_left_chunk_select"), str8_lit_comp("Moves the cursor or selection left one chunk."), str8_lit_comp(""), str8_lit_comp("Move Left Chunk Select"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_right_chunk_select"), str8_lit_comp("Moves the cursor or selection right one chunk."), str8_lit_comp(""), str8_lit_comp("Move Right Chunk Select"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_up_chunk_select"), str8_lit_comp("Moves the cursor or selection up one chunk."), str8_lit_comp(""), str8_lit_comp("Move Up Chunk Select"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_down_chunk_select"), str8_lit_comp("Moves the cursor or selection down one chunk."), str8_lit_comp(""), str8_lit_comp("Move Down Chunk Select"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_up_page_select"), str8_lit_comp("Moves the cursor or selection up one page, while selecting."), str8_lit_comp(""), str8_lit_comp("Move Up Page Select"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_down_page_select"), str8_lit_comp("Moves the cursor or selection down one page, while selecting."), str8_lit_comp(""), str8_lit_comp("Move Down Page Select"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_up_whole_select"), str8_lit_comp("Moves the cursor or selection to the beginning of the relevant content, while selecting."), str8_lit_comp(""), str8_lit_comp("Move Up Whole Select"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_down_whole_select"), str8_lit_comp("Moves the cursor or selection to the end of the relevant content, while selecting."), str8_lit_comp(""), str8_lit_comp("Move Down Whole Select"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_up_reorder"), str8_lit_comp("Moves the cursor or selection up, while swapping the currently selected element with that upward."), str8_lit_comp(""), str8_lit_comp("Move Up Reorder"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_down_reorder"), str8_lit_comp("Moves the cursor or selection down, while swapping the currently selected element with that downward."), str8_lit_comp(""), str8_lit_comp("Move Down Reorder"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_home"), str8_lit_comp("Moves the cursor to the beginning of the line."), str8_lit_comp(""), str8_lit_comp("Move Home"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_end"), str8_lit_comp("Moves the cursor to the end of the line."), str8_lit_comp(""), str8_lit_comp("Move End"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_home_select"), str8_lit_comp("Moves the cursor to the beginning of the line, while selecting."), str8_lit_comp(""), str8_lit_comp("Move Home Select"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("move_end_select"), str8_lit_comp("Moves the cursor to the end of the line, while selecting."), str8_lit_comp(""), str8_lit_comp("Move End Select"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("select_all"), str8_lit_comp("Selects everything possible."), str8_lit_comp(""), str8_lit_comp("Select All"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("delete_single"), str8_lit_comp("Deletes a single element to the right of the cursor, or the active selection."), str8_lit_comp(""), str8_lit_comp("Delete Single"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("delete_chunk"), str8_lit_comp("Deletes a chunk to the right of the cursor, or the active selection."), str8_lit_comp(""), str8_lit_comp("Delete Chunk"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("backspace_single"), str8_lit_comp("Deletes a single element to the left of the cursor, or the active selection."), str8_lit_comp(""), str8_lit_comp("Backspace Single"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("backspace_chunk"), str8_lit_comp("Deletes a chunk to the left of the cursor, or the active selection."), str8_lit_comp(""), str8_lit_comp("Backspace Chunk"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("copy"), str8_lit_comp("Copies the active selection to the clipboard."), str8_lit_comp(""), str8_lit_comp("Copy"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Clipboard},
{ str8_lit_comp("cut"), str8_lit_comp("Copies the active selection to the clipboard, then deletes it."), str8_lit_comp(""), str8_lit_comp("Cut"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Clipboard},
{ str8_lit_comp("paste"), str8_lit_comp("Pastes the current contents of the clipboard."), str8_lit_comp(""), str8_lit_comp("Paste"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Clipboard},
{ str8_lit_comp("insert_text"), str8_lit_comp("Inserts the text that was used to cause this command."), str8_lit_comp(""), str8_lit_comp("Insert Text"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("goto_line"), str8_lit_comp("Jumps to a line number in the current code file."), str8_lit_comp(""), str8_lit_comp("Go To Line"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_TextPoint, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*1)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Null},
{ str8_lit_comp("goto_address"), str8_lit_comp("Jumps to an address in the current memory or disassembly view."), str8_lit_comp(""), str8_lit_comp("Go To Address"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_VirtualAddr, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*1)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Null},
{ str8_lit_comp("center_cursor"), str8_lit_comp("Snaps the current code view to center the cursor."), str8_lit_comp(""), str8_lit_comp("Center Cursor"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("contain_cursor"), str8_lit_comp("Snaps the current code view to contain the cursor."), str8_lit_comp(""), str8_lit_comp("Contain Cursor"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("find_text_forward"), str8_lit_comp("Searches the current code file forward (from the cursor) for a string."), str8_lit_comp(""), str8_lit_comp("Find Text (Forward)"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_String, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*1)|(DF_CmdQueryFlag_KeepOldInput*1)|(DF_CmdQueryFlag_SelectOldInput*1)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Find},
{ str8_lit_comp("find_text_backward"), str8_lit_comp("Searches the current code file backwards (from the cursor) for a string."), str8_lit_comp(""), str8_lit_comp("Find Text (Backwards)"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_String, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*1)|(DF_CmdQueryFlag_KeepOldInput*1)|(DF_CmdQueryFlag_SelectOldInput*1)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Find},
{ str8_lit_comp("find_next"), str8_lit_comp("Searches the current code file forward (from the cursor) for the last searched string."), str8_lit_comp(""), str8_lit_comp("Find Next"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*1)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Find},
{ str8_lit_comp("find_prev"), str8_lit_comp("Searches the current code file backwards (from the cursor) for the last searched string."), str8_lit_comp(""), str8_lit_comp("Find Previous"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*1)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Find},
{ str8_lit_comp("find_thread"), str8_lit_comp("Jumps to the passed thread in either source code, disassembly, or both if they're already open."), str8_lit_comp(""), str8_lit_comp("Find Thread"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Thread, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Find},
{ str8_lit_comp("find_selected_thread"), str8_lit_comp("Jumps to the selected thread in either source code, disassembly, or both if they're already open."), str8_lit_comp(""), str8_lit_comp("Find Selected Thread"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Find},
{ str8_lit_comp("goto_name"), str8_lit_comp("Searches for the passed string as a file, a symbol in debug info, and more, then jumps to it if possible."), str8_lit_comp(""), str8_lit_comp("Go To Name"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_String, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*1)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Null},
{ str8_lit_comp("goto_name_at_cursor"), str8_lit_comp("Searches for the text at the cursor as a file, a symbol in debug info, and more, then jumps to it if possible."), str8_lit_comp(""), str8_lit_comp("Go To Name At Cursor"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("toggle_watch_expr"), str8_lit_comp("Adds or removes an expression to an opened watch view."), str8_lit_comp(""), str8_lit_comp("Toggle Watch Expression"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("toggle_watch_expr_at_cursor"), str8_lit_comp("Adds or removes the expression that the cursor or selection is currently over to an opened watch view."), str8_lit_comp(""), str8_lit_comp("Toggle Watch Expression At Cursor"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("toggle_watch_expr_at_mouse"), str8_lit_comp("Adds or removes the expression that the mouse is currently over to an opened watch view."), str8_lit_comp(""), str8_lit_comp("Toggle Watch Expression At Mouse"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("set_columns"), str8_lit_comp("Sets the number of columns for a memory view."), str8_lit_comp(""), str8_lit_comp("Set Columns"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Index, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*1)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Thumbnails},
{ str8_lit_comp("toggle_address_visibility"), str8_lit_comp("Toggles the visibility of addresses in a disassembly view."), str8_lit_comp(""), str8_lit_comp("Toggle Address Visibility"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Thumbnails},
{ str8_lit_comp("toggle_code_bytes_visibility"), str8_lit_comp("Toggles the visibility of machine code bytes in a disassembly view."), str8_lit_comp(""), str8_lit_comp("Toggle Code Bytes Visibility"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Thumbnails},
{ str8_lit_comp("enable_entity"), str8_lit_comp("Enables an entity."), str8_lit_comp(""), str8_lit_comp("Enable Entity"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("disable_entity"), str8_lit_comp("Disables an entity."), str8_lit_comp(""), str8_lit_comp("Disable Entity"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("freeze_entity"), str8_lit_comp("Freezes an entity."), str8_lit_comp(""), str8_lit_comp("Freeze Entity"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("thaw_entity"), str8_lit_comp("Thaws an entity."), str8_lit_comp(""), str8_lit_comp("Thaw Entity"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("remove_entity"), str8_lit_comp("Removes an entity."), str8_lit_comp(""), str8_lit_comp("Remove Entity"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("name_entity"), str8_lit_comp("Equips an entity with a name."), str8_lit_comp(""), str8_lit_comp("Name Entity"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("edit_entity"), str8_lit_comp("Opens the editor for an entity."), str8_lit_comp(""), str8_lit_comp("Edit Entity"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("duplicate_entity"), str8_lit_comp("Duplicates an entity."), str8_lit_comp(""), str8_lit_comp("Duplicate Entity"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("text_breakpoint"), str8_lit_comp("Places or removes a breakpoint on the specified line of source code."), str8_lit_comp(""), str8_lit_comp("Text Breakpoint"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_FilePath, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_CircleFilled},
{ str8_lit_comp("address_breakpoint"), str8_lit_comp("Places or removes a breakpoint on the specified address."), str8_lit_comp(""), str8_lit_comp("Address Breakpoint"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_VirtualAddr, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*1)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_CircleFilled},
{ str8_lit_comp("function_breakpoint"), str8_lit_comp("Places or removes a breakpoint on the first address(es) of the specified function."), str8_lit_comp(""), str8_lit_comp("Function Breakpoint"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_String, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*1)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_CircleFilled},
{ str8_lit_comp("toggle_breakpoint_cursor"), str8_lit_comp("Places or removes a breakpoint on the line on which the active cursor sits."), str8_lit_comp(""), str8_lit_comp("Toggle Breakpoint At Cursor"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_CircleFilled},
{ str8_lit_comp("remove_breakpoint"), str8_lit_comp("Removes an existing breakpoint."), str8_lit_comp(""), str8_lit_comp("Remove Breakpoint"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Breakpoint, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Trash},
{ str8_lit_comp("enable_breakpoint"), str8_lit_comp("Enables a breakpoint."), str8_lit_comp(""), str8_lit_comp("Enable Breakpoint"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Breakpoint, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_CheckFilled},
{ str8_lit_comp("disable_breakpoint"), str8_lit_comp("Disables a breakpoint."), str8_lit_comp(""), str8_lit_comp("Disable Breakpoint"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Breakpoint, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_CheckHollow},
{ str8_lit_comp("toggle_watch_pin"), str8_lit_comp("Places or removes a watch pin on a textual location on a particular entity."), str8_lit_comp(""), str8_lit_comp("Toggle Watch Pin"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("toggle_watch_pin_at_cursor"), str8_lit_comp("Places or removes a watch pin at the cursor on the currently active file."), str8_lit_comp(""), str8_lit_comp("Toggle Watch Pin At Cursor"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_String, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*1)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Binoculars},
{ str8_lit_comp("add_target"), str8_lit_comp("Adds a new target."), str8_lit_comp("application,executable,debug"), str8_lit_comp("Add Target"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_FilePath, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*1)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Target},
{ str8_lit_comp("remove_target"), str8_lit_comp("Removes an existing target."), str8_lit_comp("delete,remove,target"), str8_lit_comp("Remove Target"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Target, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Trash},
{ str8_lit_comp("edit_target"), str8_lit_comp("Edits an existing target."), str8_lit_comp(""), str8_lit_comp("Edit Target"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Target, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Pencil},
{ str8_lit_comp("select_target"), str8_lit_comp("Selects a target."), str8_lit_comp(""), str8_lit_comp("Select Target"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Target, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Target},
{ str8_lit_comp("enable_target"), str8_lit_comp("Enables a target, in addition to all targets currently enabled."), str8_lit_comp(""), str8_lit_comp("Enable Target"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Target, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_CheckFilled},
{ str8_lit_comp("disable_target"), str8_lit_comp("Disables a target."), str8_lit_comp(""), str8_lit_comp("Disable Target"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Target, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_CheckHollow},
{ str8_lit_comp("retry_ended_process"), str8_lit_comp("Launches a new process with the same options as the passed ended process."), str8_lit_comp(""), str8_lit_comp("Retry Ended Process"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Entity, DF_EntityKind_Process, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("attach"), str8_lit_comp("Attaches to a process that is already running on the local machine."), str8_lit_comp(""), str8_lit_comp("Attach"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_ID, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Null},
{ str8_lit_comp("register_as_jit_debugger"), str8_lit_comp("Registers the RAD debugger as the just-in-time (JIT) debugger used by the operating system."), str8_lit_comp(""), str8_lit_comp("Register As Just-In-Time (JIT) Debugger"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("entity_ref_fast_path"), str8_lit_comp("Activates the default behavior when clicking an entity reference."), str8_lit_comp(""), str8_lit_comp("Entity Reference Fast Path"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("spawn_entity_view"), str8_lit_comp("Spawns a new view, given an entity and other parameterizations."), str8_lit_comp(""), str8_lit_comp("Spawn Entity View"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("find_code_location"), str8_lit_comp("Finds a specific source code location given file, line, and column coordinates. Opens the file if necessary."), str8_lit_comp(""), str8_lit_comp("Find Code Location"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_FilePath, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_FileOutline},
{ str8_lit_comp("filter"), str8_lit_comp("Begins filtering the active view."), str8_lit_comp("sort,search,filter,find"), str8_lit_comp("Filter"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Find},
{ str8_lit_comp("apply_filter"), str8_lit_comp("Applies the typed filter to the active view."), str8_lit_comp("sort,search,filter,find,apply"), str8_lit_comp("Apply Filter"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Find},
{ str8_lit_comp("clear_filter"), str8_lit_comp("Clears the filter applied to the active view."), str8_lit_comp("sort,search,filter,find,clear"), str8_lit_comp("Clear Filter"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Find},
{ str8_lit_comp("getting_started"), str8_lit_comp("Opens the menu for information on getting started."), str8_lit_comp("tutorial,help"), str8_lit_comp("Getting Started"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_QuestionMark},
{ str8_lit_comp("commands"), str8_lit_comp("Opens the list of all commands."), str8_lit_comp(""), str8_lit_comp("Commands"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_List},
{ str8_lit_comp("target"), str8_lit_comp("Opens the editor for a target."), str8_lit_comp(""), str8_lit_comp("Target"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Target},
{ str8_lit_comp("targets"), str8_lit_comp("Opens the list of all targets."), str8_lit_comp(""), str8_lit_comp("Targets"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Target},
{ str8_lit_comp("file_path_map"), str8_lit_comp("Opens the file path mapping editor."), str8_lit_comp(""), str8_lit_comp("File Path Map"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_FileOutline},
{ str8_lit_comp("auto_view_rules"), str8_lit_comp("Opens the auto view rule editor."), str8_lit_comp(""), str8_lit_comp("Auto View Rules"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("scheduler"), str8_lit_comp("Opens the scheduler view, for process and thread controls."), str8_lit_comp("threads,processes,targets"), str8_lit_comp("Scheduler"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Scheduler},
{ str8_lit_comp("call_stack"), str8_lit_comp("Opens the call stack view."), str8_lit_comp("callstack,thread,unwind"), str8_lit_comp("Call Stack"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Thread},
{ str8_lit_comp("modules"), str8_lit_comp("Opens the modules view."), str8_lit_comp(""), str8_lit_comp("Modules"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Module},
{ str8_lit_comp("pending_entity"), str8_lit_comp("Opens a view which waits for the passed entity to be completely loaded, then replaces itself with a new view."), str8_lit_comp(""), str8_lit_comp("Pending Entity"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_FileOutline},
{ str8_lit_comp("code"), str8_lit_comp("Opens the code view for an already-loaded file."), str8_lit_comp(""), str8_lit_comp("Code"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_FileOutline},
{ str8_lit_comp("watch"), str8_lit_comp("Opens a watch view."), str8_lit_comp(""), str8_lit_comp("Watch"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("locals"), str8_lit_comp("Opens a locals view."), str8_lit_comp(""), str8_lit_comp("Locals"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("registers"), str8_lit_comp("Opens a registers view."), str8_lit_comp(""), str8_lit_comp("Registers"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("globals"), str8_lit_comp("Opens a globals view."), str8_lit_comp(""), str8_lit_comp("Globals"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("thread_locals"), str8_lit_comp("Opens a thread locals view."), str8_lit_comp(""), str8_lit_comp("Thread Locals"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("types"), str8_lit_comp("Opens a types view."), str8_lit_comp(""), str8_lit_comp("Types"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("procedures"), str8_lit_comp("Opens a procedures view."), str8_lit_comp(""), str8_lit_comp("Procedures"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Binoculars},
{ str8_lit_comp("output"), str8_lit_comp("Opens an output view."), str8_lit_comp(""), str8_lit_comp("Output"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_List},
{ str8_lit_comp("memory"), str8_lit_comp("Opens a memory view."), str8_lit_comp(""), str8_lit_comp("Memory"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Grid},
{ str8_lit_comp("disassembly"), str8_lit_comp("Opens the disassembly view."), str8_lit_comp("disasm"), str8_lit_comp("Disassembly"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Glasses},
{ str8_lit_comp("breakpoints"), str8_lit_comp("Opens the breakpoints view."), str8_lit_comp(""), str8_lit_comp("Breakpoints"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_CircleFilled},
{ str8_lit_comp("watch_pins"), str8_lit_comp("Opens the watch pins view."), str8_lit_comp(""), str8_lit_comp("Watch Pins"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Pin},
{ str8_lit_comp("exception_filters"), str8_lit_comp("Opens the exception filters view."), str8_lit_comp("exceptions,filters"), str8_lit_comp("Exception Filters"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Gear},
{ str8_lit_comp("settings"), str8_lit_comp("Opens the settings view."), str8_lit_comp("theme,color,scheme,options"), str8_lit_comp("Settings"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Gear},
{ str8_lit_comp("pick_file"), str8_lit_comp("Opens the file browser to pick a file."), str8_lit_comp(""), str8_lit_comp("Pick File"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_FilePath, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*1)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_FileOutline},
{ str8_lit_comp("pick_folder"), str8_lit_comp("Opens the file browser to pick a folder."), str8_lit_comp(""), str8_lit_comp("Pick Folder"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_FilePath, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*1)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_FolderOpenFilled},
{ str8_lit_comp("pick_file_or_folder"), str8_lit_comp("Opens the file browser to pick a file or folder."), str8_lit_comp(""), str8_lit_comp("Pick File/Folder"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_FilePath, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*1)|(DF_CmdQueryFlag_AllowFolders*1)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_FileOutline},
{ str8_lit_comp("complete_query"), str8_lit_comp("Completes a query."), str8_lit_comp(""), str8_lit_comp("Complete Query"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("cancel_query"), str8_lit_comp("Cancels a query."), str8_lit_comp(""), str8_lit_comp("Cancel Query"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("toggle_dev_menu"), str8_lit_comp("Opens and closes the developer menu."), str8_lit_comp(""), str8_lit_comp("Toggle Developer Menu"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("log_marker"), str8_lit_comp("Logs a marker in the application log, to denote specific points in time within the log."), str8_lit_comp(""), str8_lit_comp("Log Marker"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
};
DF_CoreViewRuleSpecInfo df_g_core_view_rule_spec_info_table[20] =
{
{str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (DF_CoreViewRuleSpecInfoFlag_Inherited*0)|(DF_CoreViewRuleSpecInfoFlag_Expandable*0)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*0)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*0), 0, 0, },
{str8_lit_comp("array"), str8_lit_comp("Array"), str8_lit_comp("x:{expr}"), str8_lit_comp("Specifies that a pointer points to N elements, rather than only 1."), (DF_CoreViewRuleSpecInfoFlag_Inherited*0)|(DF_CoreViewRuleSpecInfoFlag_Expandable*0)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*1)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*0), DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_NAME(array) , 0, },
{str8_lit_comp("slice"), str8_lit_comp("Slice"), str8_lit_comp(""), str8_lit_comp("Specifies that a pointer within a struct, also containing an integer, points to the number of elements encoded by the integer."), (DF_CoreViewRuleSpecInfoFlag_Inherited*0)|(DF_CoreViewRuleSpecInfoFlag_Expandable*0)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*1)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*0), DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_NAME(slice) , 0, },
{str8_lit_comp("list"), str8_lit_comp("List"), str8_lit_comp("x:{member}"), str8_lit_comp("Specifies that some struct, union, or class forms the top of a linked list, and the member which points at the following element in the list."), (DF_CoreViewRuleSpecInfoFlag_Inherited*0)|(DF_CoreViewRuleSpecInfoFlag_Expandable*0)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*0)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*1), 0, DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(list) , },
{str8_lit_comp("bswap"), str8_lit_comp("Byte Swap"), str8_lit_comp(""), str8_lit_comp("Specifies that all integer primitives should be byte-swapped, such that their endianness is reversed."), (DF_CoreViewRuleSpecInfoFlag_Inherited*1)|(DF_CoreViewRuleSpecInfoFlag_Expandable*0)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*1)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*0), DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_NAME(bswap) , 0, },
{str8_lit_comp("dec"), str8_lit_comp("Decimal Base (Base 10)"), str8_lit_comp(""), str8_lit_comp("Specifies that all integral evaluations should appear in base-10 form."), (DF_CoreViewRuleSpecInfoFlag_Inherited*1)|(DF_CoreViewRuleSpecInfoFlag_Expandable*0)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*0)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*0), 0, 0, },
{str8_lit_comp("bin"), str8_lit_comp("Binary Base (Base 2)"), str8_lit_comp(""), str8_lit_comp("Specifies that all integral evaluations should appear in base-2 form."), (DF_CoreViewRuleSpecInfoFlag_Inherited*1)|(DF_CoreViewRuleSpecInfoFlag_Expandable*0)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*0)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*0), 0, 0, },
{str8_lit_comp("oct"), str8_lit_comp("Octal Base (Base 8)"), str8_lit_comp(""), str8_lit_comp("Specifies that all integral evaluations should appear in base-8 form."), (DF_CoreViewRuleSpecInfoFlag_Inherited*1)|(DF_CoreViewRuleSpecInfoFlag_Expandable*0)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*0)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*0), 0, 0, },
{str8_lit_comp("hex"), str8_lit_comp("Hexadecimal Base (Base 16)"), str8_lit_comp(""), str8_lit_comp("Specifies that all integral evaluations should appear in base-16 form."), (DF_CoreViewRuleSpecInfoFlag_Inherited*1)|(DF_CoreViewRuleSpecInfoFlag_Expandable*0)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*0)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*0), 0, 0, },
{str8_lit_comp("only"), str8_lit_comp("Only Specified Members"), str8_lit_comp("x:{member}"), str8_lit_comp("Specifies that only the specified members should appear in struct, union, or class evaluations."), (DF_CoreViewRuleSpecInfoFlag_Inherited*1)|(DF_CoreViewRuleSpecInfoFlag_Expandable*0)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*0)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*1), 0, DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(only) , },
{str8_lit_comp("omit"), str8_lit_comp("Omit Specified Members"), str8_lit_comp("x:{member}"), str8_lit_comp("Omits a list of member names from appearing in struct, union, or class evaluations."), (DF_CoreViewRuleSpecInfoFlag_Inherited*1)|(DF_CoreViewRuleSpecInfoFlag_Expandable*0)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*0)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*1), 0, DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(omit) , },
{str8_lit_comp("no_addr"), str8_lit_comp("Disable Address Values"), str8_lit_comp(""), str8_lit_comp("Displays only what pointers point to, if possible, without the pointer's address value."), (DF_CoreViewRuleSpecInfoFlag_Inherited*1)|(DF_CoreViewRuleSpecInfoFlag_Expandable*0)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*0)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*0), 0, 0, },
{str8_lit_comp("rgba"), str8_lit_comp("Color (RGBA)"), str8_lit_comp(""), str8_lit_comp("Displays as a color, interpreting the data as encoding R, G, B, and A values."), (DF_CoreViewRuleSpecInfoFlag_Inherited*0)|(DF_CoreViewRuleSpecInfoFlag_Expandable*1)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*0)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*1), 0, DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(rgba) , },
{str8_lit_comp("text"), str8_lit_comp("Text"), str8_lit_comp("x:{'lang':lang, 'size':expr}"), str8_lit_comp("Displays as text."), (DF_CoreViewRuleSpecInfoFlag_Inherited*0)|(DF_CoreViewRuleSpecInfoFlag_Expandable*1)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*0)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*1), 0, DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(text) , },
{str8_lit_comp("disasm"), str8_lit_comp("Disassembly"), str8_lit_comp("x:{'arch':arch, 'size':expr}"), str8_lit_comp("Displays as disassembled instructions, interpreting the data as raw machine code."), (DF_CoreViewRuleSpecInfoFlag_Inherited*0)|(DF_CoreViewRuleSpecInfoFlag_Expandable*1)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*0)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*1), 0, DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(disasm) , },
{str8_lit_comp("graph"), str8_lit_comp("Graph"), str8_lit_comp(""), str8_lit_comp("Displays as a pointer graph, visualizing nodes and edges formed by pointers directly."), (DF_CoreViewRuleSpecInfoFlag_Inherited*0)|(DF_CoreViewRuleSpecInfoFlag_Expandable*1)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*0)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*1), 0, DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(graph) , },
{str8_lit_comp("bitmap"), str8_lit_comp("Bitmap"), str8_lit_comp("x:{'w':expr, 'h':expr, 'fmt':tex2dformat}"), str8_lit_comp("Displays as a bitmap, interpreting the data as raw pixel data."), (DF_CoreViewRuleSpecInfoFlag_Inherited*0)|(DF_CoreViewRuleSpecInfoFlag_Expandable*1)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*0)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*1), 0, DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(bitmap) , },
{str8_lit_comp("geo"), str8_lit_comp("Geometry"), str8_lit_comp("x:{'count':expr, 'vertices_base':expr, 'vertices_size':expr}"), str8_lit_comp("Displays as geometry, interpreting the data as vertex data."), (DF_CoreViewRuleSpecInfoFlag_Inherited*0)|(DF_CoreViewRuleSpecInfoFlag_Expandable*1)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*0)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*1), 0, DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(geo) , },
{str8_lit_comp("odin_map"), str8_lit_comp("Odin map"), str8_lit_comp(""), str8_lit_comp("Specifies that a struct should be rendered as an Odin map type."), (DF_CoreViewRuleSpecInfoFlag_Inherited*0)|(DF_CoreViewRuleSpecInfoFlag_Expandable*1)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*0)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*1), 0, DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(odin_map) , },
{str8_lit_comp("odin_slice"), str8_lit_comp("Odin slice"), str8_lit_comp(""), str8_lit_comp("Specifies a struct of {data, len} should be rendered as a slice (odin's)."), (DF_CoreViewRuleSpecInfoFlag_Inherited*0)|(DF_CoreViewRuleSpecInfoFlag_Expandable*0)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*1)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*0), DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_NAME(odin_slice) , 0, },
};
String8 df_g_icon_kind_text_table[69] =
{
str8_lit_comp(""),
str8_lit_comp("b"),
str8_lit_comp("c"),
str8_lit_comp("B"),
str8_lit_comp("C"),
str8_lit_comp("f"),
str8_lit_comp("F"),
str8_lit_comp("g"),
str8_lit_comp("h"),
str8_lit_comp("r"),
str8_lit_comp("s"),
str8_lit_comp("i"),
str8_lit_comp("w"),
str8_lit_comp("W"),
str8_lit_comp("k"),
str8_lit_comp("K"),
str8_lit_comp("L"),
str8_lit_comp("R"),
str8_lit_comp("U"),
str8_lit_comp("D"),
str8_lit_comp("G"),
str8_lit_comp("P"),
str8_lit_comp("3"),
str8_lit_comp("p"),
str8_lit_comp("O"),
str8_lit_comp("o"),
str8_lit_comp("!"),
str8_lit_comp("1"),
str8_lit_comp("<"),
str8_lit_comp(">"),
str8_lit_comp("^"),
str8_lit_comp("v"),
str8_lit_comp("9"),
str8_lit_comp("0"),
str8_lit_comp("7"),
str8_lit_comp("8"),
str8_lit_comp("+"),
str8_lit_comp("-"),
str8_lit_comp("'"),
str8_lit_comp("\""),
str8_lit_comp("M"),
str8_lit_comp("."),
str8_lit_comp("x"),
str8_lit_comp("q"),
str8_lit_comp("j"),
str8_lit_comp("u"),
str8_lit_comp("m"),
str8_lit_comp("n"),
str8_lit_comp("l"),
str8_lit_comp("a"),
str8_lit_comp("z"),
str8_lit_comp("y"),
str8_lit_comp("X"),
str8_lit_comp("Y"),
str8_lit_comp("S"),
str8_lit_comp("T"),
str8_lit_comp("Z"),
str8_lit_comp("d"),
str8_lit_comp("N"),
str8_lit_comp("E"),
str8_lit_comp("H"),
str8_lit_comp("e"),
str8_lit_comp("I"),
str8_lit_comp("J"),
str8_lit_comp("A"),
str8_lit_comp("?"),
str8_lit_comp("4"),
str8_lit_comp("5"),
str8_lit_comp("c"),
};
C_LINKAGE_END
File diff suppressed because it is too large Load Diff
-7
View File
@@ -1,7 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#include "df/core/df_core.c"
#include "df/gfx/df_gfx.c"
#include "df/gfx/df_views.c"
#include "df/gfx/df_view_rules.c"
-12
View File
@@ -1,12 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef DEBUG_FRONTEND_INC_H
#define DEBUG_FRONTEND_INC_H
#include "df/core/df_core.h"
#include "df/gfx/df_gfx.h"
#include "df/gfx/df_views.h"
#include "df/gfx/df_view_rules.h"
#endif // DEBUG_FRONTEND_INC_H
-14624
View File
File diff suppressed because it is too large Load Diff
-1117
View File
File diff suppressed because it is too large Load Diff
-731
View File
@@ -1,731 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Embedded Data
@embed_file df_g_icon_font_bytes: "../data/icons.ttf"
@embed_file df_g_default_main_font_bytes: "../data/Roboto-Regular.ttf"
@embed_file df_g_default_code_font_bytes: "../data/liberation-mono.ttf"
//@embed_file df_g_default_code_font_bytes: "../data/Inconsolata-Regular.ttf"
@embed_file df_g_icon_file_bytes: "../data/logo.ico"
////////////////////////////////
//~ rjf: Default Bindings
@table(name key ctrl shift alt)
DF_DefaultBindingTable:
{
//- rjf: low-level target control operations
{ "kill_all" F5 0 shift 0 }
{ "step_into_inst" F11 0 0 alt }
{ "step_over_inst" F10 0 0 alt }
{ "step_out" F11 0 shift 0 }
{ "halt" X ctrl shift 0 }
{ "halt" Pause 0 0 0 }
{ "soft_halt_refresh" R 0 0 alt }
//- rjf: high-level composite target control operations
{ "run" F5 0 0 0 }
{ "restart" F5 ctrl shift 0 }
{ "step_into" F11 0 0 0 }
{ "step_over" F10 0 0 0 }
{ "run_to_cursor" F10 ctrl 0 0 }
{ "set_next_statement" F10 ctrl shift 0 }
//- rjf: font sizes
{ "inc_ui_font_scale" Equal 0 0 alt }
{ "dec_ui_font_scale" Minus 0 0 alt }
{ "inc_code_font_scale" Equal 0 shift alt }
{ "dec_code_font_scale" Minus 0 shift alt }
//- rjf: windows
{ "window" N ctrl shift 0 }
{ "toggle_fullscreen" Return ctrl 0 0 }
//- rjf: panel splitting
{ "new_panel_right" P ctrl 0 0 }
{ "new_panel_down" Minus ctrl 0 0 }
//- rjf: panel rotation
{ "rotate_panel_columns" 2 ctrl 0 0 }
//- rjf: focused panel changing
{ "next_panel" Comma ctrl 0 0 }
{ "prev_panel" Comma ctrl shift 0 }
{ "focus_panel_right" Right ctrl 0 alt }
{ "focus_panel_left" Left ctrl 0 alt }
{ "focus_panel_up" Up ctrl 0 alt }
{ "focus_panel_down" Down ctrl 0 alt }
//- rjf: undo/redo
//{ "undo" Z ctrl 0 0 }
//{ "redo" Y ctrl 0 0 }
//- rjf: focus history
//{ "go_back" Left 0 0 alt }
//{ "go_forward" Right 0 0 alt }
//- rjf: panel removal
{ "close_panel" P ctrl shift 0 }
//- rjf: panel tab
{ "next_tab" PageDown ctrl 0 0 }
{ "prev_tab" PageUp ctrl 0 0 }
{ "next_tab" Tab ctrl 0 0 }
{ "prev_tab" Tab ctrl shift 0 }
{ "move_tab_right" PageDown ctrl shift 0 }
{ "move_tab_left" PageUp ctrl shift 0 }
{ "close_tab" W ctrl 0 0 }
{ "tab_bar_top" Up ctrl shift alt }
{ "tab_bar_bottom" Down ctrl shift alt }
//- rjf: files
{ "open" O ctrl 0 0 }
{ "reload_active" R ctrl shift 0 }
{ "switch" I ctrl 0 0 }
{ "switch_to_partner_file" O 0 0 alt }
//- rjf: setting config paths
{ "open_user" O ctrl shift alt }
{ "open_project" O ctrl 0 alt }
//- rjf: meta controls
{ "edit" F2 0 0 0 }
{ "accept" Return 0 0 0 }
{ "cancel" Esc 0 0 0 }
//- rjf: directional movement & text controls
{ "move_left" Left 0 0 0 }
{ "move_right" Right 0 0 0 }
{ "move_up" Up 0 0 0 }
{ "move_down" Down 0 0 0 }
{ "move_left_select" Left 0 shift 0 }
{ "move_right_select" Right 0 shift 0 }
{ "move_up_select" Up 0 shift 0 }
{ "move_down_select" Down 0 shift 0 }
{ "move_left_chunk" Left ctrl 0 0 }
{ "move_right_chunk" Right ctrl 0 0 }
{ "move_up_chunk" Up ctrl 0 0 }
{ "move_down_chunk" Down ctrl 0 0 }
{ "move_up_page" PageUp 0 0 0 }
{ "move_down_page" PageDown 0 0 0 }
{ "move_up_whole" Home ctrl 0 0 }
{ "move_down_whole" End ctrl 0 0 }
{ "move_left_chunk_select" Left ctrl shift 0 }
{ "move_right_chunk_select" Right ctrl shift 0 }
{ "move_up_chunk_select" Up ctrl shift 0 }
{ "move_down_chunk_select" Down ctrl shift 0 }
{ "move_up_page_select" PageUp 0 shift 0 }
{ "move_down_page_select" PageDown 0 shift 0 }
{ "move_up_whole_select" Home ctrl shift 0 }
{ "move_down_whole_select" End ctrl shift 0 }
{ "move_up_reorder" Up 0 0 alt }
{ "move_down_reorder" Down 0 0 alt }
{ "move_home" Home 0 0 0 }
{ "move_end" End 0 0 0 }
{ "move_home_select" Home 0 shift 0 }
{ "move_end_select" End 0 shift 0 }
{ "select_all" A ctrl 0 0 }
{ "delete_single" Delete 0 0 0 }
{ "delete_chunk" Delete ctrl 0 0 }
{ "backspace_single" Backspace 0 0 0 }
{ "backspace_chunk" Backspace ctrl 0 0 }
{ "copy" C ctrl 0 0 }
{ "copy" Insert ctrl 0 0 }
{ "cut" X ctrl 0 0 }
{ "paste" V ctrl 0 0 }
{ "paste" Insert 0 shift 0 }
{ "insert_text" Null 0 0 0 }
//- rjf: code navigation
{ "goto_line" G ctrl 0 0 }
{ "goto_address" G 0 0 alt }
{ "find_text_forward" F ctrl 0 0 }
{ "find_text_backward" R ctrl 0 0 }
{ "find_next" F3 0 0 0 }
{ "find_prev" F3 shift 0 0 }
//- rjf: thread finding
{ "find_selected_thread" F4 0 0 0 }
//- rjf: name finding
{ "goto_name" J ctrl 0 0 }
{ "goto_name_at_cursor" F12 0 0 0 }
//- rjf: watch expressions
{ "toggle_watch_expr_at_cursor" W 0 0 alt }
{ "toggle_watch_expr_at_mouse" D ctrl 0 0 }
{ "toggle_watch_pin_at_cursor" F9 ctrl 0 0 }
//- rjf: breakpoints
{ "toggle_breakpoint_cursor" F9 0 0 0 }
//- rjf: targets
{ "add_target" T ctrl 0 0 }
//- rjf: attaching
{ "attach" F6 0 shift 0 }
//- rjf: filtering
{ "filter" Slash ctrl 0 0 }
//- rjf: command lister
{ "run_command" F1 0 0 0 }
//- rjf: developer commands
{ "log_marker" M ctrl shift alt }
}
@data(DF_StringBindingPair) df_g_default_binding_table:
{
@expand(DF_DefaultBindingTable a) ```{str8_lit_comp("$(a.name)"), {OS_Key_$(a.key), 0 $(a.ctrl != 0 -> `|OS_EventFlag_Ctrl`) $(a.shift != 0 -> `|OS_EventFlag_Shift`) $(a.alt != 0 -> `|OS_EventFlag_Alt`)}}```;
}
////////////////////////////////
//~ rjf: Binding Version Remap Table
@table(old_name new_name)
DF_BindingVersionRemapTable:
{
{"commands" "run_command"}
{"load_user" "open_user"}
{"load_profile" "open_profile"}
{"load_project" "open_project"}
{"open_profile" "open_project"}
}
@data(String8) df_g_binding_version_remap_old_name_table:
{
@expand(DF_BindingVersionRemapTable a) `str8_lit_comp("$(a.old_name)")`
}
@data(String8) df_g_binding_version_remap_new_name_table:
{
@expand(DF_BindingVersionRemapTable a) `str8_lit_comp("$(a.new_name)")`
}
////////////////////////////////
//~ rjf: Gfx Layer View Kinds
@table(name, name_lower, display_string, name_kind, icon, parameterized_by_entity, project_specific, can_serialize, can_serialize_entity_path, can_filter, filter_is_code, typing_automatically_filters, inc_in_docs, docs_desc)
DF_GfxViewTable:
{
{ Null "null" "" Null Null 0 0 0 0 0 0 0 0 "" }
{ Empty "empty" "" Null Null 0 0 0 0 0 0 0 0 "" }
{ GettingStarted "getting_started" "Getting Started" Null QuestionMark 0 0 1 0 0 0 0 0 "" }
{ Commands "commands" "Commands" Null List 0 0 0 0 0 0 0 0 "" }
{ FileSystem "file_system" "File System" Null FileOutline 0 0 0 0 0 0 0 0 "" }
{ SystemProcesses "system_processes" "System Processes" Null Null 0 0 0 0 0 0 0 0 "" }
{ EntityLister "entity_lister" "Entity List" Null Null 0 0 0 0 0 0 0 0 "" }
{ SymbolLister "symbol_lister" "Symbols" Null Null 0 0 0 0 0 0 0 0 "" }
{ Target "target" "Target" EntityName Target 1 0 0 0 0 0 0 0 "" }
{ Targets "targets" "Targets" Null Target 0 0 1 0 1 0 1 1 "Displays a list of all targets, as well as controls for enabling, disabling, launching, editing, or deleting each target. For more information on targets, read the `Targets` section." }
{ FilePathMap "file_path_map" "File Path Map" Null FileOutline 0 0 1 0 0 0 0 1 "Displays a table of *path maps*. Each path map is a pair of file or folder paths, one being a 'source' path, and one being a 'destination' path. These pairs are used by the debugger when automatically searching for specific files - for instance, when attempting to snap to a source code location specified by debug info. If debug info refers to a path on the machine on which a target executable was originally built, but that path is not valid on the debugger machine, but some alternative path exists, then path maps may be used to redirect the debugger from the debug info's specified paths to the associated appropriate debugger machine file paths." }
{ AutoViewRules "auto_view_rules" "Auto View Rules" Null Binoculars 0 0 1 0 0 0 0 1 "Displays a table of *auto view rules*. Each *auto view rule* is a pair, with one element being a type, and the other being a view rule, which should be automatically applied to expressions of that type, when possible." }
{ Scheduler "scheduler" "Scheduler" Null Scheduler 0 0 1 0 1 1 1 1 "Displays all processes and threads to which the debugger is currently attached, and contains controls for selecting and freezing threads." }
{ CallStack "call_stack" "Call Stack" Null Thread 0 0 1 0 0 0 0 1 "Displays the call stack of the currently selected thread. Each frame in the call stack contains the associated module, function name, and return address. Allows selection of a particular call stack frame other than the top." }
{ Modules "modules" "Modules" Null Module 0 0 1 0 1 0 1 1 "Displays a table of all modules currently loaded by any process to which the debugger is attached. This table displays each module's name, virtual address range in the containing process' address space, and which debug info file is being used by the debugger for the associated module." }
{ PendingEntity "pending_entity" "Pending Entity" EntityName FileOutline 1 0 0 0 0 0 0 0 "" }
{ Code "code" "Code" EntityName FileOutline 1 1 1 1 0 0 0 0 "" }
{ Disassembly "disassembly" "Disassembly" Null Glasses 0 0 1 0 0 0 0 1 "Displays disassembled instructions in a textual form from the selected thread's containing process virtual address space." }
{ Watch "watch" "Watch" Null Binoculars 0 0 1 0 1 1 1 1 "The familiar 'watch window' debugger interface. Allows the inputting of a number of expressions. Each expression in the table is evaluated within the context of the selected thread's selected call stack frame. If applicable (depending on visualization rules and the expression's type), these expressions may be hierarchically expanded, which displays children as more rows in the table. The values of these expressions may also be edited, and if possible, can be used to write to registers or memory in attached processes. Also contains a new *view rule* column, not found in other major debuggers, which allows per-row specification of various visualization rules. These view rules may be used to visualize and inspect the evaluation of expressions in a variety of ways. To learn more, read the 'View Rules' section." }
{ Locals "locals" "Locals" Null Binoculars 0 0 1 0 1 1 1 1 "Nearly identical to `Watch`, but automatically filled with local variables found within the selected call stack frame of the selected thread, according to the associated debug info. View rules and evaluation values can be edited, like in `Watch`, but unlike `Watch`, expressions cannot be edited or added to the table." }
{ Registers "registers" "Registers" Null Binoculars 0 0 1 0 1 1 1 1 "Nearly identical to `Watch`, but automatically filled with all register names according to the selected thread's architecture. View rules and evaluation values can be edited, like in `Watch`, but unlike `Watch`, expressions cannot be edited or added to the table." }
{ Globals "globals" "Globals" Null Binoculars 0 0 1 0 1 1 1 1 "Nearly identical to `Watch`, but automatically filled with all global variables within the selected thread's module. View rules and evaluation values can be edited, like in `Watch`, but unlike `Watch`, expressions cannot be edited or added to the table." }
{ ThreadLocals "thread_locals" "Thread Locals" Null Binoculars 0 0 1 0 1 1 1 1 "Nearly identical to `Watch`, but automatically filled with all thread local variables within the selected thread's module. View rules and evaluation values can be edited, like in `Watch`, but unlike `Watch`, expressions cannot be edited or added to the table." }
{ Types "types" "Types" Null Binoculars 0 0 1 0 1 1 1 1 "Nearly identical to `Watch`, but automatically filled with all types within the selected thread's module. View rules can be edited, like in `Watch`, but unlike `Watch`, expressions cannot be edited or added to the table." }
{ Procedures "procedures" "Procedures" Null Binoculars 0 0 1 0 1 1 1 1 "Nearly identical to `Watch`, but automatically filled with all procedures within the selected thread's module. View rules can be edited, like in `Watch`, but unlike `Watch`, expressions cannot be edited or added to the table." }
{ Output "output" "Output" Null List 0 0 1 0 0 0 0 1 "Displays textual output from the selected thread's containing process." }
{ Memory "memory" "Memory" Null Grid 0 0 1 0 0 0 0 1 "A familiar hex-editor-like interface for viewing memory of attached processes." }
{ Breakpoints "breakpoints" "Breakpoints" Null CircleFilled 0 0 1 0 1 0 1 1 "Displays a table of all breakpoints, containing information about each breakpoint's name, location, and hit count. Also contains per-breakpoint controls for enabling, deleting, or editing each breakpoint. For more information on breakpoints and their features, read the 'Breakpoints' section." }
{ WatchPins "watch_pins" "Watch Pins" Null Pin 0 0 1 0 1 1 1 1 "Displays a table of all watch pins (watched expressions, like those found in `Watch`, but instead of being within a table, being pinned to some source code location, like breakpoints). This table contains each pin's name, location, and controls for editing or deleting each pin." }
{ ExceptionFilters "exception_filters" "Exception Filters" Null Gear 0 0 1 0 1 0 1 1 "An interface which controls whether or not the debugger will halt attached processes upon encountering specific exception codes for the first time." }
{ Settings "settings" "Settings" Null Gear 0 0 1 0 1 0 1 1 "An interface to modify general settings for the debugger's appearance and behavior." }
}
@enum DF_GfxViewKind:
{
@expand(DF_GfxViewTable a) `$(a.name)`,
COUNT,
}
@gen
{
@expand(DF_GfxViewTable a) `DF_VIEW_SETUP_FUNCTION_DEF($(a.name));`;
@expand(DF_GfxViewTable a) `DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF($(a.name));`;
@expand(DF_GfxViewTable a) `DF_VIEW_CMD_FUNCTION_DEF($(a.name));`;
@expand(DF_GfxViewTable a) `DF_VIEW_UI_FUNCTION_DEF($(a.name));`;
}
@data(DF_ViewSpecInfo) df_g_gfx_view_kind_spec_info_table:
{
@expand(DF_GfxViewTable a) ```{(0|$(a.parameterized_by_entity)*DF_ViewSpecFlag_ParameterizedByEntity|$(a.project_specific)*DF_ViewSpecFlag_ProjectSpecific|$(a.can_serialize)*DF_ViewSpecFlag_CanSerialize|$(a.can_serialize_entity_path)*DF_ViewSpecFlag_CanSerializeEntityPath|$(a.can_filter)*DF_ViewSpecFlag_CanFilter|$(a.filter_is_code)*DF_ViewSpecFlag_FilterIsCode|$(a.typing_automatically_filters)*DF_ViewSpecFlag_TypingAutomaticallyFilters), str8_lit_comp("$(a.name_lower)"), str8_lit_comp("$(a.display_string)"), DF_NameKind_$(a.name_kind), DF_IconKind_$(a.icon), DF_VIEW_SETUP_FUNCTION_NAME($(a.name)), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME($(a.name)), DF_VIEW_CMD_FUNCTION_NAME($(a.name)), DF_VIEW_UI_FUNCTION_NAME($(a.name))}```;
}
////////////////////////////////
//~ rjf: Command Parameter Slot -> View
@table(slot view_spec opt_cmd_spec)
DF_CmdParamSlot2ViewSpecMap:
{
{Entity "entity_lister" "" }
{EntityList "entity_lister" "" }
{FilePath "file_system" "" }
{CmdSpec "commands" "" }
{ID "system_processes" "" }
{String "symbol_lister" "goto_name" }
{String "symbol_lister" "function_breakpoint" }
}
@data(DF_CmdParamSlot) df_g_cmd_param_slot_2_view_spec_src_map:
{
@expand(DF_CmdParamSlot2ViewSpecMap a) `DF_CmdParamSlot_$(a.slot)`
}
@data(String8) df_g_cmd_param_slot_2_view_spec_dst_map:
{
@expand(DF_CmdParamSlot2ViewSpecMap a) `str8_lit_comp("$(a.view_spec)")`
}
@data(String8) df_g_cmd_param_slot_2_view_spec_cmd_map:
{
@expand(DF_CmdParamSlot2ViewSpecMap a) `str8_lit_comp("$(a.opt_cmd_spec)")`
}
////////////////////////////////
//~ rjf: Built-In Graphical View Rule Extensions
//
// NOTE(rjf): see @view_rule_info
@table(string vr ls ru bu tu tab_display_string)
DF_GfxViewRuleTable:
{
{"array" - - - - - "" }
{"slice" - - - - - "" }
{"list" x - - - - "" }
{"dec" - x - - - "" }
{"bin" - x - - - "" }
{"oct" - x - - - "" }
{"hex" - x - - - "" }
{"only" x x - - - "" }
{"omit" x x - - - "" }
{"no_addr" - x - - - "" }
{"rgba" - - x x - "" }
{"text" - - - x x "Text" }
{"disasm" - - - x x "Disassembly" }
{"bitmap" - - x x x "Bitmap" }
{"odin_map" - - x x x "Odin HashMap" }
{"geo" - - x x x "Geometry" }
}
@gen
{
``;
@expand(DF_GfxViewRuleTable a)
`$(a.vr == "x" -> "DF_GFX_VIEW_RULE_VIZ_ROW_PROD_FUNCTION_DEF(" .. a.name_lower .. ");")`;
@expand(DF_GfxViewRuleTable a)
`$(a.ls == "x" -> "DF_GFX_VIEW_RULE_LINE_STRINGIZE_FUNCTION_DEF(" .. a.name_lower .. ");")`;
@expand(DF_GfxViewRuleTable a)
`$(a.ru == "x" -> "DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_DEF(" .. a.name_lower .. ");")`;
@expand(DF_GfxViewRuleTable a)
`$(a.bu == "x" -> "DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(" .. a.name_lower .. ");")`;
@expand(DF_GfxViewRuleTable a)
`$(a.tu == "x" -> "DF_VIEW_SETUP_FUNCTION_DEF(" .. a.name_lower .. ");")`;
@expand(DF_GfxViewRuleTable a)
`$(a.tu == "x" -> "DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(" .. a.name_lower .. ");")`;
@expand(DF_GfxViewRuleTable a)
`$(a.tu == "x" -> "DF_VIEW_CMD_FUNCTION_DEF(" .. a.name_lower .. ");")`;
@expand(DF_GfxViewRuleTable a)
`$(a.tu == "x" -> "DF_VIEW_UI_FUNCTION_DEF(" .. a.name_lower .. ");")`;
}
@data(DF_ViewSpecInfo) @c_file df_g_gfx_view_rule_tab_view_spec_info_table:
{
@expand(DF_GfxViewRuleTable a)
```$(a.tu == "x" -> '{ DF_ViewSpecFlag_CanSerialize|DF_ViewSpecFlag_CanSerializeQuery, str8_lit_comp("' .. a.string .. '_view_rule"), str8_lit_comp("' .. a.tab_display_string .. '"), DF_NameKind_Null, DF_IconKind_Binoculars, ' .. 'DF_VIEW_SETUP_FUNCTION_NAME(' .. a.string .. '), DF_VIEW_STRING_FROM_STATE_FUNCTION_NAME(' .. a.string .. '), DF_VIEW_CMD_FUNCTION_NAME(' .. a.string .. '), DF_VIEW_UI_FUNCTION_NAME(' .. a.string .. ') }')```;
}
@data(DF_GfxViewRuleSpecInfo) @c_file df_g_gfx_view_rule_spec_info_table:
{
@expand(DF_GfxViewRuleTable a)
```{ str8_lit_comp("$(a.string)"), (DF_GfxViewRuleSpecInfoFlag_VizRowProd*$(a.vr == "x"))|(DF_GfxViewRuleSpecInfoFlag_LineStringize*$(a.ls == "x"))|(DF_GfxViewRuleSpecInfoFlag_RowUI*$(a.ru == "x"))|(DF_GfxViewRuleSpecInfoFlag_BlockUI*$(a.bu == "x")), $(a.vr == "x" -> "DF_GFX_VIEW_RULE_VIZ_ROW_PROD_FUNCTION_NAME("..a.name_lower..")") $(a.vr != "x" -> 0), $(a.ls == "x" -> "DF_GFX_VIEW_RULE_LINE_STRINGIZE_FUNCTION_NAME("..a.name_lower..")") $(a.ls != "x" -> 0), $(a.ru == "x" -> "DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_NAME("..a.name_lower..")") $(a.ru != "x" -> 0), $(a.bu == "x" -> "DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_NAME("..a.name_lower..")") $(a.bu != "x" -> 0), str8_lit_comp("$(a.tu == 'x' -> a.string..'_view_rule')") }```;
}
////////////////////////////////
//~ rjf: Theme Tables
@table(name_upper name_lower display_string)
DF_ThemePresetTable:
{
{ DefaultDark default_dark "Default (Dark)" }
{ DefaultLight default_light "Default (Light)" }
{ VSDark vs_dark "VS (Dark)" }
{ VSLight vs_light "VS (Light)" }
{ SolarizedDark solarized_dark "Solarized (Dark)" }
{ SolarizedLight solarized_light "Solarized (Light)" }
{ HandmadeHero handmade_hero "Handmade Hero" }
{ FourCoder four_coder "4coder" }
{ FarManager far_manager "Far Manager" }
}
@table(name display_name name_lower default_dark default_light vs_dark vs_light solarized_dark solarized_light handmade_hero four_coder far_manager desc)
DF_ThemeColorTable:
{
{Null "Null" null 0xff00ffff 0xff00ffff 0xff00ffff 0xff00ffff 0xff00ffff 0xff00ffff 0xff00ffff 0xff00ffff 0xff00ffff ""}
//- rjf: global ui colors
{Text "Text" text 0xe5e5e5ff 0x4c4c4cff 0xe5e5e5ff 0x000000ff 0x999999ff 0x333333ff 0xa08462ff 0x90b080ff 0x00fefeff ""}
{TextPositive "Text (Positive)" text_positive 0x4dc221ff 0x4d9e2eff 0x4dc221ff 0x4dc221ff 0x4dc221ff 0x4dc221ff 0x4dc221ff 0x4dc221ff 0x4dc221ff ""}
{TextNegative "Text (Negative)" text_negative 0xc56452ff 0xbd371eff 0xc56452ff 0xc46451ff 0xc56452ff 0xc56452ff 0xc56452ff 0xc56452ff 0xc56452ff ""}
{TextNeutral "Text (Neutral)" text_neutral 0x307eb2ff 0x0064a7ff 0x307eb2ff 0x307eb2ff 0x307eb2ff 0x307eb2ff 0x307eb2ff 0x307eb2ff 0x307eb2ff ""}
{TextWeak "Text (Weak)" text_weak 0xa4a4a4fe 0x4c4c4cff 0xa4a4a4fe 0x0000007f 0x9999998a 0x818181ff 0x6e512eff 0x566e4bff 0x00a9a9ff ""}
{Cursor "Cursor" cursor 0x8aff00ff 0x699830ff 0x8aff00ff 0x000000ff 0x8aff00ff 0x586e75ff 0x8aff00ff 0x8aff00ff 0x8aff00ff ""}
{CursorInactive "Cursor (Inactive)" cursor_inactive 0xb23217ff 0xb23217ff 0xb23217ff 0xb23217ff 0xb23217ff 0xb23217ff 0xb23217ff 0xb23217ff 0xb23217ff ""}
{Focus "Focus" focus 0xfda200ff 0x9c5900ff 0xfda200ff 0x002affff 0xfda200ff 0x92743dff 0xfda200ff 0xfda200ff 0x00fefeff ""}
{Hover "Hover" hover 0xffffffff 0xffffffff 0xffffffff 0x000000ff 0xffffffff 0x747474ff 0xffffffff 0xffffffff 0xffffffff ""}
{DropShadow "Drop Shadow" drop_shadow 0x0000007f 0x0000004c 0x0000007f 0xa3a3a37e 0x0000007f 0xc9bfa394 0x0000007f 0x0000007f 0x0000007f ""}
{DisabledOverlay "Disabled Overlay" disabled_overlay 0x0000003f 0xa6a6a63f 0x0000003f 0x0000003f 0x0000003f 0xe4dac090 0x0000003f 0x0000003f 0x0000003f ""}
{DropSiteOverlay "Drop Site Overlay" drop_site_overlay 0xffffff0c 0x4848480c 0xffffff0c 0x0000000c 0xffffff0c 0xffffff0c 0xffffff0c 0xffffff0c 0xffffff0c ""}
{InactivePanelOverlay "Inactive Panel Overlay" inactive_panel_overlay 0x0000003f 0xa4a4a43f 0x0000003f 0xfefefe53 0x0000003f 0x0000001c 0x0000003f 0x0000003f 0x0000003f ""}
{SelectionOverlay "Selection Overlay" selection_overlay 0x99ccff4c 0x003d7a48 0x99ccff4c 0x3d74ab4b 0x99ccff4c 0x678cb24c 0x99ccff4c 0x99ccff4c 0x99ccff4c ""}
{HighlightOverlay "Highlight Overlay" highlight_overlay 0xffffff1e 0xffffff1e 0xffffff1e 0x0000001e 0xffffff1e 0xffffff1e 0xffffff1e 0xffffff1e 0xffffff1e ""}
{HighlightOverlayError "Error Highlight Overlay" error_highlight_overlay 0x5f12005f 0xff30005f 0x5f12005f 0x5f12005f 0x5f12005f 0x5f12005f 0x5f12005f 0x5f12005f 0x5f12005f ""}
//- rjf: base ui container colors
{BaseBackground "Base Background" base_background 0x1b1b1bfe 0xccccccfe 0x1b1b1bfe 0xfefefefe 0x002a35fe 0xfcf5e2fe 0x0c0c0cfe 0x0c0c0cfe 0x000081fe ""}
{BaseBackgroundAlt "Base Background (Alternate)" base_background_alt 0x2b2b2bfe 0x2b2b2bfe 0x1b1b1bfe 0xe7e7e7fe 0x2b2b2bfe 0x2b2b2bfe 0x2b2b2bfe 0x2b2b2bfe 0x2b2b2bfe ""}
{BaseBorder "Base Border" base_border 0x3f3f3ffe 0xa4a4a4fe 0x3f3f3ffe 0xb6b6b6ff 0xfefefe3a 0xbebaabfe 0x423525fe 0x3f3f3ffe 0x0000fffe ""}
//- rjf: menu bar ui container colors
{MenuBarBackground "Menu Bar Background" menu_bar_background 0x3e4c577f 0xeaeaea7f 0x1b1b1bfd 0xffffff7f 0x00202bff 0xeee8d5ff 0x0c0c0cfe 0x0c0c0cfe 0x007d7dff ""}
{MenuBarBackgroundAlt "Menu Bar Background (Alternate)" menu_bar_background_alt 0x3e4c577f 0x3e4c577f 0x1b1b1bfd 0xffffff7f 0x3e4c577f 0x3e4c577f 0x3e4c577f 0x3e4c577f 0x007d7dff ""}
{MenuBarBorder "Menu Bar Border" menu_bar_border 0xffffff19 0xa4a4a4fe 0x3f3f3ffe 0xb6b6b6ff 0xffffff19 0xbebaabfe 0xffffff19 0xffffff19 0xfefefe00 ""}
//- rjf: floating ui container colors
{FloatingBackground "Floating Background" floating_background 0x33333333 0xccccccc0 0x33333333 0xfefefec7 0x007fa14e 0xffffff7c 0x0c0c0c32 0x0c0c0c3e 0x007c7c55 ""}
{FloatingBackgroundAlt "Floating Background (Alternate)" floating_background_alt 0x33333333 0x33333333 0x33333333 0x33333333 0x33333333 0x33333333 0x33333333 0x33333333 0x33333333 ""}
{FloatingBorder "Floating Border" floating_border 0x3f3f3ffd 0xa4a4a4fe 0x3f3f3ffd 0xb6b6b6ff 0xfdfdfd3a 0xbebaabfe 0x423425fe 0x3f3f3ffd 0x00ffff55 ""}
//- rjf: ui element colors
{ImplicitButtonBackground "Implicit Button Background" implicit_button_background 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 ""}
{ImplicitButtonBorder "Implicit Button Border" implicit_button_border 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0xbdb9aa00 0x00000000 0x00000000 0x00000000 ""}
{PlainButtonBackground "Plain Button Background" plain_button_background 0x1b1b1bfe 0x1b1b1bfe 0x1b1b1bfe 0x1b1b1bfe 0x1b1b1bfe 0x1b1b1bfe 0x1b1b1bfe 0x1b1b1bfe 0x1b1b1bfe ""}
{PlainButtonBorder "Plain Button Border" plain_button_border 0x3f3f3ffe 0x3f3f3ffe 0x3f3f3ffe 0xb6b6b6ff 0xfefefe3a 0xbebaabfe 0x3f3f3ffe 0x3f3f3ffe 0x3f3f3ffe ""}
{PositivePopButtonBackground "Positive Pop Button Background" positive_pop_button_background 0x2c5b36ff 0x65f534ff 0x2c5b36ff 0x84ce93ff 0x2c5b36ff 0xb6ddbeff 0x132e19ff 0x152f1bff 0x2c5b36ff ""}
{PositivePopButtonBorder "Positive Pop Button Border" positive_pop_button_border 0x3f3f3ffd 0x3f3f3ffd 0x3f3f3ffd 0xb6b6b6ff 0xfefefe3a 0xbebaabfe 0x3f3f3ffd 0x3f3f3ffd 0x3f3f3ffd ""}
{NegativePopButtonBackground "Negative Pop Button Background" negative_pop_button_background 0x803425ff 0xff694cff 0x803425ff 0xbd3e24ff 0x803425ff 0xf8b0a1ff 0x803425ff 0x43150cff 0x803425ff ""}
{NegativePopButtonBorder "Negative Pop Button Border" negative_pop_button_border 0x3f3f3ffd 0x3f3f3ffd 0x3f3f3ffd 0xb6b6b6ff 0xfefefe3a 0xbebaabfe 0x3f3f3ffd 0x3f3f3ffd 0x3f3f3ffd ""}
{NeutralPopButtonBackground "Neutral Pop Button Background" neutral_pop_button_background 0x355b6eff 0xa6becaff 0x355b6eff 0x6e9db5ff 0x355b6eff 0xb2d3e3ff 0x15445cff 0x1b323eff 0x933100ff ""}
{NeutralPopButtonBorder "Neutral Pop Button Border" neutral_pop_button_border 0x3f3f3ffd 0xa6a6a6fd 0x3f3f3ffd 0xb6b6b6ff 0xfefefe3a 0xbebaabfe 0x3f3f3ffd 0x3f3f3ffd 0x3f3f3ffd ""}
{ScrollBarButtonBackground "Scroll Bar Button Background" scroll_bar_button_background 0x2b2b2bfe 0xa9a9a9fe 0x2b2b2bfe 0xe8e8e8fe 0x005e77fe 0xe3dbc7fe 0x1f1f27fe 0x212721fe 0x007d7dff ""}
{ScrollBarButtonBorder "Scroll Bar Button Border" scroll_bar_button_border 0x3f3f3ffe 0xc0c0c0fe 0x3f3f3ffe 0xb6b6b6ff 0xfefefe3a 0xbebaabfe 0xfefefe4d 0x3f3f3ffe 0x3f3f3ffe ""}
{TabBackground "Tab Background" tab_background 0x6f5135fe 0xa98b6fff 0x0079ccff 0xfffffffe 0x005e77fe 0xfdf6e3ff 0x1f1f27fe 0x212721fe 0x007d7dff ""}
{TabBorder "Tab Border" tab_border 0xfefefe4d 0xffffff4d 0xfefefe4d 0xb6b6b6ff 0xfefefe4d 0xbebaabfe 0xfefefe4d 0xfefefe4d 0xfefefe4d ""}
{TabBackgroundInactive "Tab Background (Inactive)" tab_background_inactive 0x3e4c577f 0x8282827f 0xfefefe14 0xcdd4dc7f 0x3e4c577f 0xd4cfc0fe 0x131315ee 0x3a3a3a7f 0x3e4c577f ""}
{TabBorderInactive "Tab Border (Inactive)" tab_border_inactive 0xffffff19 0xffffff19 0xffffff00 0xb6b6b6ff 0xffffff19 0xbebaabfe 0xffffff19 0x00000019 0xfefefe19 ""}
//- rjf: code colors
{CodeDefault "Code (Default)" code_default 0xcbcbcbff 0x4d4d4dff 0xcbcbcbff 0x000000ff 0xcbcbcbff 0x657b83ff 0xa08462ff 0x90b080ff 0x00fefeff ""}
{CodeSymbol "Code (Symbol)" code_symbol 0x42a2cffe 0x205670fe 0xdcdcaaff 0x000000ff 0xcb4a15ff 0xcb4a15ff 0xcc5634ff 0x42a2cffe 0x65b1ffff ""}
{CodeType "Code (Type)" code_type 0xfec746ff 0x996b00ff 0x4ec9afff 0xa33700ff 0xcb4a15ff 0xcb4a15ff 0xd8a51bff 0xfd7c52ff 0xfec746ff ""}
{CodeLocal "Code (Local)" code_local 0x98bc80ff 0x446a2bff 0x9cdbfeff 0x007666ff 0x98bc80ff 0x258ad2ff 0xc04047ff 0x98bc80ff 0x00ff00ff ""}
{CodeRegister "Code (Register)" code_register 0xb7afd5ff 0x4c35a1ff 0xb7afd5ff 0xb7afd5ff 0xb7afd5ff 0x373345ff 0xb7afd5ff 0xb7afd5ff 0xb7afd5ff ""}
{CodeKeyword "Code (Keyword)" code_keyword 0xb38d4cff 0x573700ff 0x569cd6ff 0x0000ffff 0x849803ff 0x586e75ff 0xac7a09ff 0xd08f1eff 0x00ffffff ""}
{CodeDelimiterOperator "Code (Delimiters/Operators)" code_delimiter_operator 0x767676ff 0x767676ff 0x767676ff 0x767676ff 0x767676ff 0x767676ff 0xa08462ff 0x90b080ff 0xffffffff ""}
{CodeNumeric "Code (Numeric)" code_numeric 0x98abb1ff 0x3f6e7dff 0xb5cea8ff 0x088658ff 0xd33582ff 0xd33482ef 0x698e21ff 0x4fff2eff 0x00ff00ff ""}
{CodeNumericAltDigitGroup "Code (Numeric, Alt. Digit Group)" code_numeric_alt_digit_group 0x738287ff 0x1f4450ff 0x729360ff 0x0c3828ff 0x902559ff 0x8e2659ff 0x3a4e11ff 0x3ccd21ff 0x738287ff ""}
{CodeString "Code (String)" code_string 0x98abb1ff 0x3c606bff 0xd59b85ff 0xa31414ff 0x1f9d91ff 0x29a198ff 0x6a8e22ff 0x4fff2eff 0x98abb1ff ""}
{CodeMeta "Code (Meta)" code_meta 0xd96759ff 0xad3627ff 0xd59c85ff 0x0000ffff 0x839802ff 0xd96759ff 0xdab98fff 0xa0b8a0ff 0xff0000ff ""}
{CodeComment "Code (Comment)" code_comment 0x717171ff 0x4b4b4bff 0x57a54aff 0x008000ff 0x556a6fff 0x93a1a1ff 0x686868ff 0x1e8fefff 0xffffffff ""}
{CodeLineNumbers "Code Line Numbers" code_line_numbers 0x7f7f7fff 0x4b4b4bff 0x2a91afff 0x227893ff 0x566c73ff 0x227893ef 0xa08462ff 0x7e7e7ffe 0x007d7dff ""}
{CodeLineNumbersSelected "Code Line Numbers (Selected)" code_line_numbers_selected 0xbebebeff 0x000000ff 0x9ddaecff 0x123d4bfe 0xa2aaacff 0x111e22ef 0xc8b399ff 0xbebebeff 0x00fefeff ""}
//- rjf: debugging colors
{LineInfoBackground0 "Line Info Background 0" line_info_background_0 0x99503d3f 0x99503d3f 0x99503d3f 0x99503d3f 0x99503d3f 0x99503d3f 0x99503d3f 0x99503d3f 0x99503d3f ""}
{LineInfoBackground1 "Line Info Background 1" line_info_background_1 0xfe82493f 0xfe82493f 0xfe82493f 0xfe82493f 0xfe82493f 0xfe82493f 0xfe82493f 0xfe82493f 0xfe82493f ""}
{LineInfoBackground2 "Line Info Background 2" line_info_background_2 0xffba173f 0xffba173f 0xffba173f 0xffba173f 0xffba173f 0xffba173f 0xffba173f 0xffba173f 0xffba173f ""}
{LineInfoBackground3 "Line Info Background 3" line_info_background_3 0xcefd693f 0xcefd693f 0xcefd693f 0xcefd693f 0xcefd693f 0xcefd693f 0xcefd693f 0xcefd693f 0xcefd693f ""}
{LineInfoBackground4 "Line Info Background 4" line_info_background_4 0x99503d3f 0x99503d3f 0x99503d3f 0x99503d3f 0x99503d3f 0x99503d3f 0x99503d3f 0x99503d3f 0x99503d3f ""}
{LineInfoBackground5 "Line Info Background 5" line_info_background_5 0xfe82493f 0xfe82493f 0xfe82493f 0xfe82493f 0xfe82493f 0xfe82493f 0xfe82493f 0xfe82493f 0xfe82493f ""}
{LineInfoBackground6 "Line Info Background 6" line_info_background_6 0xffba173f 0xffba173f 0xffba173f 0xffba173f 0xffba173f 0xffba173f 0xffba173f 0xffba173f 0xffba173f ""}
{LineInfoBackground7 "Line Info Background 7" line_info_background_7 0xcefd693f 0xcefd693f 0xcefd693f 0xcefd693f 0xcefd693f 0xcefd693f 0xcefd693f 0xcefd693f 0xcefd693f ""}
{Thread0 "Thread 0" thread_0 0xffcb7fff 0x945800ff 0xffcb7fff 0x945800ff 0xffcb7fff 0x945800ff 0xffcb7fff 0xffcb7fff 0xffcb7fff ""}
{Thread1 "Thread 1" thread_1 0xb2ff65ff 0x3f5b23ff 0xb2ff65ff 0x3f5b23ff 0xb2ff65ff 0x3f5b23ff 0xb2ff65ff 0xb2ff65ff 0xb2ff65ff ""}
{Thread2 "Thread 2" thread_2 0xff99e5ff 0x642a55ff 0xff99e5ff 0x642a55ff 0xff99e5ff 0x642a55ff 0xff99e5ff 0xff99e5ff 0xff99e5ff ""}
{Thread3 "Thread 3" thread_3 0x6598ffff 0x30456fff 0x6598ffff 0x30456fff 0x6598ffff 0x30456fff 0x6598ffff 0x6598ffff 0x6598ffff ""}
{Thread4 "Thread 4" thread_4 0x65ffcbff 0x264f41ff 0x65ffcbff 0x264f41ff 0x65ffcbff 0x264f41ff 0x65ffcbff 0x65ffcbff 0x65ffcbff ""}
{Thread5 "Thread 5" thread_5 0xff9819ff 0x736a5fff 0xff9819ff 0x736a5fff 0xff9819ff 0x736a5fff 0xff9819ff 0xff9819ff 0xff9819ff ""}
{Thread6 "Thread 6" thread_6 0x9932ffff 0x472f5eff 0x9932ffff 0x472f5eff 0x9932ffff 0x472f5eff 0x9932ffff 0x9932ffff 0x9932ffff ""}
{Thread7 "Thread 7" thread_7 0x65ff4cff 0x405d3bff 0x65ff4cff 0x405d3bff 0x65ff4cff 0x405d3bff 0x65ff4cff 0x65ff4cff 0x65ff4cff ""}
{ThreadUnwound "Thread (Unwound)" thread_unwound 0xb2ccd8ff 0x49606aff 0xb2ccd8ff 0x49606aff 0xb2ccd8ff 0x49606aff 0xb2ccd8ff 0xb2ccd8ff 0xb2ccd8ff ""}
{ThreadError "Thread (Error)" thread_error 0xb23219ff 0xb23219ff 0xb23219ff 0xb23219ff 0xb23219ff 0xb23218ff 0xb23219ff 0xb23219ff 0xb23219ff ""}
{Breakpoint "Breakpoint" breakpoint 0xa72911ff 0xff2800ff 0xa72911ff 0xa72911ff 0xa72911ff 0xff684bff 0xa72911ff 0xa72911ff 0xff2800ff ""}
}
@table(old_name new_name)
DF_ThemeColorVersionRemapTable:
{
{plain_text text}
{plain_background base_background}
{plain_border base_border}
{plain_overlay drop_site_overlay}
{code_function code_symbol}
{code_symbol code_delimiter_operator}
{code_numeric code_numeric_alt_digit_group}
{line_info_0 line_info_background_0}
{line_info_1 line_info_background_1}
{line_info_2 line_info_background_2}
{line_info_3 line_info_background_3}
{alt_background menu_bar_background}
{alt_border menu_bar_border}
{tab_inactive tab_background_inactive}
{tab_active tab_background}
{weak_text text_weak}
{text_selection selection}
{cursor cursor}
{highlight_0 focus}
{success_background positive_pop_button_background}
{failure_background negative_pop_button_background}
{action_background neutral_pop_button_background}
}
@enum DF_ThemeColor:
{
@expand(DF_ThemeColorTable a) `$(a.name)`,
COUNT,
}
@enum DF_ThemePreset:
{
@expand(DF_ThemePresetTable a) `$(a.name)`,
COUNT,
}
@data(String8) df_g_theme_preset_display_string_table:
{
@expand(DF_ThemePresetTable a) `str8_lit_comp("$(a.display_string)")`,
}
@data(String8) df_g_theme_preset_code_string_table:
{
@expand(DF_ThemePresetTable a) `str8_lit_comp("$(a.name_lower)")`,
}
@data(String8) df_g_theme_color_version_remap_old_name_table:
{
@expand(DF_ThemeColorVersionRemapTable a) `str8_lit_comp("$(a.old_name)")`
}
@data(String8) df_g_theme_color_version_remap_new_name_table:
{
@expand(DF_ThemeColorVersionRemapTable a) `str8_lit_comp("$(a.new_name)")`
}
@data(Vec4F32) df_g_theme_preset_colors__default_dark: {@expand(DF_ThemeColorTable a) `rgba_from_u32_lit_comp($(a.default_dark))`}
@data(Vec4F32) df_g_theme_preset_colors__default_light: {@expand(DF_ThemeColorTable a) `rgba_from_u32_lit_comp($(a.default_light))`}
@data(Vec4F32) df_g_theme_preset_colors__vs_dark: {@expand(DF_ThemeColorTable a) `rgba_from_u32_lit_comp($(a.vs_dark))`}
@data(Vec4F32) df_g_theme_preset_colors__vs_light: {@expand(DF_ThemeColorTable a) `rgba_from_u32_lit_comp($(a.vs_light))`}
@data(Vec4F32) df_g_theme_preset_colors__solarized_dark: {@expand(DF_ThemeColorTable a) `rgba_from_u32_lit_comp($(a.solarized_dark))`,}
@data(Vec4F32) df_g_theme_preset_colors__solarized_light:{@expand(DF_ThemeColorTable a) `rgba_from_u32_lit_comp($(a.solarized_light))`,}
@data(Vec4F32) df_g_theme_preset_colors__handmade_hero: {@expand(DF_ThemeColorTable a) `rgba_from_u32_lit_comp($(a.handmade_hero))`,}
@data(Vec4F32) df_g_theme_preset_colors__four_coder: {@expand(DF_ThemeColorTable a) `rgba_from_u32_lit_comp($(a.four_coder))`,}
@data(Vec4F32) df_g_theme_preset_colors__far_manager: {@expand(DF_ThemeColorTable a) `rgba_from_u32_lit_comp($(a.far_manager))`;}
@data(`Vec4F32*`) df_g_theme_preset_colors_table:
{
@expand(DF_ThemePresetTable a) `df_g_theme_preset_colors__$(a.name_lower)`,
}
@data(String8) df_g_theme_color_display_string_table:
{
@expand(DF_ThemeColorTable a) `str8_lit_comp("$(a.display_name)")`
}
@data(String8) df_g_theme_color_cfg_string_table:
{
@expand(DF_ThemeColorTable a) `str8_lit_comp("$(a.name_lower)")`
}
////////////////////////////////
//~ rjf: Settings
@table(name name_lower display_string default_per_window default_s32 s32_min s32_max)
DF_SettingTable:
{
{HoverAnimations hover_animations "Hover Animations" 0 1 0 1 }
{PressAnimations press_animations "Press Animations" 0 1 0 1 }
{FocusAnimations focus_animations "Focus Animations" 0 1 0 1 }
{TooltipAnimations tooltip_animations "Tooltip Animations" 0 1 0 1 }
{MenuAnimations menu_animations "Menu Animations" 0 1 0 1 }
{ScrollingAnimations scrolling_animations "Scrolling Animations" 0 1 0 1 }
{BackgroundBlur background_blur "Background Blur" 0 1 0 1 }
{ThreadLines thread_lines "Thread Lines" 0 1 0 1 }
{BreakpointLines breakpoint_lines "Breakpoint Lines" 0 1 0 1 }
{ThreadGlow thread_glow "Thread Glow" 0 1 0 1 }
{BreakpointGlow breakpoint_glow "Breakpoint Glow" 0 1 0 1 }
{OpaqueBackgrounds opaque_backgrounds "Opaque Backgrounds" 0 0 0 1 }
{TabWidth tab_width "Tab Width" 0 4 1 32 }
{MainFontSize main_font_size "Main Font Size" 1 12 6 72 }
{CodeFontSize code_font_size "Code Font Size" 1 12 6 72 }
{SmoothUIText smooth_ui_text "Smooth UI Text" 1 1 0 1 }
{SmoothCodeText smooth_code_text "Smooth Code Text" 1 0 0 1 }
{HintUIText hint_ui_text "Hint UI Text" 1 1 0 1 }
{HintCodeText hint_code_text "Hint Code Text" 1 1 0 1 }
}
@enum DF_SettingCode:
{
@expand(DF_SettingTable a) `$(a.name)`,
COUNT
}
@data(String8) df_g_setting_code_display_string_table:
{
@expand(DF_SettingTable a) `str8_lit_comp("$(a.display_string)")`
}
@data(String8) df_g_setting_code_lower_string_table:
{
@expand(DF_SettingTable a) `str8_lit_comp("$(a.name_lower)")`
}
@data(B8) df_g_setting_code_default_is_per_window_table:
{
@expand(DF_SettingTable a) `$(a.default_per_window)`
}
@data(DF_SettingVal) df_g_setting_code_default_val_table:
{
@expand(DF_SettingTable a) `{1, $(a.default_s32)}`
}
@data(Rng1S32) df_g_setting_code_s32_range_table:
{
@expand(DF_SettingTable a) `{$(a.s32_min), $(a.s32_max)}`
}
////////////////////////////////
//~ rjf: Help/Docs/README
@markdown
raddbg_readme:
{
@title "The RAD Debugger (ALPHA)";
@p "The RAD Debugger is a native, user-mode, multi-process, graphical debugger. It currently only supports local-machine Windows x64 debugging with PDBs, with plans to expand and port in the future.";
@subtitle "Getting Started";
@p "To launch the RAD Debugger with your executable and command line arguments, run `raddbg` from the command line like so:";
@p "```raddbg my_program.exe --foo --bar --baz```";
@p "For more information, see the 'Command-Line Usage' section.";
@p "Default keyboard shortcuts for common debugger controls include:";
@unordered_list
{
@p "**Ctrl + O**: Open Source Code File";
@p "**F10**: Step Over";
@p "**F11**: Step Into";
@p "**Shift + F11**: Step Out";
@p "**F5**: Run";
@p "**Ctrl + Shift + X**, or **Pause**: Halt All Processes";
@p "**Shift + F5**: Kill All Processes";
@p "**Shift + F6**: Attach To Process";
@p "**Ctrl + F**: Search For Text (Forwards)";
@p "**F9**: Toggle Breakpoint At Cursor";
@p "**Ctrl + Comma**: Focus Next Panel";
@p "**Ctrl + Shift + Comma**: Focus Previous Panel";
@p "**Ctrl + Shift + Alt + Arrow Key**: Focus Panel In Direction";
@p "**Ctrl + Tab**: Focus Next Tab";
@p "**Ctrl + Shift + Tab**: Focus Previous Tab";
@p "**Ctrl + W**: Close Tab";
@p "**F1**: Open Command Palette";
}
@p "For more information, see the 'Commands' section.";
@p "View rules can be used to visualize expressions differently in the watch window. Here are some examples:";
@unordered_list
{
@p "`array:16`: Visualize a pointer as pointing to a 16-element array.";
@p "`array:(count*2)`: Visualize a pointer as pointing to a `count*2`-element array.";
@p "`list:next`: Visualize a linked list flatly, where each node has a `next` pointer, which points to the next node in the list.";
@p "`hex`: Visualize numeric literals as base-16 (hexadecimal).";
@p "`dec`: Visualize numeric literals as base-10 (decimal).";
@p "`oct`: Visualize numeric literals as base-8 (octal).";
@p "`bin`: Visualize numeric literals as base-2 (binary).";
@p "`omit:(foo bar baz)`: Prohibits members named `foo`, `bar`, and `baz` from being displayed.";
@p "`only:(foo bar baz)`: Only allows members named `foo`, `bar`, and `baz` to be displayed.";
}
@p "Multiple view rules can be specified on one line, so they can be combined like so:";
@p "```list:next, hex, omit:next```";
@p "For more information, see the 'View Rules' section.";
@subtitle "Command-Line Usage";
@p "When run normally, either by launching through a file explorer or running from a command line without arguments, `raddbg` will open a new instance of the debugger. But it also supports a number of command line options for a number of other purposes. These options are specified with a `-` or `--` prefix, followed by the name of the option, and if the option requires a parameter, followed by a `:` or `=`, followed by the parameter's content. A list of the possible options follows:";
@unordered_list
{
@p "`--help` Displays a help menu which documents the possible command line options.";
@p "`--user:<path>` Specifies a path to the user file which the debugger should use instead of the default. The default user file is stored at `%appdata%/raddbg/default.raddbg_user`. For more information on user files, read the 'User & Profile Files' section.";
@p "`--project:<path>` Specifies a path to the project file which the debugger should use instead of the default. The default project file is stored at `%appdata%/raddbg/default.raddbg_project`. For more information on project files, read the 'User & Project Files' section.";
@p "`--auto_run` Specifies that the debugger should immediately run its selected targets upon launching.";
@p "`--auto_step` Specifies that the debugger should immediately step into its selected targets upon launching.";
//@p "`--ipc` Specifies that the launched debugger instance is for communicating a command to another instance of the debugger. In this mode, any non-argument command line contents will be used to express a command. For more information on commands, read the 'Commands' section. For more information on driving another debugger instance with this argument, read the 'Driving Another Debugger Instance' section."
}
@p "On the command line, non-options (meaning any command line arguments *not* prefixed with a `-` or `--`) can also be specified. with normal usage, they are interpreted as the command line for a target (see the 'Targets' section)."
// add when --ipc support is ready: "When driving another debugger instance (using the `--ipc` argument), this additional command line text is used to encode a debugger command.";
@p "The debugger will stop parsing `-` and `--` prefixes as arguments after seeing a standalone `--`, *or* after seeing the first non-option argument, when reading the command line left-to-right. Some examples of command line usage and their interpretations are below:";
@unordered_list
{
@p "`raddbg --foo --bar --a:b --c=d test.exe` All options are used to configure `raddbg`. `test.exe` is interpreted as a target executable. `b` is interpreted as the parameter for the `a` option. `d` is interpreted as the parameter for the `c` option.";
@p "`raddbg test.exe --foo --bar` `test.exe` is interpreted as a target executable. `--foo --bar` is interpreted as arguments for `test.exe`, and thus are *not* used to configure `raddbg`.";
@p "`raddbg -- test.exe` `test.exe` is interpreted as a target executable.";
//@p "`raddbg --ipc find_code_location \"c:/foo/bar/baz.c:123:1\"` `--ipc` configures `raddbg` to drive another instance of `raddbg`. The remainder of the text is interpreted as a command.";
@p "`raddbg \"C:/path with spaces/test.exe\" --foo --bar` A target is formed from the `test.exe` path, and `--foo --bar` are interpreted as arguments to the `test.exe` target.";
}
@subtitle "Windows, Panels, & Tabs";
@p "Each opened *window* in the debugger frontend is subdivided into *panels*. Panels subdivide regions of their window without overlapping. Each panel can contain multiple *tabs*, and can have one tab selected at any time. Tabs can be dragged and dropped between panels. Each tab is used to view one of the many supported debugger interfaces, including source code, disassembly, memory, or watches. When a tab is selected, that interface will fill the tab's containing panel's region of the containing window.";
@p "There are no 'special' windows, panels, or tabs; the debugger is written such that the number of windows, each window's panel organization, and the placement and arrangement of tabs can all be organized in a large variety of ways.";
@p "A list of debugger interfaces, which can occupy tabs, are below:";
@unordered_list
{
@expand(DF_GfxViewTable a) @p "$(a.inc_in_docs -> '`'..a.display_string..'` '..a.docs_desc)";
}
@subtitle "Commands";
@p "The debugger is operated with *commands*. Commands may be manually executed in the debugger UI through the `Commands` menu (which you can open either in the `View` menu bar list, or by using the keybinding, which is F1 by default). Operations in the debugger UI are implemented with commands, so if it's ever unclear how to accomplish some operation through the UI, a useful fallback is searching for and running the command through the command menu.";
//@p "Commands are also how a debugger instance launched with `--ipc` may communicate with a primary debugger instance.";
//@p "A list of commands, how they're referred to textually (for the purposes of `--ipc` debugger instances), and their descriptions are below:";
@p "A list of commands and their descriptions are below:";
@unordered_list
{
@expand(DF_CoreCmdTable a) @p "$(a.lister_omit == 0 -> '`'..a.display_name..'` '..'(`'..a.string..'`) '..a.desc)";
}
@subtitle "Targets";
@p "A *target* is one executable and configuration for launching that executable, including command line arguments and working directory (the directory from which the executable is launched). Each target may also have a custom label (replaces the executable path when visualizing the target), and the name of a custom entry point function (when the default entry points - `main`, `WinMain`, etc. - are not desired when stepping into the program upon launch). The debugger can have several targets at once. Each target can also be enabled or disabled. Some operations work on all enabled targets - for instance, the `Run` or `Kill All` commands (standardly bound as F5 or Shift + F5). Enabling and disabling targets allows one to filter which targets are currently being worked with.";
@p "To add a target, you can run the `Add Target` command. A target is also created automatically from command line arguments - the rules for how this happens can be found in the `Command-Line Usage` section.";
@p "Targets created through command line usage are temporary, meaning they are not persistently saved across runs of the debugger. To change this, you can right click the command-line-created target in the `Targets` view, and click `Save To Project`. After doing so, the target will be restored across runs, and will no longer need to be specified on the command-line.";
@subtitle "View Rules";
@p "*View Rules* are used to transform the way that evaluations in the debugger are visualized. An evaluation is produced by taking an expression string - for instance, the name of a variable - and using debug info and information from an attached process' live runtime (memory, registers, and so on) to interpret it.";
@p "Evaluations may be visualized in a variety of ways. A 64-bit unsigned integer may be visualized as a textual representation of the value with a radix of 10. A 32-bit floating-point value may be visualized as a textual representation of the value. An array of 32-bit floating-point values can be visualized as a list of textual representations of those values.";
@p "But all of these cases may be visualized in a number of other ways, as well. A 64-bit unsigned integer may be more usefully represented with a radix of 16, 8, or 2. An array of 32-bit floating-point values may encode the R, G, B, and A components of a color, or vertex positions for 3D geometry, or samples for a waveform. An array of bytes may encode raw pixel data for an image, or image data in a compressed format. A struct may have several members which are not useful to look at all the time. A struct may form the head of a linked list, and a flat linked list representation may be more preferable than the traditional watch view representation, which adds an additional layer of hierarchical nesting with the expansion of each 'next' pointer in a linked list. When designing the debugger, we felt that the traditional memory view and watch view representations of data in a debugged-process were not sufficient. View rules were added to the traditional watch view structure to allow per-row specification of extra visualization parameters.";
@p "View rules are specified with the name of a view rule, and depending on the view rule, a `:`, followed by parameters for the view rule. These parameters may be whitespace delimited, but importantly, multiple view rules may be specified per-row in a watch view. To explicitly separate the parameters of one view rule from the name of another - for instance, in a case like `array:16 bin`, where `bin` will not be interpreted as a view rule, but as a parameter of `array` - then commas and semicolons may be used to separate the two view rules (`array:16, bin`), or parentheses/braces/brackets may also be used to explicitly delimit the view rule parameters (`array:(16) bin`).";
@p "A list of currently-supported view rules are below:";
@unordered_list
{
@expand(DF_CoreViewRuleTable a) @p "$(a.docs == 'x' -> '`'..a.string..'` ('..a.display_name..') '..a.description)";
}
@subtitle "Breakpoints";
@p "Breakpoints interrupt execution of attached processes. They may be placed on specific code addresses, lines of source code, on specific symbol names. In the latter two cases, the higher level locations are resolved to code addresses. If there is no code associated with a line of source code, then the resolution path chooses to use the next closest line of source code in the same file. A symbol name breakpoint will only work if the symbol name is found within loaded debug info.";
@p "Breakpoints may have stop conditions attached to them. When a breakpoint is hit by a thread, before it stops execution, the stop condition is evaluated, and if it evaluates to a nonzero value, only then is execution stopped.";
@p "Each breakpoint has a hit count. Every time a breakpoint causes execution to stop, this counter is increased.";
@p "Processor breakpoints are not currently supported, but planned to be in the future.";
@subtitle "User & Project Files";
@p "Applicable state controlling the debugger's appearance, behavior, targets, breakpoints, and other configurations is saved and reloaded across runs of the debugger through both *user files* and *project files*. These files are auto-saved. These files are written in a textual format which can be hand-edited as necessary, but they're also continuously re-read and re-written by the debugger. By default, the debugger uses `%appdata%/raddbg/default.raddbg_user` for its user file path, and `%appdata%/raddbg/default.raddbg_project` for its project file path. These paths can be overridden on the command line (see the 'Command-Line Usage' section).";
@p "The *user file* defaultly stores file path maps, windows (including their preferred monitor, placement, and size), each window's panel layout and tabs, keybindings, theme colors, and fonts.";
@p "The *project file* defaultly stores targets, breakpoints, watch pins, and exception code filters.";
@p "Because both can be hand-edited, however, if you want to store something normally stored in a user file in a project file, or vice versa, this can be done by hand transferring the textual data from one file to another. There is no path in the debugger's UI to support this transfer, currently, although this is planned.";
//@subtitle "Driving Another Debugger Instance";
//@p "When the debugger is launched with the `--ipc` command-line argument, it does not launch another instance of the graphical debugger. Instead, it launches, sends a string encoding a command to a running instance of the graphical debugger, and then terminates. The set of commands which can be sent are identical to those which can be run from the debugger's UI itself, but these commands must be encoded textually (through the other command-line arguments). These commands are described in the 'Commands' section.";
}
File diff suppressed because it is too large Load Diff
-144
View File
@@ -1,144 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef DF_VIEW_RULES_H
#define DF_VIEW_RULES_H
////////////////////////////////
//~ rjf: "rgba"
typedef struct DF_VR_RGBAState DF_VR_RGBAState;
struct DF_VR_RGBAState
{
Vec4F32 hsva;
U64 memgen_idx;
};
internal Vec4F32 df_vr_rgba_from_eval(DF_Eval eval, TG_Graph *graph, RDI_Parsed *raddbg, DF_Entity *process);
internal void df_vr_eval_commit_rgba(DF_Eval eval, TG_Graph *graph, RDI_Parsed *raddbg, DF_CtrlCtx *ctrl_ctx, Vec4F32 rgba);
////////////////////////////////
//~ rjf: "text"
typedef struct DF_TxtTopologyInfo DF_TxtTopologyInfo;
struct DF_TxtTopologyInfo
{
TXT_LangKind lang;
U64 size_cap;
};
typedef struct DF_VR_TextState DF_VR_TextState;
struct DF_VR_TextState
{
B32 initialized;
TxtPt cursor;
TxtPt mark;
S64 preferred_column;
U64 last_open_frame_idx;
F32 loaded_t;
};
internal DF_TxtTopologyInfo df_vr_txt_topology_info_from_cfg(DI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg);
////////////////////////////////
//~ rjf: "disasm"
typedef struct DF_DisasmTopologyInfo DF_DisasmTopologyInfo;
struct DF_DisasmTopologyInfo
{
Architecture arch;
U64 size_cap;
};
typedef struct DF_VR_DisasmState DF_VR_DisasmState;
struct DF_VR_DisasmState
{
B32 initialized;
TxtPt cursor;
TxtPt mark;
S64 preferred_column;
U64 last_open_frame_idx;
F32 loaded_t;
};
internal DF_DisasmTopologyInfo df_vr_disasm_topology_info_from_cfg(DI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg);
////////////////////////////////
//~ rjf: "bitmap"
typedef struct DF_BitmapTopologyInfo DF_BitmapTopologyInfo;
struct DF_BitmapTopologyInfo
{
U64 width;
U64 height;
R_Tex2DFormat fmt;
};
typedef struct DF_BitmapViewState DF_BitmapViewState;
struct DF_BitmapViewState
{
Vec2F32 view_center_pos;
F32 zoom;
DF_BitmapTopologyInfo top;
};
typedef struct DF_VR_BitmapState DF_VR_BitmapState;
struct DF_VR_BitmapState
{
U64 last_open_frame_idx;
F32 loaded_t;
};
typedef struct DF_VR_BitmapBoxDrawData DF_VR_BitmapBoxDrawData;
struct DF_VR_BitmapBoxDrawData
{
Rng2F32 src;
R_Handle texture;
F32 loaded_t;
B32 hovered;
Vec2S32 mouse_px;
F32 ui_per_bmp_px;
};
internal Vec2F32 df_bitmap_view_state__screen_from_canvas_pos(DF_BitmapViewState *bvs, Rng2F32 rect, Vec2F32 cvs);
internal Rng2F32 df_bitmap_view_state__screen_from_canvas_rect(DF_BitmapViewState *bvs, Rng2F32 rect, Rng2F32 cvs);
internal Vec2F32 df_bitmap_view_state__canvas_from_screen_pos(DF_BitmapViewState *bvs, Rng2F32 rect, Vec2F32 scr);
internal Rng2F32 df_bitmap_view_state__canvas_from_screen_rect(DF_BitmapViewState *bvs, Rng2F32 rect, Rng2F32 scr);
internal DF_BitmapTopologyInfo df_vr_bitmap_topology_info_from_cfg(DI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg);
////////////////////////////////
//~ rjf: "geo"
typedef struct DF_GeoTopologyInfo DF_GeoTopologyInfo;
struct DF_GeoTopologyInfo
{
U64 index_count;
Rng1U64 vertices_vaddr_range;
};
typedef struct DF_VR_GeoState DF_VR_GeoState;
struct DF_VR_GeoState
{
B32 initialized;
U64 last_open_frame_idx;
F32 loaded_t;
F32 pitch;
F32 pitch_target;
F32 yaw;
F32 yaw_target;
F32 zoom;
F32 zoom_target;
};
typedef struct DF_VR_GeoBoxDrawData DF_VR_GeoBoxDrawData;
struct DF_VR_GeoBoxDrawData
{
DF_ExpandKey key;
R_Handle vertex_buffer;
R_Handle index_buffer;
F32 loaded_t;
};
internal DF_GeoTopologyInfo df_vr_geo_topology_info_from_cfg(DI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg);
#endif // DF_VIEW_RULES_H
File diff suppressed because it is too large Load Diff
-565
View File
@@ -1,565 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef DEBUG_FRONTEND_VIEWS_H
#define DEBUG_FRONTEND_VIEWS_H
////////////////////////////////
//~ rjf: FileSystem @view_types
typedef enum DF_FileSortKind
{
DF_FileSortKind_Null,
DF_FileSortKind_Filename,
DF_FileSortKind_LastModified,
DF_FileSortKind_Size,
DF_FileSortKind_COUNT
}
DF_FileSortKind;
typedef struct DF_FileInfo DF_FileInfo;
struct DF_FileInfo
{
String8 filename;
FileProperties props;
FuzzyMatchRangeList match_ranges;
};
typedef struct DF_FileInfoNode DF_FileInfoNode;
struct DF_FileInfoNode
{
DF_FileInfoNode *next;
DF_FileInfo file_info;
};
typedef struct DF_FileSystemViewPathState DF_FileSystemViewPathState;
struct DF_FileSystemViewPathState
{
DF_FileSystemViewPathState *hash_next;
String8 normalized_path;
Vec2S64 cursor;
};
typedef struct DF_FileSystemViewState DF_FileSystemViewState;
struct DF_FileSystemViewState
{
B32 initialized;
U64 path_state_table_size;
DF_FileSystemViewPathState **path_state_table;
DF_FileSortKind sort_kind;
Side sort_side;
Arena *cached_files_arena;
String8 cached_files_path;
DF_FileSortKind cached_files_sort_kind;
Side cached_files_sort_side;
U64 cached_file_count;
DF_FileInfo *cached_files;
F32 col_pcts[3];
};
////////////////////////////////
//~ rjf: Commands @view_types
typedef struct DF_CmdListerItem DF_CmdListerItem;
struct DF_CmdListerItem
{
DF_CmdSpec *cmd_spec;
U64 registrar_idx;
U64 ordering_idx;
FuzzyMatchRangeList name_match_ranges;
FuzzyMatchRangeList desc_match_ranges;
FuzzyMatchRangeList tags_match_ranges;
};
typedef struct DF_CmdListerItemNode DF_CmdListerItemNode;
struct DF_CmdListerItemNode
{
DF_CmdListerItemNode *next;
DF_CmdListerItem item;
};
typedef struct DF_CmdListerItemList DF_CmdListerItemList;
struct DF_CmdListerItemList
{
DF_CmdListerItemNode *first;
DF_CmdListerItemNode *last;
U64 count;
};
typedef struct DF_CmdListerItemArray DF_CmdListerItemArray;
struct DF_CmdListerItemArray
{
DF_CmdListerItem *v;
U64 count;
};
////////////////////////////////
//~ rjf: PendingEntity @view_types
typedef struct DF_PendingEntityViewState DF_PendingEntityViewState;
struct DF_PendingEntityViewState
{
Arena *deferred_cmd_arena;
DF_CmdList deferred_cmds;
Arena *complete_cfg_arena;
DF_CfgNode *complete_cfg_root;
};
////////////////////////////////
//~ rjf: EntityLister @view_types
typedef struct DF_EntityListerItem DF_EntityListerItem;
struct DF_EntityListerItem
{
DF_Entity *entity;
FuzzyMatchRangeList name_match_ranges;
};
typedef struct DF_EntityListerItemNode DF_EntityListerItemNode;
struct DF_EntityListerItemNode
{
DF_EntityListerItemNode *next;
DF_EntityListerItem item;
};
typedef struct DF_EntityListerItemList DF_EntityListerItemList;
struct DF_EntityListerItemList
{
DF_EntityListerItemNode *first;
DF_EntityListerItemNode *last;
U64 count;
};
typedef struct DF_EntityListerItemArray DF_EntityListerItemArray;
struct DF_EntityListerItemArray
{
DF_EntityListerItem *v;
U64 count;
};
////////////////////////////////
//~ rjf: SystemProcesses @view_types
typedef struct DF_ProcessInfo DF_ProcessInfo;
struct DF_ProcessInfo
{
DMN_ProcessInfo info;
B32 is_attached;
FuzzyMatchRangeList attached_match_ranges;
FuzzyMatchRangeList name_match_ranges;
FuzzyMatchRangeList pid_match_ranges;
};
typedef struct DF_ProcessInfoNode DF_ProcessInfoNode;
struct DF_ProcessInfoNode
{
DF_ProcessInfoNode *next;
DF_ProcessInfo info;
};
typedef struct DF_ProcessInfoList DF_ProcessInfoList;
struct DF_ProcessInfoList
{
DF_ProcessInfoNode *first;
DF_ProcessInfoNode *last;
U64 count;
};
typedef struct DF_ProcessInfoArray DF_ProcessInfoArray;
struct DF_ProcessInfoArray
{
DF_ProcessInfo *v;
U64 count;
};
////////////////////////////////
//~ rjf: Breakpoint @view_types
typedef struct DF_BreakpointViewState DF_BreakpointViewState;
struct DF_BreakpointViewState
{
B32 initialized;
Vec2S32 selected_p;
F32 key_pct;
F32 val_pct;
};
////////////////////////////////
//~ rjf: Target @view_types
typedef struct DF_TargetViewState DF_TargetViewState;
struct DF_TargetViewState
{
B32 initialized;
// rjf: pick file kind
DF_EntityKind pick_dst_kind;
// rjf: selection cursor
Vec2S64 cursor;
// rjf: text input state
TxtPt input_cursor;
TxtPt input_mark;
U8 input_buffer[1024];
U64 input_size;
B32 input_editing;
// rjf: table column pcts
F32 key_pct;
F32 value_pct;
};
////////////////////////////////
//~ rjf: FilePathMap @view_types
typedef struct DF_FilePathMapViewState DF_FilePathMapViewState;
struct DF_FilePathMapViewState
{
B32 initialized;
Vec2S64 cursor;
TxtPt input_cursor;
TxtPt input_mark;
U8 input_buffer[1024];
U64 input_size;
B32 input_editing;
DF_Handle pick_file_dst_map;
Side pick_file_dst_side;
F32 src_column_pct;
F32 dst_column_pct;
};
////////////////////////////////
//~ rjf: AutoViewRules @view_types
typedef struct DF_AutoViewRulesViewState DF_AutoViewRulesViewState;
struct DF_AutoViewRulesViewState
{
B32 initialized;
Vec2S64 cursor;
TxtPt input_cursor;
TxtPt input_mark;
U8 input_buffer[1024];
U64 input_size;
B32 input_editing;
F32 src_column_pct;
F32 dst_column_pct;
};
////////////////////////////////
//~ rjf: Modules @view_types
typedef struct DF_ModulesViewState DF_ModulesViewState;
struct DF_ModulesViewState
{
B32 initialized;
DF_Handle selected_entity;
S64 selected_column;
B32 txt_editing;
TxtPt txt_cursor;
TxtPt txt_mark;
U8 txt_buffer[1024];
U64 txt_size;
DF_Handle pick_file_dst_entity;
F32 idx_col_pct;
F32 desc_col_pct;
F32 range_col_pct;
F32 dbg_col_pct;
};
////////////////////////////////
//~ rjf: Watch, Locals, Registers @view_types
typedef struct DF_EvalRoot DF_EvalRoot;
struct DF_EvalRoot
{
DF_EvalRoot *next;
DF_EvalRoot *prev;
U64 expr_buffer_string_size;
U64 expr_buffer_cap;
U8 *expr_buffer;
};
typedef enum DF_WatchViewColumnKind
{
DF_WatchViewColumnKind_Expr,
DF_WatchViewColumnKind_Value,
DF_WatchViewColumnKind_Type,
DF_WatchViewColumnKind_ViewRule,
DF_WatchViewColumnKind_COUNT
}
DF_WatchViewColumnKind;
typedef enum DF_WatchViewFillKind
{
DF_WatchViewFillKind_Mutable,
DF_WatchViewFillKind_Registers,
DF_WatchViewFillKind_Locals,
DF_WatchViewFillKind_Globals,
DF_WatchViewFillKind_ThreadLocals,
DF_WatchViewFillKind_Types,
DF_WatchViewFillKind_Procedures,
DF_WatchViewFillKind_COUNT
}
DF_WatchViewFillKind;
typedef struct DF_WatchViewPoint DF_WatchViewPoint;
struct DF_WatchViewPoint
{
DF_WatchViewColumnKind column_kind;
DF_ExpandKey parent_key;
DF_ExpandKey key;
};
typedef struct DF_WatchViewTextEditState DF_WatchViewTextEditState;
struct DF_WatchViewTextEditState
{
DF_WatchViewTextEditState *pt_hash_next;
DF_WatchViewPoint pt;
TxtPt cursor;
TxtPt mark;
U8 input_buffer[1024];
U64 input_size;
U8 initial_buffer[1024];
U64 initial_size;
};
typedef struct DF_WatchViewState DF_WatchViewState;
struct DF_WatchViewState
{
B32 initialized;
// rjf: fill kind (way that the contents of the watch view are computed)
DF_WatchViewFillKind fill_kind;
// rjf; table cursor state
DF_WatchViewPoint cursor;
DF_WatchViewPoint mark;
DF_WatchViewPoint next_cursor;
DF_WatchViewPoint next_mark;
// rjf: text input state
Arena *text_edit_arena;
U64 text_edit_state_slots_count;
DF_WatchViewTextEditState dummy_text_edit_state;
DF_WatchViewTextEditState **text_edit_state_slots;
B32 text_editing;
// rjf: table column width state
F32 expr_column_pct;
F32 value_column_pct;
F32 type_column_pct;
F32 view_rule_column_pct;
// rjf: mutable fill-kind root expression state
DF_EvalRoot *first_root;
DF_EvalRoot *last_root;
DF_EvalRoot *first_free_root;
U64 root_count;
};
////////////////////////////////
//~ rjf: Code, Output @view_types
typedef U32 DF_CodeViewFlags;
enum
{
DF_CodeViewFlag_StickToBottom = (1<<0),
};
typedef U32 DF_CodeViewBuildFlags;
enum
{
DF_CodeViewBuildFlag_Margins = (1<<0),
DF_CodeViewBuildFlag_All = 0xffffffff,
};
typedef struct DF_CodeViewState DF_CodeViewState;
struct DF_CodeViewState
{
// rjf: stable state
B32 initialized;
S64 preferred_column;
B32 drifted_for_search;
DF_Handle pick_file_override_target;
DF_CodeViewFlags flags;
// rjf: per-frame command info
S64 goto_line_num;
B32 center_cursor;
B32 contain_cursor;
B32 watch_expr_at_mouse;
Arena *find_text_arena;
String8 find_text_fwd;
String8 find_text_bwd;
};
////////////////////////////////
//~ rjf: Disassembly @view_types
typedef struct DF_DisasmViewState DF_DisasmViewState;
struct DF_DisasmViewState
{
B32 initialized;
DF_Handle process;
U64 base_vaddr;
DASM_StyleFlags style_flags;
U64 goto_vaddr;
DF_CodeViewState cv;
};
////////////////////////////////
//~ rjf: Memory @view_types
typedef struct DF_MemoryViewState DF_MemoryViewState;
struct DF_MemoryViewState
{
B32 initialized;
// rjf: last-viewed-memory cache
Arena *last_viewed_memory_cache_arena;
U8 *last_viewed_memory_cache_buffer;
Rng1U64 last_viewed_memory_cache_range;
U64 last_viewed_memory_cache_memgen_idx;
// rjf: control state
U64 cursor;
U64 mark;
// rjf: organization state
U64 num_columns;
U64 bytes_per_cell;
// rjf: command pass-through data
B32 center_cursor;
B32 contain_cursor;
};
////////////////////////////////
//~ rjf: Settings @view_types
typedef enum DF_SettingsItemKind
{
DF_SettingsItemKind_CategoryHeader,
DF_SettingsItemKind_GlobalSetting,
DF_SettingsItemKind_WindowSetting,
DF_SettingsItemKind_ThemeColor,
DF_SettingsItemKind_ThemePreset,
DF_SettingsItemKind_COUNT
}
DF_SettingsItemKind;
typedef struct DF_SettingsItem DF_SettingsItem;
struct DF_SettingsItem
{
DF_SettingsItemKind kind;
String8 kind_string;
String8 string;
FuzzyMatchRangeList kind_string_matches;
FuzzyMatchRangeList string_matches;
DF_IconKind icon_kind;
DF_SettingCode code;
DF_ThemeColor color;
DF_ThemePreset preset;
DF_SettingsItemKind category;
};
typedef struct DF_SettingsItemNode DF_SettingsItemNode;
struct DF_SettingsItemNode
{
DF_SettingsItemNode *next;
DF_SettingsItem v;
};
typedef struct DF_SettingsItemList DF_SettingsItemList;
struct DF_SettingsItemList
{
DF_SettingsItemNode *first;
DF_SettingsItemNode *last;
U64 count;
};
typedef struct DF_SettingsItemArray DF_SettingsItemArray;
struct DF_SettingsItemArray
{
DF_SettingsItem *v;
U64 count;
};
////////////////////////////////
//~ rjf: Quick Sort Comparisons
internal int df_qsort_compare_file_info__default(DF_FileInfo *a, DF_FileInfo *b);
internal int df_qsort_compare_file_info__default_filtered(DF_FileInfo *a, DF_FileInfo *b);
internal int df_qsort_compare_file_info__filename(DF_FileInfo *a, DF_FileInfo *b);
internal int df_qsort_compare_file_info__last_modified(DF_FileInfo *a, DF_FileInfo *b);
internal int df_qsort_compare_file_info__size(DF_FileInfo *a, DF_FileInfo *b);
internal int df_qsort_compare_process_info(DF_ProcessInfo *a, DF_ProcessInfo *b);
internal int df_qsort_compare_cmd_lister__strength(DF_CmdListerItem *a, DF_CmdListerItem *b);
internal int df_qsort_compare_entity_lister__strength(DF_EntityListerItem *a, DF_EntityListerItem *b);
internal int df_qsort_compare_settings_item(DF_SettingsItem *a, DF_SettingsItem *b);
////////////////////////////////
//~ rjf: Command Lister
internal DF_CmdListerItemList df_cmd_lister_item_list_from_needle(Arena *arena, String8 needle);
internal DF_CmdListerItemArray df_cmd_lister_item_array_from_list(Arena *arena, DF_CmdListerItemList list);
internal void df_cmd_lister_item_array_sort_by_strength__in_place(DF_CmdListerItemArray array);
////////////////////////////////
//~ rjf: System Process Lister
internal DF_ProcessInfoList df_process_info_list_from_query(Arena *arena, String8 query);
internal DF_ProcessInfoArray df_process_info_array_from_list(Arena *arena, DF_ProcessInfoList list);
internal void df_process_info_array_sort_by_strength__in_place(DF_ProcessInfoArray array);
////////////////////////////////
//~ rjf: Entity Lister
internal DF_EntityListerItemList df_entity_lister_item_list_from_needle(Arena *arena, DF_EntityKind kind, DF_EntityFlags omit_flags, String8 needle);
internal DF_EntityListerItemArray df_entity_lister_item_array_from_list(Arena *arena, DF_EntityListerItemList list);
internal void df_entity_lister_item_array_sort_by_strength__in_place(DF_EntityListerItemArray array);
////////////////////////////////
//~ rjf: Code Views
internal void df_code_view_init(DF_CodeViewState *cv, DF_View *view);
internal void df_code_view_cmds(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewState *cv, DF_CmdList *cmds, String8 text_data, TXT_TextInfo *text_info, DASM_InstArray *dasm_insts, Rng1U64 dasm_vaddr_range, DI_Key dasm_dbgi_key);
internal void df_code_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_CodeViewState *cv, DF_CodeViewBuildFlags flags, Rng2F32 rect, String8 text_data, TXT_TextInfo *text_info, DASM_InstArray *dasm_insts, Rng1U64 dasm_vaddr_range, DI_Key dasm_dbgi_key);
////////////////////////////////
//~ rjf: Watch Views
//- rjf: eval watch view instance -> eval view key
internal DF_EvalViewKey df_eval_view_key_from_eval_watch_view(DF_WatchViewState *ewv);
//- rjf: root allocation/deallocation/mutation
internal DF_EvalRoot * df_eval_root_alloc(DF_View *view, DF_WatchViewState *ews);
internal void df_eval_root_release(DF_WatchViewState *ews, DF_EvalRoot *root);
internal void df_eval_root_equip_string(DF_EvalRoot *root, String8 string);
internal DF_EvalRoot * df_eval_root_from_string(DF_WatchViewState *ews, String8 string);
internal DF_EvalRoot * df_eval_root_from_expand_key(DF_WatchViewState *ews, DF_EvalView *eval_view, DF_ExpandKey expand_key);
internal String8 df_string_from_eval_root(DF_EvalRoot *root);
internal DF_ExpandKey df_parent_expand_key_from_eval_root(DF_EvalRoot *root);
internal DF_ExpandKey df_expand_key_from_eval_root(DF_EvalRoot *root);
//- rjf: watch view points <-> table coordinates
internal B32 df_watch_view_point_match(DF_WatchViewPoint a, DF_WatchViewPoint b);
internal DF_WatchViewPoint df_watch_view_point_from_tbl(DF_EvalVizBlockList *blocks, Vec2S64 tbl);
internal Vec2S64 df_tbl_from_watch_view_point(DF_EvalVizBlockList *blocks, DF_WatchViewPoint pt);
//- rjf: table coordinates -> strings
internal String8 df_string_from_eval_viz_row_column_kind(Arena *arena, DF_EvalView *ev, TG_Graph *graph, RDI_Parsed *rdi, DF_EvalVizRow *row, DF_WatchViewColumnKind col_kind, B32 editable);
//- rjf: table coordinates -> text edit state
internal DF_WatchViewTextEditState *df_watch_view_text_edit_state_from_pt(DF_WatchViewState *wv, DF_WatchViewPoint pt);
//- rjf: windowed watch tree visualization
internal DF_EvalVizBlockList df_eval_viz_block_list_from_watch_view_state(Arena *arena, DI_Scope *di_scope, FZY_Scope *fzy_scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_View *view, DF_WatchViewState *ews);
//- rjf: eval/watch views main hooks
internal void df_watch_view_init(DF_WatchViewState *ewv, DF_View *view, DF_WatchViewFillKind fill_kind);
internal void df_watch_view_cmds(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewState *ewv, DF_CmdList *cmds);
internal void df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewState *ewv, B32 modifiable, U32 default_radix, Rng2F32 rect);
#endif // DEBUG_FRONTEND_VIEWS_H
File diff suppressed because it is too large Load Diff
+112 -110
View File
@@ -4,24 +4,24 @@
//////////////////////////////// ////////////////////////////////
//~ rjf: Generated Code //~ rjf: Generated Code
#define D_StackPushImpl(name_upper, name_lower, type, val) \ #define DR_StackPushImpl(name_upper, name_lower, type, val) \
D_Bucket *bucket = d_top_bucket();\ DR_Bucket *bucket = dr_top_bucket();\
type old_val = bucket->top_##name_lower->v;\ type old_val = bucket->top_##name_lower->v;\
D_##name_upper##Node *node = push_array(d_thread_ctx->arena, D_##name_upper##Node, 1);\ DR_##name_upper##Node *node = push_array(dr_thread_ctx->arena, DR_##name_upper##Node, 1);\
node->v = (val);\ node->v = (val);\
SLLStackPush(bucket->top_##name_lower, node);\ SLLStackPush(bucket->top_##name_lower, node);\
bucket->stack_gen += 1;\ bucket->stack_gen += 1;\
return old_val return old_val
#define D_StackPopImpl(name_upper, name_lower, type) \ #define DR_StackPopImpl(name_upper, name_lower, type) \
D_Bucket *bucket = d_top_bucket();\ DR_Bucket *bucket = dr_top_bucket();\
type popped_val = bucket->top_##name_lower->v;\ type popped_val = bucket->top_##name_lower->v;\
SLLStackPop(bucket->top_##name_lower);\ SLLStackPop(bucket->top_##name_lower);\
bucket->stack_gen += 1;\ bucket->stack_gen += 1;\
return popped_val return popped_val
#define D_StackTopImpl(name_upper, name_lower, type) \ #define DR_StackTopImpl(name_upper, name_lower, type) \
D_Bucket *bucket = d_top_bucket();\ DR_Bucket *bucket = dr_top_bucket();\
type top_val = bucket->top_##name_lower->v;\ type top_val = bucket->top_##name_lower->v;\
return top_val return top_val
@@ -31,7 +31,7 @@ return top_val
//~ rjf: Basic Helpers //~ rjf: Basic Helpers
internal U64 internal U64
d_hash_from_string(String8 string) dr_hash_from_string(String8 string)
{ {
U64 result = 5381; U64 result = 5381;
for(U64 i = 0; i < string.size; i += 1) for(U64 i = 0; i < string.size; i += 1)
@@ -45,9 +45,9 @@ d_hash_from_string(String8 string)
//~ rjf: Fancy String Type Functions //~ rjf: Fancy String Type Functions
internal void internal void
d_fancy_string_list_push(Arena *arena, D_FancyStringList *list, D_FancyString *str) dr_fancy_string_list_push(Arena *arena, DR_FancyStringList *list, DR_FancyString *str)
{ {
D_FancyStringNode *n = push_array_no_zero(arena, D_FancyStringNode, 1); DR_FancyStringNode *n = push_array_no_zero(arena, DR_FancyStringNode, 1);
MemoryCopyStruct(&n->v, str); MemoryCopyStruct(&n->v, str);
SLLQueuePush(list->first, list->last, n); SLLQueuePush(list->first, list->last, n);
list->node_count += 1; list->node_count += 1;
@@ -55,7 +55,7 @@ d_fancy_string_list_push(Arena *arena, D_FancyStringList *list, D_FancyString *s
} }
internal void internal void
d_fancy_string_list_concat_in_place(D_FancyStringList *dst, D_FancyStringList *to_push) dr_fancy_string_list_concat_in_place(DR_FancyStringList *dst, DR_FancyStringList *to_push)
{ {
if(dst->last != 0 && to_push->first != 0) if(dst->last != 0 && to_push->first != 0)
{ {
@@ -72,13 +72,13 @@ d_fancy_string_list_concat_in_place(D_FancyStringList *dst, D_FancyStringList *t
} }
internal String8 internal String8
d_string_from_fancy_string_list(Arena *arena, D_FancyStringList *list) dr_string_from_fancy_string_list(Arena *arena, DR_FancyStringList *list)
{ {
String8 result = {0}; String8 result = {0};
result.size = list->total_size; result.size = list->total_size;
result.str = push_array_no_zero(arena, U8, result.size); result.str = push_array_no_zero(arena, U8, result.size);
U64 idx = 0; U64 idx = 0;
for(D_FancyStringNode *n = list->first; n != 0; n = n->next) for(DR_FancyStringNode *n = list->first; n != 0; n = n->next)
{ {
MemoryCopy(result.str+idx, n->v.string.str, n->v.string.size); MemoryCopy(result.str+idx, n->v.string.str, n->v.string.size);
idx += n->v.string.size; idx += n->v.string.size;
@@ -86,16 +86,16 @@ d_string_from_fancy_string_list(Arena *arena, D_FancyStringList *list)
return result; return result;
} }
internal D_FancyRunList internal DR_FancyRunList
d_fancy_run_list_from_fancy_string_list(Arena *arena, F32 tab_size_px, F_RasterFlags flags, D_FancyStringList *strs) dr_fancy_run_list_from_fancy_string_list(Arena *arena, F32 tab_size_px, FNT_RasterFlags flags, DR_FancyStringList *strs)
{ {
ProfBeginFunction(); ProfBeginFunction();
D_FancyRunList run_list = {0}; DR_FancyRunList run_list = {0};
F32 base_align_px = 0; F32 base_align_px = 0;
for(D_FancyStringNode *n = strs->first; n != 0; n = n->next) for(DR_FancyStringNode *n = strs->first; n != 0; n = n->next)
{ {
D_FancyRunNode *dst_n = push_array(arena, D_FancyRunNode, 1); DR_FancyRunNode *dst_n = push_array(arena, DR_FancyRunNode, 1);
dst_n->v.run = f_push_run_from_string(arena, n->v.font, n->v.size, base_align_px, tab_size_px, flags, n->v.string); dst_n->v.run = fnt_push_run_from_string(arena, n->v.font, n->v.size, base_align_px, tab_size_px, flags, n->v.string);
dst_n->v.color = n->v.color; dst_n->v.color = n->v.color;
dst_n->v.underline_thickness = n->v.underline_thickness; dst_n->v.underline_thickness = n->v.underline_thickness;
dst_n->v.strikethrough_thickness = n->v.strikethrough_thickness; dst_n->v.strikethrough_thickness = n->v.strikethrough_thickness;
@@ -109,16 +109,16 @@ d_fancy_run_list_from_fancy_string_list(Arena *arena, F32 tab_size_px, F_RasterF
return run_list; return run_list;
} }
internal D_FancyRunList internal DR_FancyRunList
d_fancy_run_list_copy(Arena *arena, D_FancyRunList *src) dr_fancy_run_list_copy(Arena *arena, DR_FancyRunList *src)
{ {
D_FancyRunList dst = {0}; DR_FancyRunList dst = {0};
for(D_FancyRunNode *src_n = src->first; src_n != 0; src_n = src_n->next) for(DR_FancyRunNode *src_n = src->first; src_n != 0; src_n = src_n->next)
{ {
D_FancyRunNode *dst_n = push_array(arena, D_FancyRunNode, 1); DR_FancyRunNode *dst_n = push_array(arena, DR_FancyRunNode, 1);
SLLQueuePush(dst.first, dst.last, dst_n); SLLQueuePush(dst.first, dst.last, dst_n);
MemoryCopyStruct(&dst_n->v, &src_n->v); MemoryCopyStruct(&dst_n->v, &src_n->v);
dst_n->v.run.pieces = f_piece_array_copy(arena, &src_n->v.run.pieces); dst_n->v.run.pieces = fnt_piece_array_copy(arena, &src_n->v.run.pieces);
dst.node_count += 1; dst.node_count += 1;
} }
dst.dim = src->dim; dst.dim = src->dim;
@@ -131,22 +131,22 @@ d_fancy_run_list_copy(Arena *arena, D_FancyRunList *src)
// (Frame boundaries) // (Frame boundaries)
internal void internal void
d_begin_frame(void) dr_begin_frame(void)
{ {
if(d_thread_ctx == 0) if(dr_thread_ctx == 0)
{ {
Arena *arena = arena_alloc__sized(GB(64), MB(8)); Arena *arena = arena_alloc(.reserve_size = GB(64), .commit_size = MB(8));
d_thread_ctx = push_array(arena, D_ThreadCtx, 1); dr_thread_ctx = push_array(arena, DR_ThreadCtx, 1);
d_thread_ctx->arena = arena; dr_thread_ctx->arena = arena;
d_thread_ctx->arena_frame_start_pos = arena_pos(arena); dr_thread_ctx->arena_frame_start_pos = arena_pos(arena);
} }
arena_pop_to(d_thread_ctx->arena, d_thread_ctx->arena_frame_start_pos); arena_pop_to(dr_thread_ctx->arena, dr_thread_ctx->arena_frame_start_pos);
d_thread_ctx->free_bucket_selection = 0; dr_thread_ctx->free_bucket_selection = 0;
d_thread_ctx->top_bucket = 0; dr_thread_ctx->top_bucket = 0;
} }
internal void internal void
d_submit_bucket(OS_Handle os_window, R_Handle r_window, D_Bucket *bucket) dr_submit_bucket(OS_Handle os_window, R_Handle r_window, DR_Bucket *bucket)
{ {
r_window_submit(os_window, r_window, &bucket->passes); r_window_submit(os_window, r_window, &bucket->passes);
} }
@@ -156,45 +156,45 @@ d_submit_bucket(OS_Handle os_window, R_Handle r_window, D_Bucket *bucket)
// //
// (Bucket: Handle to sequence of many render passes, constructed by this layer) // (Bucket: Handle to sequence of many render passes, constructed by this layer)
internal D_Bucket * internal DR_Bucket *
d_bucket_make(void) dr_bucket_make(void)
{ {
D_Bucket *bucket = push_array(d_thread_ctx->arena, D_Bucket, 1); DR_Bucket *bucket = push_array(dr_thread_ctx->arena, DR_Bucket, 1);
D_BucketStackInits(bucket); DR_BucketStackInits(bucket);
return bucket; return bucket;
} }
internal void internal void
d_push_bucket(D_Bucket *bucket) dr_push_bucket(DR_Bucket *bucket)
{ {
D_BucketSelectionNode *node = d_thread_ctx->free_bucket_selection; DR_BucketSelectionNode *node = dr_thread_ctx->free_bucket_selection;
if(node) if(node)
{ {
SLLStackPop(d_thread_ctx->free_bucket_selection); SLLStackPop(dr_thread_ctx->free_bucket_selection);
} }
else else
{ {
node = push_array(d_thread_ctx->arena, D_BucketSelectionNode, 1); node = push_array(dr_thread_ctx->arena, DR_BucketSelectionNode, 1);
} }
SLLStackPush(d_thread_ctx->top_bucket, node); SLLStackPush(dr_thread_ctx->top_bucket, node);
node->bucket = bucket; node->bucket = bucket;
} }
internal void internal void
d_pop_bucket(void) dr_pop_bucket(void)
{ {
D_BucketSelectionNode *node = d_thread_ctx->top_bucket; DR_BucketSelectionNode *node = dr_thread_ctx->top_bucket;
SLLStackPop(d_thread_ctx->top_bucket); SLLStackPop(dr_thread_ctx->top_bucket);
SLLStackPush(d_thread_ctx->free_bucket_selection, node); SLLStackPush(dr_thread_ctx->free_bucket_selection, node);
} }
internal D_Bucket * internal DR_Bucket *
d_top_bucket(void) dr_top_bucket(void)
{ {
D_Bucket *bucket = 0; DR_Bucket *bucket = 0;
if(d_thread_ctx->top_bucket != 0) if(dr_thread_ctx->top_bucket != 0)
{ {
bucket = d_thread_ctx->top_bucket->bucket; bucket = dr_thread_ctx->top_bucket->bucket;
} }
return bucket; return bucket;
} }
@@ -214,10 +214,10 @@ d_top_bucket(void)
//- rjf: rectangles //- rjf: rectangles
internal inline R_Rect2DInst * internal inline R_Rect2DInst *
d_rect(Rng2F32 dst, Vec4F32 color, F32 corner_radius, F32 border_thickness, F32 edge_softness) dr_rect(Rng2F32 dst, Vec4F32 color, F32 corner_radius, F32 border_thickness, F32 edge_softness)
{ {
Arena *arena = d_thread_ctx->arena; Arena *arena = dr_thread_ctx->arena;
D_Bucket *bucket = d_top_bucket(); DR_Bucket *bucket = dr_top_bucket();
R_Pass *pass = r_pass_from_kind(arena, &bucket->passes, R_PassKind_UI); R_Pass *pass = r_pass_from_kind(arena, &bucket->passes, R_PassKind_UI);
R_PassParams_UI *params = pass->params_ui; R_PassParams_UI *params = pass->params_ui;
R_BatchGroup2DList *rects = &params->rects; R_BatchGroup2DList *rects = &params->rects;
@@ -255,10 +255,10 @@ d_rect(Rng2F32 dst, Vec4F32 color, F32 corner_radius, F32 border_thickness, F32
//- rjf: images //- rjf: images
internal inline R_Rect2DInst * internal inline R_Rect2DInst *
d_img(Rng2F32 dst, Rng2F32 src, R_Handle texture, Vec4F32 color, F32 corner_radius, F32 border_thickness, F32 edge_softness) dr_img(Rng2F32 dst, Rng2F32 src, R_Handle texture, Vec4F32 color, F32 corner_radius, F32 border_thickness, F32 edge_softness)
{ {
Arena *arena = d_thread_ctx->arena; Arena *arena = dr_thread_ctx->arena;
D_Bucket *bucket = d_top_bucket(); DR_Bucket *bucket = dr_top_bucket();
R_Pass *pass = r_pass_from_kind(arena, &bucket->passes, R_PassKind_UI); R_Pass *pass = r_pass_from_kind(arena, &bucket->passes, R_PassKind_UI);
R_PassParams_UI *params = pass->params_ui; R_PassParams_UI *params = pass->params_ui;
R_BatchGroup2DList *rects = &params->rects; R_BatchGroup2DList *rects = &params->rects;
@@ -300,14 +300,14 @@ d_img(Rng2F32 dst, Rng2F32 src, R_Handle texture, Vec4F32 color, F32 corner_radi
//- rjf: blurs //- rjf: blurs
internal R_PassParams_Blur * internal R_PassParams_Blur *
d_blur(Rng2F32 rect, F32 blur_size, F32 corner_radius) dr_blur(Rng2F32 rect, F32 blur_size, F32 corner_radius)
{ {
Arena *arena = d_thread_ctx->arena; Arena *arena = dr_thread_ctx->arena;
D_Bucket *bucket = d_top_bucket(); DR_Bucket *bucket = dr_top_bucket();
R_Pass *pass = r_pass_from_kind(arena, &bucket->passes, R_PassKind_Blur); R_Pass *pass = r_pass_from_kind(arena, &bucket->passes, R_PassKind_Blur);
R_PassParams_Blur *params = pass->params_blur; R_PassParams_Blur *params = pass->params_blur;
params->rect = rect; params->rect = rect;
params->clip = d_top_clip(); params->clip = dr_top_clip();
params->blur_size = blur_size; params->blur_size = blur_size;
params->corner_radii[Corner_00] = corner_radius; params->corner_radii[Corner_00] = corner_radius;
params->corner_radii[Corner_01] = corner_radius; params->corner_radii[Corner_01] = corner_radius;
@@ -319,10 +319,10 @@ d_blur(Rng2F32 rect, F32 blur_size, F32 corner_radius)
//- rjf: 3d rendering pass params //- rjf: 3d rendering pass params
internal R_PassParams_Geo3D * internal R_PassParams_Geo3D *
d_geo3d_begin(Rng2F32 viewport, Mat4x4F32 view, Mat4x4F32 projection) dr_geo3d_begin(Rng2F32 viewport, Mat4x4F32 view, Mat4x4F32 projection)
{ {
Arena *arena = d_thread_ctx->arena; Arena *arena = dr_thread_ctx->arena;
D_Bucket *bucket = d_top_bucket(); DR_Bucket *bucket = dr_top_bucket();
R_Pass *pass = r_pass_from_kind(arena, &bucket->passes, R_PassKind_Geo3D); R_Pass *pass = r_pass_from_kind(arena, &bucket->passes, R_PassKind_Geo3D);
R_PassParams_Geo3D *params = pass->params_geo3d; R_PassParams_Geo3D *params = pass->params_geo3d;
params->viewport = viewport; params->viewport = viewport;
@@ -334,10 +334,10 @@ d_geo3d_begin(Rng2F32 viewport, Mat4x4F32 view, Mat4x4F32 projection)
//- rjf: meshes //- rjf: meshes
internal R_Mesh3DInst * internal R_Mesh3DInst *
d_mesh(R_Handle mesh_vertices, R_Handle mesh_indices, R_GeoTopologyKind mesh_geo_topology, R_GeoVertexFlags mesh_geo_vertex_flags, R_Handle albedo_tex, Mat4x4F32 inst_xform) dr_mesh(R_Handle mesh_vertices, R_Handle mesh_indices, R_GeoTopologyKind mesh_geo_topology, R_GeoVertexFlags mesh_geo_vertex_flags, R_Handle albedo_tex, Mat4x4F32 inst_xform)
{ {
Arena *arena = d_thread_ctx->arena; Arena *arena = dr_thread_ctx->arena;
D_Bucket *bucket = d_top_bucket(); DR_Bucket *bucket = dr_top_bucket();
R_Pass *pass = r_pass_from_kind(arena, &bucket->passes, R_PassKind_Geo3D); R_Pass *pass = r_pass_from_kind(arena, &bucket->passes, R_PassKind_Geo3D);
R_PassParams_Geo3D *params = pass->params_geo3d; R_PassParams_Geo3D *params = pass->params_geo3d;
@@ -362,9 +362,9 @@ d_mesh(R_Handle mesh_vertices, R_Handle mesh_indices, R_GeoTopologyKind mesh_geo
(U64)mesh_geo_vertex_flags, (U64)mesh_geo_vertex_flags,
albedo_tex.u64[0], albedo_tex.u64[0],
albedo_tex.u64[1], albedo_tex.u64[1],
(U64)d_top_tex2d_sample_kind(), (U64)dr_top_tex2d_sample_kind(),
}; };
hash = d_hash_from_string(str8((U8 *)buffer, sizeof(buffer))); hash = dr_hash_from_string(str8((U8 *)buffer, sizeof(buffer)));
slot_idx = hash%params->mesh_batches.slots_count; slot_idx = hash%params->mesh_batches.slots_count;
} }
@@ -393,7 +393,7 @@ d_mesh(R_Handle mesh_vertices, R_Handle mesh_indices, R_GeoTopologyKind mesh_geo
node->params.mesh_geo_topology = mesh_geo_topology; node->params.mesh_geo_topology = mesh_geo_topology;
node->params.mesh_geo_vertex_flags = mesh_geo_vertex_flags; node->params.mesh_geo_vertex_flags = mesh_geo_vertex_flags;
node->params.albedo_tex = albedo_tex; node->params.albedo_tex = albedo_tex;
node->params.albedo_tex_sample_kind = d_top_tex2d_sample_kind(); node->params.albedo_tex_sample_kind = dr_top_tex2d_sample_kind();
node->params.xform = mat_4x4f32(1.f); node->params.xform = mat_4x4f32(1.f);
} }
@@ -406,12 +406,12 @@ d_mesh(R_Handle mesh_vertices, R_Handle mesh_indices, R_GeoTopologyKind mesh_geo
//- rjf: collating one pre-prepped bucket into parent bucket //- rjf: collating one pre-prepped bucket into parent bucket
internal void internal void
d_sub_bucket(D_Bucket *bucket) dr_sub_bucket(DR_Bucket *bucket)
{ {
Arena *arena = d_thread_ctx->arena; Arena *arena = dr_thread_ctx->arena;
D_Bucket *src = bucket; DR_Bucket *src = bucket;
D_Bucket *dst = d_top_bucket(); DR_Bucket *dst = dr_top_bucket();
Rng2F32 dst_clip = d_top_clip(); Rng2F32 dst_clip = dr_top_clip();
B32 dst_clip_is_set = !(dst_clip.x0 == 0 && dst_clip.x1 == 0 && B32 dst_clip_is_set = !(dst_clip.x0 == 0 && dst_clip.x1 == 0 &&
dst_clip.y0 == 0 && dst_clip.y1 == 0); dst_clip.y0 == 0 && dst_clip.y1 == 0);
for(R_PassNode *n = src->passes.first; n != 0; n = n->next) for(R_PassNode *n = src->passes.first; n != 0; n = n->next)
@@ -434,7 +434,7 @@ d_sub_bucket(D_Bucket *bucket)
dst_ui->rects.count += 1; dst_ui->rects.count += 1;
MemoryCopyStruct(&dst_group_n->params, &src_group_n->params); MemoryCopyStruct(&dst_group_n->params, &src_group_n->params);
dst_group_n->batches = src_group_n->batches; dst_group_n->batches = src_group_n->batches;
dst_group_n->params.xform = d_top_xform2d(); dst_group_n->params.xform = dr_top_xform2d();
if(dst_clip_is_set) if(dst_clip_is_set)
{ {
B32 clip_is_set = !(dst_group_n->params.clip.x0 == 0 && B32 clip_is_set = !(dst_group_n->params.clip.x0 == 0 &&
@@ -455,7 +455,7 @@ d_sub_bucket(D_Bucket *bucket)
//- rjf: text //- rjf: text
internal void internal void
d_truncated_fancy_run_list(Vec2F32 p, D_FancyRunList *list, F32 max_x, F_Run trailer_run) dr_truncated_fancy_run_list(Vec2F32 p, DR_FancyRunList *list, F32 max_x, FNT_Run trailer_run)
{ {
ProfBeginFunction(); ProfBeginFunction();
@@ -467,19 +467,19 @@ d_truncated_fancy_run_list(Vec2F32 p, D_FancyRunList *list, F32 max_x, F_Run tra
B32 trailer_found = 0; B32 trailer_found = 0;
Vec4F32 last_color = {0}; Vec4F32 last_color = {0};
U64 byte_off = 0; U64 byte_off = 0;
for(D_FancyRunNode *n = list->first; n != 0; n = n->next) for(DR_FancyRunNode *n = list->first; n != 0; n = n->next)
{ {
D_FancyRun *fr = &n->v; DR_FancyRun *fr = &n->v;
Rng1F32 pixel_range = {0}; Rng1F32 pixel_range = {0};
{ {
pixel_range.min = 100000; pixel_range.min = 100000;
pixel_range.max = 0; pixel_range.max = 0;
} }
F_Piece *piece_first = fr->run.pieces.v; FNT_Piece *piece_first = fr->run.pieces.v;
F_Piece *piece_opl = piece_first + fr->run.pieces.count; FNT_Piece *piece_opl = piece_first + fr->run.pieces.count;
F32 pre_advance = advance; F32 pre_advance = advance;
last_color = fr->color; last_color = fr->color;
for(F_Piece *piece = piece_first; for(FNT_Piece *piece = piece_first;
piece < piece_opl; piece < piece_opl;
piece += 1) piece += 1)
{ {
@@ -501,8 +501,8 @@ d_truncated_fancy_run_list(Vec2F32 p, D_FancyRunList *list, F32 max_x, F_Run tra
p.y + piece->offset.y + size.y); p.y + piece->offset.y + size.y);
if(!r_handle_match(texture, r_handle_zero())) if(!r_handle_match(texture, r_handle_zero()))
{ {
d_img(dst, src, texture, fr->color, 0, 0, 0); dr_img(dst, src, texture, fr->color, 0, 0, 0);
//d_rect(dst, v4f32(0, 1, 0, 0.5f), 0, 1.f, 0.f); //dr_rect(dst, v4f32(0, 1, 0, 0.5f), 0, 1.f, 0.f);
} }
advance += piece->advance; advance += piece->advance;
pixel_range.min = Min(pre_advance, pixel_range.min); pixel_range.min = Min(pre_advance, pixel_range.min);
@@ -510,15 +510,15 @@ d_truncated_fancy_run_list(Vec2F32 p, D_FancyRunList *list, F32 max_x, F_Run tra
} }
if(fr->underline_thickness > 0) if(fr->underline_thickness > 0)
{ {
d_rect(r2f32p(p.x + pixel_range.min, dr_rect(r2f32p(p.x + pixel_range.min,
p.y+fr->run.descent+fr->run.descent/8, p.y+fr->run.descent+fr->run.descent/8,
p.x + pixel_range.max, p.x + pixel_range.max,
p.y+fr->run.descent+fr->run.descent/8+fr->underline_thickness), p.y+fr->run.descent+fr->run.descent/8+fr->underline_thickness),
fr->color, 0, 0, 0.8f); fr->color, 0, 0, 0.8f);
} }
if(fr->strikethrough_thickness > 0) if(fr->strikethrough_thickness > 0)
{ {
d_rect(r2f32p(p.x+pre_advance, p.y+fr->run.descent - fr->run.ascent/2, p.x+advance, p.y+fr->run.descent - fr->run.ascent/2 + fr->strikethrough_thickness), fr->color, 0, 0, 1.f); dr_rect(r2f32p(p.x+pre_advance, p.y+fr->run.descent - fr->run.ascent/2, p.x+advance, p.y+fr->run.descent - fr->run.ascent/2 + fr->strikethrough_thickness), fr->color, 0, 0, 1.f);
} }
if(trailer_found) if(trailer_found)
{ {
@@ -530,11 +530,11 @@ d_truncated_fancy_run_list(Vec2F32 p, D_FancyRunList *list, F32 max_x, F_Run tra
//- rjf: draw trailer //- rjf: draw trailer
if(trailer_found) if(trailer_found)
{ {
F_Piece *piece_first = trailer_run.pieces.v; FNT_Piece *piece_first = trailer_run.pieces.v;
F_Piece *piece_opl = piece_first + trailer_run.pieces.count; FNT_Piece *piece_opl = piece_first + trailer_run.pieces.count;
F32 pre_advance = advance; F32 pre_advance = advance;
Vec4F32 trailer_piece_color = last_color; Vec4F32 trailer_piece_color = last_color;
for(F_Piece *piece = piece_first; for(FNT_Piece *piece = piece_first;
piece < piece_opl; piece < piece_opl;
piece += 1) piece += 1)
{ {
@@ -547,7 +547,7 @@ d_truncated_fancy_run_list(Vec2F32 p, D_FancyRunList *list, F32 max_x, F_Run tra
p.y + piece->offset.y + size.y); p.y + piece->offset.y + size.y);
if(!r_handle_match(texture, r_handle_zero())) if(!r_handle_match(texture, r_handle_zero()))
{ {
d_img(dst, src, texture, trailer_piece_color, 0, 0, 0); dr_img(dst, src, texture, trailer_piece_color, 0, 0, 0);
trailer_piece_color.w *= 0.5f; trailer_piece_color.w *= 0.5f;
} }
advance += piece->advance; advance += piece->advance;
@@ -558,7 +558,7 @@ d_truncated_fancy_run_list(Vec2F32 p, D_FancyRunList *list, F32 max_x, F_Run tra
} }
internal void internal void
d_truncated_fancy_run_fuzzy_matches(Vec2F32 p, D_FancyRunList *list, F32 max_x, FuzzyMatchRangeList *ranges, Vec4F32 color) dr_truncated_fancy_run_fuzzy_matches(Vec2F32 p, DR_FancyRunList *list, F32 max_x, FuzzyMatchRangeList *ranges, Vec4F32 color)
{ {
for(FuzzyMatchRangeNode *match_n = ranges->first; match_n != 0; match_n = match_n->next) for(FuzzyMatchRangeNode *match_n = ranges->first; match_n != 0; match_n = match_n->next)
{ {
@@ -573,15 +573,15 @@ d_truncated_fancy_run_fuzzy_matches(Vec2F32 p, D_FancyRunList *list, F32 max_x,
F32 advance = 0; F32 advance = 0;
F32 ascent = 0; F32 ascent = 0;
F32 descent = 0; F32 descent = 0;
for(D_FancyRunNode *fr_n = list->first; fr_n != 0; fr_n = fr_n->next) for(DR_FancyRunNode *fr_n = list->first; fr_n != 0; fr_n = fr_n->next)
{ {
D_FancyRun *fr = &fr_n->v; DR_FancyRun *fr = &fr_n->v;
F_Run *run = &fr->run; FNT_Run *run = &fr->run;
ascent = run->ascent; ascent = run->ascent;
descent = run->descent; descent = run->descent;
for(U64 piece_idx = 0; piece_idx < run->pieces.count; piece_idx += 1) for(U64 piece_idx = 0; piece_idx < run->pieces.count; piece_idx += 1)
{ {
F_Piece *piece = &run->pieces.v[piece_idx]; FNT_Piece *piece = &run->pieces.v[piece_idx];
if(contains_1u64(byte_range, byte_off)) if(contains_1u64(byte_range, byte_off))
{ {
F32 pre_advance = advance + piece->offset.x; F32 pre_advance = advance + piece->offset.x;
@@ -601,18 +601,19 @@ d_truncated_fancy_run_fuzzy_matches(Vec2F32 p, D_FancyRunList *list, F32 max_x,
p.y - descent - ascent + ascent/8.f + list->dim.y); p.y - descent - ascent + ascent/8.f + list->dim.y);
rect.x0 = Min(rect.x0, p.x+max_x); rect.x0 = Min(rect.x0, p.x+max_x);
rect.x1 = Min(rect.x1, p.x+max_x); rect.x1 = Min(rect.x1, p.x+max_x);
d_rect(rect, color, (descent+ascent)/4.f, 0, 1.f); dr_rect(rect, color, (descent+ascent)/4.f, 0, 1.f);
} }
} }
} }
internal void internal void
d_text_run(Vec2F32 p, Vec4F32 color, F_Run run) dr_text_run(Vec2F32 p, Vec4F32 color, FNT_Run run)
{ {
ProfBeginFunction();
F32 advance = 0; F32 advance = 0;
F_Piece *piece_first = run.pieces.v; FNT_Piece *piece_first = run.pieces.v;
F_Piece *piece_opl = piece_first + run.pieces.count; FNT_Piece *piece_opl = piece_first + run.pieces.count;
for(F_Piece *piece = piece_first; for(FNT_Piece *piece = piece_first;
piece < piece_opl; piece < piece_opl;
piece += 1) piece += 1)
{ {
@@ -625,17 +626,18 @@ d_text_run(Vec2F32 p, Vec4F32 color, F_Run run)
p.y + piece->offset.y + size.y); p.y + piece->offset.y + size.y);
if(size.x != 0 && size.y != 0 && !r_handle_match(texture, r_handle_zero())) if(size.x != 0 && size.y != 0 && !r_handle_match(texture, r_handle_zero()))
{ {
d_img(dst, src, texture, color, 0, 0, 0); dr_img(dst, src, texture, color, 0, 0, 0);
} }
advance += piece->advance; advance += piece->advance;
} }
ProfEnd();
} }
internal void internal void
d_text(F_Tag font, F32 size, F32 base_align_px, F32 tab_size_px, F_RasterFlags flags, Vec2F32 p, Vec4F32 color, String8 string) dr_text(FNT_Tag font, F32 size, F32 base_align_px, F32 tab_size_px, FNT_RasterFlags flags, Vec2F32 p, Vec4F32 color, String8 string)
{ {
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
F_Run run = f_push_run_from_string(scratch.arena, font, size, base_align_px, tab_size_px, flags, string); FNT_Run run = fnt_push_run_from_string(scratch.arena, font, size, base_align_px, tab_size_px, flags, string);
d_text_run(p, color, run); dr_text_run(p, color, run);
scratch_end(scratch); scratch_end(scratch);
} }
+74 -73
View File
@@ -7,10 +7,10 @@
//////////////////////////////// ////////////////////////////////
//~ rjf: Fancy String Types //~ rjf: Fancy String Types
typedef struct D_FancyString D_FancyString; typedef struct DR_FancyString DR_FancyString;
struct D_FancyString struct DR_FancyString
{ {
F_Tag font; FNT_Tag font;
String8 string; String8 string;
Vec4F32 color; Vec4F32 color;
F32 size; F32 size;
@@ -18,43 +18,43 @@ struct D_FancyString
F32 strikethrough_thickness; F32 strikethrough_thickness;
}; };
typedef struct D_FancyStringNode D_FancyStringNode; typedef struct DR_FancyStringNode DR_FancyStringNode;
struct D_FancyStringNode struct DR_FancyStringNode
{ {
D_FancyStringNode *next; DR_FancyStringNode *next;
D_FancyString v; DR_FancyString v;
}; };
typedef struct D_FancyStringList D_FancyStringList; typedef struct DR_FancyStringList DR_FancyStringList;
struct D_FancyStringList struct DR_FancyStringList
{ {
D_FancyStringNode *first; DR_FancyStringNode *first;
D_FancyStringNode *last; DR_FancyStringNode *last;
U64 node_count; U64 node_count;
U64 total_size; U64 total_size;
}; };
typedef struct D_FancyRun D_FancyRun; typedef struct DR_FancyRun DR_FancyRun;
struct D_FancyRun struct DR_FancyRun
{ {
F_Run run; FNT_Run run;
Vec4F32 color; Vec4F32 color;
F32 underline_thickness; F32 underline_thickness;
F32 strikethrough_thickness; F32 strikethrough_thickness;
}; };
typedef struct D_FancyRunNode D_FancyRunNode; typedef struct DR_FancyRunNode DR_FancyRunNode;
struct D_FancyRunNode struct DR_FancyRunNode
{ {
D_FancyRunNode *next; DR_FancyRunNode *next;
D_FancyRun v; DR_FancyRun v;
}; };
typedef struct D_FancyRunList D_FancyRunList; typedef struct DR_FancyRunList DR_FancyRunList;
struct D_FancyRunList struct DR_FancyRunList
{ {
D_FancyRunNode *first; DR_FancyRunNode *first;
D_FancyRunNode *last; DR_FancyRunNode *last;
U64 node_count; U64 node_count;
Vec2F32 dim; Vec2F32 dim;
}; };
@@ -67,94 +67,95 @@ struct D_FancyRunList
//////////////////////////////// ////////////////////////////////
//~ rjf: Draw Bucket Types //~ rjf: Draw Bucket Types
typedef struct D_Bucket D_Bucket; typedef struct DR_Bucket DR_Bucket;
struct D_Bucket struct DR_Bucket
{ {
R_PassList passes; R_PassList passes;
U64 stack_gen; U64 stack_gen;
U64 last_cmd_stack_gen; U64 last_cmd_stack_gen;
D_BucketStackDecls; DR_BucketStackDecls;
}; };
//////////////////////////////// ////////////////////////////////
//~ rjf: Thread Context //~ rjf: Thread Context
typedef struct D_BucketSelectionNode D_BucketSelectionNode; typedef struct DR_BucketSelectionNode DR_BucketSelectionNode;
struct D_BucketSelectionNode struct DR_BucketSelectionNode
{ {
D_BucketSelectionNode *next; DR_BucketSelectionNode *next;
D_Bucket *bucket; DR_Bucket *bucket;
}; };
typedef struct D_ThreadCtx D_ThreadCtx; typedef struct DR_ThreadCtx DR_ThreadCtx;
struct D_ThreadCtx struct DR_ThreadCtx
{ {
Arena *arena; Arena *arena;
U64 arena_frame_start_pos; U64 arena_frame_start_pos;
D_BucketSelectionNode *top_bucket; DR_BucketSelectionNode *top_bucket;
D_BucketSelectionNode *free_bucket_selection; DR_BucketSelectionNode *free_bucket_selection;
}; };
//////////////////////////////// ////////////////////////////////
//~ rjf: Globals //~ rjf: Globals
thread_static D_ThreadCtx *d_thread_ctx = 0; thread_static DR_ThreadCtx *dr_thread_ctx = 0;
//////////////////////////////// ////////////////////////////////
//~ rjf: Basic Helpers //~ rjf: Basic Helpers
internal U64 d_hash_from_string(String8 string); internal U64 dr_hash_from_string(String8 string);
//////////////////////////////// ////////////////////////////////
//~ rjf: Fancy String Type Functions //~ rjf: Fancy String Type Functions
internal void d_fancy_string_list_push(Arena *arena, D_FancyStringList *list, D_FancyString *str); internal void dr_fancy_string_list_push(Arena *arena, DR_FancyStringList *list, DR_FancyString *str);
internal void d_fancy_string_list_concat_in_place(D_FancyStringList *dst, D_FancyStringList *to_push); #define dr_fancy_string_list_push_new(arena, list, font_, size_, color_, string_, ...) dr_fancy_string_list_push((arena), (list), &(DR_FancyString){.font = (font_), .string = (string_), .color = (color_), .size = (size_), __VA_ARGS__})
internal String8 d_string_from_fancy_string_list(Arena *arena, D_FancyStringList *list); internal void dr_fancy_string_list_concat_in_place(DR_FancyStringList *dst, DR_FancyStringList *to_push);
internal D_FancyRunList d_fancy_run_list_from_fancy_string_list(Arena *arena, F32 tab_size_px, F_RasterFlags flags, D_FancyStringList *strs); internal String8 dr_string_from_fancy_string_list(Arena *arena, DR_FancyStringList *list);
internal D_FancyRunList d_fancy_run_list_copy(Arena *arena, D_FancyRunList *src); internal DR_FancyRunList dr_fancy_run_list_from_fancy_string_list(Arena *arena, F32 tab_size_px, FNT_RasterFlags flags, DR_FancyStringList *strs);
internal DR_FancyRunList dr_fancy_run_list_copy(Arena *arena, DR_FancyRunList *src);
//////////////////////////////// ////////////////////////////////
//~ rjf: Top-Level API //~ rjf: Top-Level API
// //
// (Frame boundaries & bucket submission) // (Frame boundaries & bucket submission)
internal void d_begin_frame(void); internal void dr_begin_frame(void);
internal void d_submit_bucket(OS_Handle os_window, R_Handle r_window, D_Bucket *bucket); internal void dr_submit_bucket(OS_Handle os_window, R_Handle r_window, DR_Bucket *bucket);
//////////////////////////////// ////////////////////////////////
//~ rjf: Bucket Construction & Selection API //~ rjf: Bucket Construction & Selection API
// //
// (Bucket: Handle to sequence of many render passes, constructed by this layer) // (Bucket: Handle to sequence of many render passes, constructed by this layer)
internal D_Bucket *d_bucket_make(void); internal DR_Bucket *dr_bucket_make(void);
internal void d_push_bucket(D_Bucket *bucket); internal void dr_push_bucket(DR_Bucket *bucket);
internal void d_pop_bucket(void); internal void dr_pop_bucket(void);
internal D_Bucket *d_top_bucket(void); internal DR_Bucket *dr_top_bucket(void);
#define D_BucketScope(b) DeferLoop(d_push_bucket(b), d_pop_bucket()) #define DR_BucketScope(b) DeferLoop(dr_push_bucket(b), dr_pop_bucket())
//////////////////////////////// ////////////////////////////////
//~ rjf: Bucket Stacks //~ rjf: Bucket Stacks
// //
// (Pushing/popping implicit draw parameters) // (Pushing/popping implicit draw parameters)
internal R_Tex2DSampleKind d_push_tex2d_sample_kind(R_Tex2DSampleKind v); internal R_Tex2DSampleKind dr_push_tex2d_sample_kind(R_Tex2DSampleKind v);
internal Mat3x3F32 d_push_xform2d(Mat3x3F32 v); internal Mat3x3F32 dr_push_xform2d(Mat3x3F32 v);
internal Rng2F32 d_push_clip(Rng2F32 v); internal Rng2F32 dr_push_clip(Rng2F32 v);
internal F32 d_push_transparency(F32 v); internal F32 dr_push_transparency(F32 v);
internal R_Tex2DSampleKind d_pop_tex2d_sample_kind(void); internal R_Tex2DSampleKind dr_pop_tex2d_sample_kind(void);
internal Mat3x3F32 d_pop_xform2d(void); internal Mat3x3F32 dr_pop_xform2d(void);
internal Rng2F32 d_pop_clip(void); internal Rng2F32 dr_pop_clip(void);
internal F32 d_pop_transparency(void); internal F32 dr_pop_transparency(void);
internal R_Tex2DSampleKind d_top_tex2d_sample_kind(void); internal R_Tex2DSampleKind dr_top_tex2d_sample_kind(void);
internal Mat3x3F32 d_top_xform2d(void); internal Mat3x3F32 dr_top_xform2d(void);
internal Rng2F32 d_top_clip(void); internal Rng2F32 dr_top_clip(void);
internal F32 d_top_transparency(void); internal F32 dr_top_transparency(void);
#define D_Tex2DSampleKindScope(v) DeferLoop(d_push_tex2d_sample_kind(v), d_pop_tex2d_sample_kind()) #define DR_Tex2DSampleKindScope(v) DeferLoop(dr_push_tex2d_sample_kind(v), dr_pop_tex2d_sample_kind())
#define D_XForm2DScope(v) DeferLoop(d_push_xform2d(v), d_pop_xform2d()) #define DR_XForm2DScope(v) DeferLoop(dr_push_xform2d(v), dr_pop_xform2d())
#define D_ClipScope(v) DeferLoop(d_push_clip(v), d_pop_clip()) #define DR_ClipScope(v) DeferLoop(dr_push_clip(v), dr_pop_clip())
#define D_TransparencyScope(v) DeferLoop(d_push_transparency(v), d_pop_transparency()) #define DR_TransparencyScope(v) DeferLoop(dr_push_transparency(v), dr_pop_transparency())
//////////////////////////////// ////////////////////////////////
//~ rjf: Core Draw Calls //~ rjf: Core Draw Calls
@@ -162,30 +163,30 @@ internal F32 d_top_transparency(void);
// (Apply to the calling thread's currently selected bucket) // (Apply to the calling thread's currently selected bucket)
//- rjf: rectangles //- rjf: rectangles
internal inline R_Rect2DInst *d_rect(Rng2F32 dst, Vec4F32 color, F32 corner_radius, F32 border_thickness, F32 edge_softness); internal inline R_Rect2DInst *dr_rect(Rng2F32 dst, Vec4F32 color, F32 corner_radius, F32 border_thickness, F32 edge_softness);
//- rjf: images //- rjf: images
internal inline R_Rect2DInst *d_img(Rng2F32 dst, Rng2F32 src, R_Handle texture, Vec4F32 color, F32 corner_radius, F32 border_thickness, F32 edge_softness); internal inline R_Rect2DInst *dr_img(Rng2F32 dst, Rng2F32 src, R_Handle texture, Vec4F32 color, F32 corner_radius, F32 border_thickness, F32 edge_softness);
//- rjf: blurs //- rjf: blurs
internal R_PassParams_Blur *d_blur(Rng2F32 rect, F32 blur_size, F32 corner_radius); internal R_PassParams_Blur *dr_blur(Rng2F32 rect, F32 blur_size, F32 corner_radius);
//- rjf: 3d rendering pass params //- rjf: 3d rendering pass params
internal R_PassParams_Geo3D *d_geo3d_begin(Rng2F32 viewport, Mat4x4F32 view, Mat4x4F32 projection); internal R_PassParams_Geo3D *dr_geo3d_begin(Rng2F32 viewport, Mat4x4F32 view, Mat4x4F32 projection);
//- rjf: meshes //- rjf: meshes
internal R_Mesh3DInst *d_mesh(R_Handle mesh_vertices, R_Handle mesh_indices, R_GeoTopologyKind mesh_geo_topology, R_GeoVertexFlags mesh_geo_vertex_flags, R_Handle albedo_tex, Mat4x4F32 inst_xform); internal R_Mesh3DInst *dr_mesh(R_Handle mesh_vertices, R_Handle mesh_indices, R_GeoTopologyKind mesh_geo_topology, R_GeoVertexFlags mesh_geo_vertex_flags, R_Handle albedo_tex, Mat4x4F32 inst_xform);
//- rjf: collating one pre-prepped bucket into parent bucket //- rjf: collating one pre-prepped bucket into parent bucket
internal void d_sub_bucket(D_Bucket *bucket); internal void dr_sub_bucket(DR_Bucket *bucket);
//////////////////////////////// ////////////////////////////////
//~ rjf: Draw Call Helpers //~ rjf: Draw Call Helpers
//- rjf: text //- rjf: text
internal void d_truncated_fancy_run_list(Vec2F32 p, D_FancyRunList *list, F32 max_x, F_Run trailer_run); internal void dr_truncated_fancy_run_list(Vec2F32 p, DR_FancyRunList *list, F32 max_x, FNT_Run trailer_run);
internal void d_truncated_fancy_run_fuzzy_matches(Vec2F32 p, D_FancyRunList *list, F32 max_x, FuzzyMatchRangeList *ranges, Vec4F32 color); internal void dr_truncated_fancy_run_fuzzy_matches(Vec2F32 p, DR_FancyRunList *list, F32 max_x, FuzzyMatchRangeList *ranges, Vec4F32 color);
internal void d_text_run(Vec2F32 p, Vec4F32 color, F_Run run); internal void dr_text_run(Vec2F32 p, Vec4F32 color, FNT_Run run);
internal void d_text(F_Tag font, F32 size, F32 base_align_px, F32 tab_size_px, F_RasterFlags flags, Vec2F32 p, Vec4F32 color, String8 string); internal void dr_text(FNT_Tag font, F32 size, F32 base_align_px, F32 tab_size_px, FNT_RasterFlags flags, Vec2F32 p, Vec4F32 color, String8 string);
#endif // DRAW_H #endif // DRAW_H
+14 -14
View File
@@ -2,7 +2,7 @@
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
@table(name, name_lower, type, default_init) @table(name, name_lower, type, default_init)
D_StackTable: DR_StackTable:
{ {
{Tex2DSampleKind tex2d_sample_kind R_Tex2DSampleKind `R_Tex2DSampleKind_Nearest` } {Tex2DSampleKind tex2d_sample_kind R_Tex2DSampleKind `R_Tex2DSampleKind_Nearest` }
{XForm2D xform2d Mat3x3F32 `{1, 0, 0, 0, 1, 0, 0, 0, 1}` } {XForm2D xform2d Mat3x3F32 `{1, 0, 0, 0, 1, 0, 0, 0, 1}` }
@@ -12,47 +12,47 @@ D_StackTable:
@gen @gen
{ {
@expand(D_StackTable a) `typedef struct D_$(a.name)Node D_$(a.name)Node; struct D_$(a.name)Node {D_$(a.name)Node *next; $(a.type) v;};`; @expand(DR_StackTable a) `typedef struct DR_$(a.name)Node DR_$(a.name)Node; struct DR_$(a.name)Node {DR_$(a.name)Node *next; $(a.type) v;};`;
} }
@gen @gen
{ {
`#define D_BucketStackDecls struct{\\`; `#define DR_BucketStackDecls struct{\\`;
@expand(D_StackTable a) `D_$(a.name)Node *top_$(a.name_lower);\\`; @expand(DR_StackTable a) `DR_$(a.name)Node *top_$(a.name_lower);\\`;
`}`; `}`;
} }
@gen @gen
{ {
@expand(D_StackTable a) `read_only global D_$(a.name)Node d_nil_$(a.name_lower) = {0, $(a.default_init)};`; @expand(DR_StackTable a) `read_only global DR_$(a.name)Node dr_nil_$(a.name_lower) = {0, $(a.default_init)};`;
} }
@gen @gen
{ {
`#define D_BucketStackInits(b) do{\\`; `#define DR_BucketStackInits(b) do{\\`;
@expand(D_StackTable a) `(b)->top_$(a.name_lower) = &d_nil_$(a.name_lower);\\`; @expand(DR_StackTable a) `(b)->top_$(a.name_lower) = &dr_nil_$(a.name_lower);\\`;
`}while(0)`; `}while(0)`;
} }
@gen @gen
{ {
`#if 0`; `#if 0`;
@expand(D_StackTable a) `internal $(a.type) $(=>35) d_push_$(a.name_lower)($(a.type) v);`; @expand(DR_StackTable a) `internal $(a.type) $(=>35) dr_push_$(a.name_lower)($(a.type) v);`;
@expand(D_StackTable a) `internal $(a.type) $(=>35) d_pop_$(a.name_lower)(void);`; @expand(DR_StackTable a) `internal $(a.type) $(=>35) dr_pop_$(a.name_lower)(void);`;
@expand(D_StackTable a) `internal $(a.type) $(=>35) d_top_$(a.name_lower)(void);`; @expand(DR_StackTable a) `internal $(a.type) $(=>35) dr_top_$(a.name_lower)(void);`;
`#endif`; `#endif`;
} }
@gen @c_file @gen @c_file
{ {
@expand(D_StackTable a) `internal $(a.type) $(=>35) d_push_$(a.name_lower)($(a.type) v) {D_StackPushImpl($(a.name), $(a.name_lower), $(a.type), v);}`; @expand(DR_StackTable a) `internal $(a.type) $(=>35) dr_push_$(a.name_lower)($(a.type) v) {DR_StackPushImpl($(a.name), $(a.name_lower), $(a.type), v);}`;
@expand(D_StackTable a) `internal $(a.type) $(=>35) d_pop_$(a.name_lower)(void) {D_StackPopImpl($(a.name), $(a.name_lower), $(a.type));}`; @expand(DR_StackTable a) `internal $(a.type) $(=>35) dr_pop_$(a.name_lower)(void) {DR_StackPopImpl($(a.name), $(a.name_lower), $(a.type));}`;
@expand(D_StackTable a) `internal $(a.type) $(=>35) d_top_$(a.name_lower)(void) {D_StackTopImpl($(a.name), $(a.name_lower), $(a.type));}`; @expand(DR_StackTable a) `internal $(a.type) $(=>35) dr_top_$(a.name_lower)(void) {DR_StackTopImpl($(a.name), $(a.name_lower), $(a.type));}`;
} }
@gen @gen
{ {
`#if 0`; `#if 0`;
@expand(D_StackTable a) `#define D_$(a.name)Scope(v) $(=>35) DeferLoop(d_push_$(a.name_lower)(v), d_pop_$(a.name_lower)())`; @expand(DR_StackTable a) `#define DR_$(a.name)Scope(v) $(=>35) DeferLoop(dr_push_$(a.name_lower)(v), dr_pop_$(a.name_lower)())`;
`#endif`; `#endif`;
} }
+12 -12
View File
@@ -3,15 +3,15 @@
//- GENERATED CODE //- GENERATED CODE
internal R_Tex2DSampleKind d_push_tex2d_sample_kind(R_Tex2DSampleKind v) {D_StackPushImpl(Tex2DSampleKind, tex2d_sample_kind, R_Tex2DSampleKind, v);} internal R_Tex2DSampleKind dr_push_tex2d_sample_kind(R_Tex2DSampleKind v) {DR_StackPushImpl(Tex2DSampleKind, tex2d_sample_kind, R_Tex2DSampleKind, v);}
internal Mat3x3F32 d_push_xform2d(Mat3x3F32 v) {D_StackPushImpl(XForm2D, xform2d, Mat3x3F32, v);} internal Mat3x3F32 dr_push_xform2d(Mat3x3F32 v) {DR_StackPushImpl(XForm2D, xform2d, Mat3x3F32, v);}
internal Rng2F32 d_push_clip(Rng2F32 v) {D_StackPushImpl(Clip, clip, Rng2F32, v);} internal Rng2F32 dr_push_clip(Rng2F32 v) {DR_StackPushImpl(Clip, clip, Rng2F32, v);}
internal F32 d_push_transparency(F32 v) {D_StackPushImpl(Transparency, transparency, F32, v);} internal F32 dr_push_transparency(F32 v) {DR_StackPushImpl(Transparency, transparency, F32, v);}
internal R_Tex2DSampleKind d_pop_tex2d_sample_kind(void) {D_StackPopImpl(Tex2DSampleKind, tex2d_sample_kind, R_Tex2DSampleKind);} internal R_Tex2DSampleKind dr_pop_tex2d_sample_kind(void) {DR_StackPopImpl(Tex2DSampleKind, tex2d_sample_kind, R_Tex2DSampleKind);}
internal Mat3x3F32 d_pop_xform2d(void) {D_StackPopImpl(XForm2D, xform2d, Mat3x3F32);} internal Mat3x3F32 dr_pop_xform2d(void) {DR_StackPopImpl(XForm2D, xform2d, Mat3x3F32);}
internal Rng2F32 d_pop_clip(void) {D_StackPopImpl(Clip, clip, Rng2F32);} internal Rng2F32 dr_pop_clip(void) {DR_StackPopImpl(Clip, clip, Rng2F32);}
internal F32 d_pop_transparency(void) {D_StackPopImpl(Transparency, transparency, F32);} internal F32 dr_pop_transparency(void) {DR_StackPopImpl(Transparency, transparency, F32);}
internal R_Tex2DSampleKind d_top_tex2d_sample_kind(void) {D_StackTopImpl(Tex2DSampleKind, tex2d_sample_kind, R_Tex2DSampleKind);} internal R_Tex2DSampleKind dr_top_tex2d_sample_kind(void) {DR_StackTopImpl(Tex2DSampleKind, tex2d_sample_kind, R_Tex2DSampleKind);}
internal Mat3x3F32 d_top_xform2d(void) {D_StackTopImpl(XForm2D, xform2d, Mat3x3F32);} internal Mat3x3F32 dr_top_xform2d(void) {DR_StackTopImpl(XForm2D, xform2d, Mat3x3F32);}
internal Rng2F32 d_top_clip(void) {D_StackTopImpl(Clip, clip, Rng2F32);} internal Rng2F32 dr_top_clip(void) {DR_StackTopImpl(Clip, clip, Rng2F32);}
internal F32 d_top_transparency(void) {D_StackTopImpl(Transparency, transparency, F32);} internal F32 dr_top_transparency(void) {DR_StackTopImpl(Transparency, transparency, F32);}
+34 -34
View File
@@ -6,44 +6,44 @@
#ifndef DRAW_META_H #ifndef DRAW_META_H
#define DRAW_META_H #define DRAW_META_H
typedef struct D_Tex2DSampleKindNode D_Tex2DSampleKindNode; struct D_Tex2DSampleKindNode {D_Tex2DSampleKindNode *next; R_Tex2DSampleKind v;}; typedef struct DR_Tex2DSampleKindNode DR_Tex2DSampleKindNode; struct DR_Tex2DSampleKindNode {DR_Tex2DSampleKindNode *next; R_Tex2DSampleKind v;};
typedef struct D_XForm2DNode D_XForm2DNode; struct D_XForm2DNode {D_XForm2DNode *next; Mat3x3F32 v;}; typedef struct DR_XForm2DNode DR_XForm2DNode; struct DR_XForm2DNode {DR_XForm2DNode *next; Mat3x3F32 v;};
typedef struct D_ClipNode D_ClipNode; struct D_ClipNode {D_ClipNode *next; Rng2F32 v;}; typedef struct DR_ClipNode DR_ClipNode; struct DR_ClipNode {DR_ClipNode *next; Rng2F32 v;};
typedef struct D_TransparencyNode D_TransparencyNode; struct D_TransparencyNode {D_TransparencyNode *next; F32 v;}; typedef struct DR_TransparencyNode DR_TransparencyNode; struct DR_TransparencyNode {DR_TransparencyNode *next; F32 v;};
#define D_BucketStackDecls struct{\ #define DR_BucketStackDecls struct{\
D_Tex2DSampleKindNode *top_tex2d_sample_kind;\ DR_Tex2DSampleKindNode *top_tex2d_sample_kind;\
D_XForm2DNode *top_xform2d;\ DR_XForm2DNode *top_xform2d;\
D_ClipNode *top_clip;\ DR_ClipNode *top_clip;\
D_TransparencyNode *top_transparency;\ DR_TransparencyNode *top_transparency;\
} }
read_only global D_Tex2DSampleKindNode d_nil_tex2d_sample_kind = {0, R_Tex2DSampleKind_Nearest}; read_only global DR_Tex2DSampleKindNode dr_nil_tex2d_sample_kind = {0, R_Tex2DSampleKind_Nearest};
read_only global D_XForm2DNode d_nil_xform2d = {0, {1, 0, 0, 0, 1, 0, 0, 0, 1}}; read_only global DR_XForm2DNode dr_nil_xform2d = {0, {1, 0, 0, 0, 1, 0, 0, 0, 1}};
read_only global D_ClipNode d_nil_clip = {0, {0}}; read_only global DR_ClipNode dr_nil_clip = {0, {0}};
read_only global D_TransparencyNode d_nil_transparency = {0, 0}; read_only global DR_TransparencyNode dr_nil_transparency = {0, 0};
#define D_BucketStackInits(b) do{\ #define DR_BucketStackInits(b) do{\
(b)->top_tex2d_sample_kind = &d_nil_tex2d_sample_kind;\ (b)->top_tex2d_sample_kind = &dr_nil_tex2d_sample_kind;\
(b)->top_xform2d = &d_nil_xform2d;\ (b)->top_xform2d = &dr_nil_xform2d;\
(b)->top_clip = &d_nil_clip;\ (b)->top_clip = &dr_nil_clip;\
(b)->top_transparency = &d_nil_transparency;\ (b)->top_transparency = &dr_nil_transparency;\
}while(0) }while(0)
#if 0 #if 0
internal R_Tex2DSampleKind d_push_tex2d_sample_kind(R_Tex2DSampleKind v); internal R_Tex2DSampleKind dr_push_tex2d_sample_kind(R_Tex2DSampleKind v);
internal Mat3x3F32 d_push_xform2d(Mat3x3F32 v); internal Mat3x3F32 dr_push_xform2d(Mat3x3F32 v);
internal Rng2F32 d_push_clip(Rng2F32 v); internal Rng2F32 dr_push_clip(Rng2F32 v);
internal F32 d_push_transparency(F32 v); internal F32 dr_push_transparency(F32 v);
internal R_Tex2DSampleKind d_pop_tex2d_sample_kind(void); internal R_Tex2DSampleKind dr_pop_tex2d_sample_kind(void);
internal Mat3x3F32 d_pop_xform2d(void); internal Mat3x3F32 dr_pop_xform2d(void);
internal Rng2F32 d_pop_clip(void); internal Rng2F32 dr_pop_clip(void);
internal F32 d_pop_transparency(void); internal F32 dr_pop_transparency(void);
internal R_Tex2DSampleKind d_top_tex2d_sample_kind(void); internal R_Tex2DSampleKind dr_top_tex2d_sample_kind(void);
internal Mat3x3F32 d_top_xform2d(void); internal Mat3x3F32 dr_top_xform2d(void);
internal Rng2F32 d_top_clip(void); internal Rng2F32 dr_top_clip(void);
internal F32 d_top_transparency(void); internal F32 dr_top_transparency(void);
#endif #endif
#if 0 #if 0
#define D_Tex2DSampleKindScope(v) DeferLoop(d_push_tex2d_sample_kind(v), d_pop_tex2d_sample_kind()) #define DR_Tex2DSampleKindScope(v) DeferLoop(dr_push_tex2d_sample_kind(v), dr_pop_tex2d_sample_kind())
#define D_XForm2DScope(v) DeferLoop(d_push_xform2d(v), d_pop_xform2d()) #define DR_XForm2DScope(v) DeferLoop(dr_push_xform2d(v), dr_pop_xform2d())
#define D_ClipScope(v) DeferLoop(d_push_clip(v), d_pop_clip()) #define DR_ClipScope(v) DeferLoop(dr_push_clip(v), dr_pop_clip())
#define D_TransparencyScope(v) DeferLoop(d_push_transparency(v), d_pop_transparency()) #define DR_TransparencyScope(v) DeferLoop(dr_push_transparency(v), dr_pop_transparency())
#endif #endif
#endif // DRAW_META_H #endif // DRAW_META_H
+169 -57
View File
@@ -1,63 +1,142 @@
// Copyright (c) 2024 Epic Games Tools // Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
@table(name num_children op_string) @table(name)
// num_children - # of children packed after this node kind E_TokenKindTable:
// op_string - string for quick display of the operator
EVAL_ExprKindTable:
{ {
{ Nil 0 "" } {Null}
{Identifier}
{Numeric}
{StringLiteral}
{CharLiteral}
{Symbol}
}
{ ArrayIndex 2 "[]" } @table(name basic_string basic_byte_size)
{ MemberAccess 2 "." } // NOTE(rjf): basic_byte_size == 0xFF? => address sized
{ Deref 1 "*" } E_TypeKindTable:
{ Address 1 "&" } {
{Null "" 0 }
{Void "void" 0 }
{Handle "HANDLE" 0xFF }
{HResult "HRESULT" 4 }
{Char8 "char8" 1 }
{Char16 "char16" 2 }
{Char32 "char32" 4 }
{UChar8 "uchar8" 1 }
{UChar16 "uchar16" 2 }
{UChar32 "uchar32" 4 }
{U8 "U8" 1 }
{U16 "U16" 2 }
{U32 "U32" 4 }
{U64 "U64" 8 }
{U128 "U128" 16 }
{U256 "U256" 32 }
{U512 "U512" 64 }
{S8 "S8" 1 }
{S16 "S16" 2 }
{S32 "S32" 4 }
{S64 "S64" 8 }
{S128 "S128" 16 }
{S256 "S256" 32 }
{S512 "S512" 64 }
{Bool "bool" 1 }
{F16 "F16" 2 }
{F32 "F32" 4 }
{F32PP "F32PP" 4 }
{F48 "F48" 6 }
{F64 "F64" 8 }
{F80 "F80" 10 }
{F128 "F128" 16 }
{ComplexF32 "ComplexF32" 8 }
{ComplexF64 "ComplexF64" 16 }
{ComplexF80 "ComplexF80" 20 }
{ComplexF128 "ComplexF128" 32 }
{Modifier "modifier" 0 }
{Ptr "ptr" 0 }
{LRef "lref" 0 }
{RRef "rref" 0 }
{Array "array" 0 }
{Function "function" 0 }
{Method "method" 0 }
{MemberPtr "member_ptr" 0 }
{Struct "struct" 0 }
{Class "class" 0 }
{Union "union" 0 }
{Enum "enum" 0 }
{Alias "typedef" 0 }
{IncompleteStruct "struct" 0 }
{IncompleteUnion "union" 0 }
{IncompleteClass "class" 0 }
{IncompleteEnum "enum" 0 }
{Bitfield "bitfield" 0 }
{Variadic "variadic" 0 }
{Collection "collection" 0 }
}
{ Cast 2 "cast" } @table(name op_kind precedence string op_pre op_sep op_pos)
{ Sizeof 1 "sizeof" } E_ExprKindTable:
{
{ Nil Null 0 "" "" "" "" }
{ Ref Null 0 "" "" "" "" }
{ Neg 1 "-" } { ArrayIndex Null 0 "[]" "" "[" "]"}
{ LogNot 1 "!" } { MemberAccess Null 0 "." "" "." "" }
{ BitNot 1 "~" } { Deref UnaryPrefix 2 "*" "*" "" "" }
{ Mul 2 "*" } { Address UnaryPrefix 2 "&" "&" "" "" }
{ Div 2 "/" }
{ Mod 2 "%" }
{ Add 2 "+" }
{ Sub 2 "-" }
{ LShift 2 "<<" }
{ RShift 2 ">>" }
{ Less 2 "<" }
{ LsEq 2 "<=" }
{ Grtr 2 ">" }
{ GrEq 2 ">=" }
{ EqEq 2 "==" }
{ NtEq 2 "!=" }
{ BitAnd 2 "&" } { Cast Null 1 "cast" "(" ")" "" }
{ BitXor 2 "^" } { Sizeof UnaryPrefix 1 "sizeof" "sizeof" "(" ")"}
{ BitOr 2 "|" } { Typeof UnaryPrefix 1 "typeof" "typeof" "(" ")"}
{ LogAnd 2 "&&" } { ByteSwap UnaryPrefix 1 "bswap" "bswap" "(" ")"}
{ LogOr 2 "||" }
{ Ternary 3 "? " } { Pos UnaryPrefix 2 "+" "+" "" "" }
{ Neg UnaryPrefix 2 "-" "-" "" "" }
{ LogNot UnaryPrefix 2 "!" "!" "" "" }
{ BitNot UnaryPrefix 2 "~" "~" "" "" }
{ Mul Binary 3 "*" "" "*" "" }
{ Div Binary 3 "/" "" "/" "" }
{ Mod Binary 3 "%" "" "%" "" }
{ Add Binary 4 "+" "" "+" "" }
{ Sub Binary 4 "-" "" "-" "" }
{ LShift Binary 5 "<<" "" "<<" "" }
{ RShift Binary 5 ">>" "" ">>" "" }
{ Less Binary 6 "<" "" "<" "" }
{ LsEq Binary 6 "<=" "" "<=" "" }
{ Grtr Binary 6 ">" "" ">" "" }
{ GrEq Binary 6 ">=" "" ">=" "" }
{ EqEq Binary 7 "==" "" "==" "" }
{ NtEq Binary 7 "!=" "" "!=" "" }
{ LeafBytecode 0 "bytecode" } { BitAnd Binary 8 "&" "" "&" "" }
{ LeafMember 0 "member" } { BitXor Binary 9 "^" "" "^" "" }
{ LeafU64 0 "U64" } { BitOr Binary 10 "|" "" "|" "" }
{ LeafF64 0 "F64" } { LogAnd Binary 11 "&&" "" "&&" "" }
{ LeafF32 0 "F32" } { LogOr Binary 12 "||" "" "||" "" }
{ TypeIdent 0 "type_ident" } { Ternary Null 0 "? " "" "?" ":"}
{ Ptr 1 "ptr" }
{ Array 2 "array" }
{ Func 1 "function" }
{ Define 2 "=" } { LeafBytecode Null 0 "bytecode" "" "" "" }
{ LeafIdent 0 "leaf_ident" } { LeafMember Null 0 "member" "" "" "" }
{ LeafStringLiteral Null 0 "string_literal" "" "" "" }
{ LeafBool Null 0 "B32" "" "" "" }
{ LeafU64 Null 0 "U64" "" "" "" }
{ LeafF64 Null 0 "F64" "" "" "" }
{ LeafF32 Null 0 "F32" "" "" "" }
{ LeafIdent Null 0 "leaf_ident" "" "" "" }
{ LeafOffset Null 0 "leaf_offset" "" "" "" }
{ LeafFilePath Null 0 "leaf_filepath" "" "" "" }
{ TypeIdent Null 0 "type_ident" "" "" "" }
{ Ptr Null 0 "ptr" "" "" "" }
{ Array Null 0 "array" "" "" "" }
{ Func Null 0 "function" "" "" "" }
{ Define Binary 13 "=" "" "=" "" }
} }
@table(name display_string) @table(name display_string)
EVAL_ResultCodeTable: E_InterpretationCodeTable:
{ {
{ Good "" } { Good "" }
{ DivideByZero "Cannot divide by zero." } { DivideByZero "Cannot divide by zero." }
@@ -72,35 +151,68 @@ EVAL_ResultCodeTable:
{ MalformedBytecode "Malformed bytecode." } { MalformedBytecode "Malformed bytecode." }
} }
@enum(U32) EVAL_ExprKind: @enum E_TokenKind:
{ {
@expand(EVAL_ExprKindTable a) `$(a.name)`, @expand(E_TokenKindTable a) `$(a.name)`,
COUNT, COUNT,
} }
@enum EVAL_ResultCode: @enum E_TypeKind:
{ {
@expand(EVAL_ResultCodeTable a) `$(a.name)`, @expand(E_TypeKindTable a) `$(a.name)`,
COUNT,
`FirstBasic = E_TypeKind_Void`,
`LastBasic = E_TypeKind_ComplexF128`,
`FirstInteger = E_TypeKind_Char8`,
`LastInteger = E_TypeKind_S512`,
`FirstSigned1 = E_TypeKind_Char8`,
`LastSigned1 = E_TypeKind_Char32`,
`FirstSigned2 = E_TypeKind_S8`,
`LastSigned2 = E_TypeKind_S512`,
`FirstIncomplete = E_TypeKind_IncompleteStruct`,
`LastIncomplete = E_TypeKind_IncompleteEnum`,
}
@enum(U32) E_ExprKind:
{
@expand(E_ExprKindTable a) `$(a.name)`,
COUNT, COUNT,
} }
@data(U8) eval_expr_kind_child_counts: @enum E_InterpretationCode:
{ {
@expand(EVAL_ExprKindTable a) `$(a.num_children)` @expand(E_InterpretationCodeTable a) `$(a.name)`,
COUNT,
} }
@data(String8) @data(String8)
eval_expr_kind_strings: e_token_kind_strings:
{ {
@expand(EVAL_ExprKindTable a) `str8_lit_comp("$(a.name)")` @expand(E_TokenKindTable a) `str8_lit_comp("$(a.name)")`
} }
@data(String8) eval_result_code_display_strings: @data(String8)
e_expr_kind_strings:
{ {
@expand(EVAL_ResultCodeTable a) `str8_lit_comp("$(a.display_string)")` @expand(E_ExprKindTable a) `str8_lit_comp("$(a.name)")`
} }
@data(String8) eval_expr_op_strings: @data(String8) e_interpretation_code_display_strings:
{ {
@expand(EVAL_ExprKindTable a) `str8_lit_comp("$(a.op_string)")` @expand(E_InterpretationCodeTable a) `str8_lit_comp("$(a.display_string)")`
}
@data(E_OpInfo) e_expr_kind_op_info_table:
{
@expand(E_ExprKindTable a) `{ E_OpKind_$(a.op_kind), $(a.precedence), str8_lit_comp("$(a.op_pre)"), str8_lit_comp("$(a.op_sep)"), str8_lit_comp("$(a.op_pos)") }`
}
@data(U8) e_kind_basic_byte_size_table:
{
@expand(E_TypeKindTable a) `$(a.basic_byte_size)`;
}
@data(String8) e_kind_basic_string_table:
{
@expand(E_TypeKindTable a) `str8_lit_comp("$(a.basic_string)")`;
} }
+260
View File
@@ -0,0 +1,260 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Bundled Evaluation Functions
internal E_Eval
e_eval_from_expr(Arena *arena, E_Expr *expr)
{
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(arena, expr);
E_OpList oplist = e_oplist_from_irtree(arena, irtree.root);
String8 bytecode = e_bytecode_from_oplist(arena, &oplist);
E_Interpretation interp = e_interpret(bytecode);
E_Eval eval =
{
.value = interp.value,
.mode = irtree.mode,
.space = irtree.space,
.expr = expr,
.type_key = irtree.type_key,
.code = interp.code,
};
e_msg_list_concat_in_place(&eval.msgs, &irtree.msgs);
if(E_InterpretationCode_Good < eval.code && eval.code < E_InterpretationCode_COUNT)
{
e_msg(arena, &eval.msgs, E_MsgKind_InterpretationError, 0, e_interpretation_code_display_strings[eval.code]);
}
return eval;
}
internal E_Eval
e_eval_from_string(Arena *arena, String8 string)
{
E_TokenArray tokens = e_token_array_from_text(arena, string);
E_Parse parse = e_parse_expr_from_text_tokens(arena, string, &tokens);
E_Eval eval = e_eval_from_expr(arena, parse.expr);
e_msg_list_concat_in_place(&eval.msgs, &parse.msgs);
return eval;
}
internal E_Eval
e_autoresolved_eval_from_eval(E_Eval eval)
{
if(e_parse_ctx &&
e_interpret_ctx &&
e_parse_ctx->modules_count > 0 &&
e_interpret_ctx->module_base != 0 &&
(e_type_key_match(eval.type_key, e_type_key_basic(E_TypeKind_S64)) ||
e_type_key_match(eval.type_key, e_type_key_basic(E_TypeKind_U64)) ||
e_type_key_match(eval.type_key, e_type_key_basic(E_TypeKind_S32)) ||
e_type_key_match(eval.type_key, e_type_key_basic(E_TypeKind_U32))))
{
U64 vaddr = eval.value.u64;
U64 voff = vaddr - e_interpret_ctx->module_base[0];
RDI_Parsed *rdi = e_parse_ctx->primary_module->rdi;
RDI_Scope *scope = rdi_scope_from_voff(rdi, voff);
RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, voff);
RDI_GlobalVariable *gvar = rdi_global_variable_from_voff(rdi, voff);
U32 string_idx = 0;
if(string_idx == 0) { string_idx = procedure->name_string_idx; }
if(string_idx == 0) { string_idx = gvar->name_string_idx; }
if(string_idx != 0)
{
eval.type_key = e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, e_type_key_basic(E_TypeKind_Void), 0);
}
}
return eval;
}
internal E_Eval
e_dynamically_typed_eval_from_eval(E_Eval eval)
{
E_TypeKey type_key = eval.type_key;
E_TypeKind type_kind = e_type_kind_from_key(type_key);
if(e_type_state != 0 &&
e_interpret_ctx != 0 &&
e_interpret_ctx->space_read != 0 &&
e_interpret_ctx->module_base != 0 &&
type_kind == E_TypeKind_Ptr)
{
Temp scratch = scratch_begin(0, 0);
E_TypeKey ptee_type_key = e_type_unwrap(e_type_direct_from_key(e_type_unwrap(type_key)));
E_TypeKind ptee_type_kind = e_type_kind_from_key(ptee_type_key);
if(ptee_type_kind == E_TypeKind_Struct || ptee_type_kind == E_TypeKind_Class)
{
E_Type *ptee_type = e_type_from_key(scratch.arena, ptee_type_key);
B32 has_vtable = 0;
for(U64 idx = 0; idx < ptee_type->count; idx += 1)
{
if(ptee_type->members[idx].kind == E_MemberKind_VirtualMethod)
{
has_vtable = 1;
break;
}
}
if(has_vtable)
{
U64 ptr_vaddr = eval.value.u64;
U64 addr_size = e_type_byte_size_from_key(e_type_unwrap(type_key));
U64 class_base_vaddr = 0;
U64 vtable_vaddr = 0;
if(e_space_read(eval.space, &class_base_vaddr, r1u64(ptr_vaddr, ptr_vaddr+addr_size)) &&
e_space_read(eval.space, &vtable_vaddr, r1u64(class_base_vaddr, class_base_vaddr+addr_size)))
{
Arch arch = e_type_state->ctx->primary_module->arch;
U32 rdi_idx = 0;
RDI_Parsed *rdi = 0;
U64 module_base = 0;
for(U64 idx = 0; idx < e_type_state->ctx->modules_count; idx += 1)
{
if(contains_1u64(e_type_state->ctx->modules[idx].vaddr_range, vtable_vaddr))
{
arch = e_type_state->ctx->modules[idx].arch;
rdi_idx = (U32)idx;
rdi = e_type_state->ctx->modules[idx].rdi;
module_base = e_type_state->ctx->modules[idx].vaddr_range.min;
break;
}
}
if(rdi != 0)
{
U64 vtable_voff = vtable_vaddr - module_base;
U64 global_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_GlobalVMap, vtable_voff);
RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, global_idx);
if(global_var->link_flags & RDI_LinkFlag_TypeScoped)
{
RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, global_var->container_idx);
RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx);
E_TypeKey derived_type_key = e_type_key_ext(e_type_kind_from_rdi(type->kind), udt->self_type_idx, rdi_idx);
E_TypeKey ptr_to_derived_type_key = e_type_key_cons_ptr(arch, derived_type_key, 0);
eval.type_key = ptr_to_derived_type_key;
}
}
}
}
}
scratch_end(scratch);
}
return eval;
}
internal E_Eval
e_value_eval_from_eval(E_Eval eval)
{
ProfBeginFunction();
if(eval.mode == E_Mode_Offset)
{
E_TypeKey type_key = e_type_unwrap(eval.type_key);
E_TypeKind type_kind = e_type_kind_from_key(type_key);
if(type_kind == E_TypeKind_Array)
{
eval.mode = E_Mode_Value;
}
else
{
U64 type_byte_size = e_type_byte_size_from_key(type_key);
Rng1U64 value_vaddr_range = r1u64(eval.value.u64, eval.value.u64 + type_byte_size);
MemoryZeroStruct(&eval.value);
if(!e_type_key_match(type_key, e_type_key_zero()) &&
type_byte_size <= sizeof(E_Value) &&
e_space_read(eval.space, &eval.value, value_vaddr_range))
{
eval.mode = E_Mode_Value;
// rjf: mask&shift, for bitfields
if(type_kind == E_TypeKind_Bitfield && type_byte_size <= sizeof(U64))
{
Temp scratch = scratch_begin(0, 0);
E_Type *type = e_type_from_key(scratch.arena, type_key);
U64 valid_bits_mask = 0;
for(U64 idx = 0; idx < type->count; idx += 1)
{
valid_bits_mask |= (1ull<<idx);
}
eval.value.u64 = eval.value.u64 >> type->off;
eval.value.u64 = eval.value.u64 & valid_bits_mask;
eval.type_key = type->direct_type_key;
scratch_end(scratch);
}
// rjf: manually sign-extend
switch(type_kind)
{
default: break;
case E_TypeKind_Char8:
case E_TypeKind_S8: {eval.value.s64 = (S64)*((S8 *)&eval.value.u64);}break;
case E_TypeKind_Char16:
case E_TypeKind_S16: {eval.value.s64 = (S64)*((S16 *)&eval.value.u64);}break;
case E_TypeKind_Char32:
case E_TypeKind_S32: {eval.value.s64 = (S64)*((S32 *)&eval.value.u64);}break;
}
}
}
}
ProfEnd();
return eval;
}
internal E_Eval
e_element_eval_from_array_eval_index(E_Eval eval, U64 index)
{
E_Eval result = {0};
result.mode = eval.mode;
result.space = eval.space;
result.type_key = e_type_direct_from_key(eval.type_key);
result.code = eval.code;
result.msgs = eval.msgs;
U64 element_size = e_type_byte_size_from_key(result.type_key);
switch(eval.mode)
{
default:{}break;
case E_Mode_Value:
if(element_size <= sizeof(E_Value) &&
index < sizeof(E_Value)/element_size)
{
MemoryCopy((U8 *)(&result.value.u512[0]),
(U8 *)(&eval.value.u512[0]) + index*element_size,
element_size);
}break;
case E_Mode_Offset:
{
result.value.u64 = eval.value.u64 + element_size*index;
}break;
}
return result;
}
internal E_Eval
e_member_eval_from_eval_member_name(E_Eval eval, String8 member_name)
{
E_Eval result = {0};
{
E_Member member = e_type_member_from_key_name__cached(eval.type_key, member_name);
if(member.kind != E_MemberKind_Null)
{
result.mode = eval.mode;
result.space = eval.space;
result.type_key = member.type_key;
result.code = eval.code;
result.msgs = eval.msgs;
switch(eval.mode)
{
default:{}break;
case E_Mode_Value:
if(member.off < sizeof(eval.value))
{
U64 member_size = e_type_byte_size_from_key(member.type_key);
MemoryCopy((U8 *)(&result.value.u512[0]),
(U8 *)(&eval.value.u512[0]) + member.off,
Min(member_size, sizeof(eval.value) - member.off));
}break;
case E_Mode_Offset:
{
result.value.u64 = eval.value.u64 + member.off;
}break;
}
}
}
return result;
}
+33
View File
@@ -0,0 +1,33 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef EVAL_BUNDLES_H
#define EVAL_BUNDLES_H
////////////////////////////////
//~ rjf: Bundled Evaluation Path Types
typedef struct E_Eval E_Eval;
struct E_Eval
{
E_Value value;
E_Mode mode;
E_Space space;
E_Expr *expr;
E_TypeKey type_key;
E_InterpretationCode code;
E_MsgList msgs;
};
////////////////////////////////
//~ rjf: Bundled Evaluation Functions
internal E_Eval e_eval_from_expr(Arena *arena, E_Expr *expr);
internal E_Eval e_eval_from_string(Arena *arena, String8 string);
internal E_Eval e_autoresolved_eval_from_eval(E_Eval eval);
internal E_Eval e_dynamically_typed_eval_from_eval(E_Eval eval);
internal E_Eval e_value_eval_from_eval(E_Eval eval);
internal E_Eval e_element_eval_from_array_eval_index(E_Eval eval, U64 index);
internal E_Eval e_member_eval_from_eval_member_name(E_Eval eval, String8 member_name);
#endif // EVAL_BUNDLES_H
File diff suppressed because it is too large Load Diff
-82
View File
@@ -1,82 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef EVAL_COMPILER_H
#define EVAL_COMPILER_H
////////////////////////////////
//~ allen: EVAL Bytecode Helpers
internal String8 eval_bytecode_from_oplist(Arena *arena, EVAL_OpList *list);
internal void eval_oplist_push_op(Arena *arena, EVAL_OpList *list, RDI_EvalOp op, U64 p);
internal void eval_oplist_push_uconst(Arena *arena, EVAL_OpList *list, U64 x);
internal void eval_oplist_push_sconst(Arena *arena, EVAL_OpList *list, S64 x);
internal void eval_oplist_push_bytecode(Arena *arena, EVAL_OpList *list, String8 bytecode);
internal void eval_oplist_concat_in_place(EVAL_OpList *left_dst, EVAL_OpList *right_destroyed);
////////////////////////////////
//~ allen: EVAL Expression Info Functions
internal RDI_EvalOp eval_opcode_from_expr_kind(EVAL_ExprKind kind);
internal B32 eval_expr_kind_is_comparison(EVAL_ExprKind kind);
////////////////////////////////
//~ allen: EVAL Expression Constructors
internal EVAL_Expr* eval_expr(Arena *arena, EVAL_ExprKind kind, void *location, EVAL_Expr *c0, EVAL_Expr *c1, EVAL_Expr *c2);
internal EVAL_Expr* eval_expr_u64(Arena *arena, void *location, U64 u64);
internal EVAL_Expr* eval_expr_f64(Arena *arena, void *location, F64 f64);
internal EVAL_Expr* eval_expr_f32(Arena *arena, void *location, F32 f32);
internal EVAL_Expr* eval_expr_child_and_u64(Arena *arena, EVAL_ExprKind kind, void *location, EVAL_Expr *child, U64 u64);
internal EVAL_Expr* eval_expr_leaf_member(Arena *arena, void *location, String8 name);
internal EVAL_Expr* eval_expr_leaf_ident(Arena *arena, void *location, String8 name);
internal EVAL_Expr* eval_expr_leaf_bytecode(Arena *arena, void *location, TG_Key type_key, String8 bytecode, EVAL_EvalMode mode);
internal EVAL_Expr* eval_expr_leaf_op_list(Arena *arena, void *location, TG_Key type_key, EVAL_OpList *ops, EVAL_EvalMode mode);
internal EVAL_Expr* eval_expr_leaf_type(Arena *arena, void *location, TG_Key type_key);
////////////////////////////////
//~ allen: EVAL Type Information Transformers
internal RDI_EvalTypeGroup eval_type_group_from_kind(TG_Kind kind);
internal TG_Key eval_type_unwrap_enum(TG_Graph *graph, RDI_Parsed *rdi, TG_Key key);
internal TG_Key eval_type_promote(TG_Graph *graph, RDI_Parsed *rdi, TG_Key key);
internal TG_Key eval_type_coerce(TG_Graph *graph, RDI_Parsed *rdi, TG_Key l, TG_Key r);
internal B32 eval_type_match(TG_Graph *graph, RDI_Parsed *rdi, TG_Key l, TG_Key r);
internal B32 eval_kind_is_integer(TG_Kind kind);
internal B32 eval_kind_is_signed(TG_Kind kind);
internal B32 eval_kind_is_basic_or_enum(TG_Kind kind);
////////////////////////////////
//~ allen: EVAL IR-Tree Constructors
internal EVAL_IRTree* eval_irtree_const_u(Arena *arena, U64 v);
internal EVAL_IRTree* eval_irtree_unary_op(Arena *arena, RDI_EvalOp op, RDI_EvalTypeGroup group, EVAL_IRTree *c);
internal EVAL_IRTree* eval_irtree_binary_op(Arena *arena, RDI_EvalOp op, RDI_EvalTypeGroup group, EVAL_IRTree *l, EVAL_IRTree *r);
internal EVAL_IRTree* eval_irtree_binary_op_u(Arena *arena, RDI_EvalOp op, EVAL_IRTree *l, EVAL_IRTree *r);
internal EVAL_IRTree* eval_irtree_conditional(Arena *arena, EVAL_IRTree *c, EVAL_IRTree *l, EVAL_IRTree *r);
internal EVAL_IRTree* eval_irtree_bytecode_no_copy(Arena *arena, String8 bytecode);
////////////////////////////////
//~ allen: EVAL IR-Tree High Level Helpers
internal EVAL_IRTree* eval_irtree_mem_read_type(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, EVAL_IRTree *c, TG_Key type_key);
internal EVAL_IRTree* eval_irtree_convert_lo(Arena *arena, EVAL_IRTree *c, RDI_EvalTypeGroup out, RDI_EvalTypeGroup in);
internal EVAL_IRTree* eval_irtree_trunc(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, EVAL_IRTree *c, TG_Key type_key);
internal EVAL_IRTree* eval_irtree_convert_hi(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, EVAL_IRTree *c, TG_Key out, TG_Key in);
internal EVAL_IRTree* eval_irtree_resolve_to_value(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, EVAL_EvalMode from_mode, EVAL_IRTree *tree, TG_Key type_key);
////////////////////////////////
//~ allen: EVAL Compiler Phases
internal void eval_push_leaf_ident_exprs_from_expr__in_place(Arena *arena, EVAL_String2ExprMap *map, EVAL_Expr *expr, EVAL_ErrorList *eout);
internal TG_Key eval_type_from_type_expr(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, EVAL_Expr *expr, EVAL_ErrorList *eout);
internal EVAL_IRTreeAndType eval_irtree_and_type_from_expr(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, EVAL_String2ExprMap *leaf_ident_expr_map, EVAL_Expr *expr, EVAL_ErrorList *eout);
internal void eval_oplist_from_irtree(Arena *arena, EVAL_IRTree *tree, EVAL_OpList *out);
#endif //EVAL_COMPILER_H
+34 -214
View File
@@ -4,15 +4,15 @@
//////////////////////////////// ////////////////////////////////
//~ rjf: Generated Code //~ rjf: Generated Code
#include "generated/eval.meta.c" #include "eval/generated/eval.meta.c"
//////////////////////////////// ////////////////////////////////
//~ rjf: Basic Functions //~ rjf: Basic Helper Functions
internal U64 internal U64
eval_hash_from_string(String8 string) e_hash_from_string(U64 seed, String8 string)
{ {
U64 result = 5381; U64 result = seed;
for(U64 i = 0; i < string.size; i += 1) for(U64 i = 0; i < string.size; i += 1)
{ {
result = ((result << 5) + result) + string.str[i]; result = ((result << 5) + result) + string.str[i];
@@ -21,234 +21,54 @@ eval_hash_from_string(String8 string)
} }
//////////////////////////////// ////////////////////////////////
//~ rjf: Error List Building Functions //~ rjf: Message Functions
internal void internal void
eval_error(Arena *arena, EVAL_ErrorList *list, EVAL_ErrorKind kind, void *location, String8 text){ e_msg(Arena *arena, E_MsgList *msgs, E_MsgKind kind, void *location, String8 text)
EVAL_Error *error = push_array_no_zero(arena, EVAL_Error, 1); {
SLLQueuePush(list->first, list->last, error); E_Msg *msg = push_array(arena, E_Msg, 1);
list->count += 1; SLLQueuePush(msgs->first, msgs->last, msg);
list->max_kind = Max(kind, list->max_kind); msgs->count += 1;
error->kind = kind; msgs->max_kind = Max(kind, msgs->max_kind);
error->location = location; msg->kind = kind;
error->text = text; msg->location = location;
msg->text = text;
} }
internal void internal void
eval_errorf(Arena *arena, EVAL_ErrorList *list, EVAL_ErrorKind kind, void *location, char *fmt, ...){ e_msgf(Arena *arena, E_MsgList *msgs, E_MsgKind kind, void *location, char *fmt, ...)
{
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
String8 text = push_str8fv(arena, fmt, args); String8 text = push_str8fv(arena, fmt, args);
va_end(args); va_end(args);
eval_error(arena, list, kind, location, text); e_msg(arena, msgs, kind, location, text);
} }
internal void internal void
eval_error_list_concat_in_place(EVAL_ErrorList *dst, EVAL_ErrorList *to_push){ e_msg_list_concat_in_place(E_MsgList *dst, E_MsgList *to_push)
if (dst->last != 0){ {
if (to_push->last != 0){ if(dst->last != 0 && to_push->first != 0)
dst->last->next = to_push->first; {
dst->last = to_push->last; dst->last->next = to_push->first;
dst->count += to_push->count; dst->last = to_push->last;
} dst->count += to_push->count;
dst->max_kind = Max(dst->max_kind, to_push->max_kind);
} }
else{ else if(to_push->first != 0)
*dst = *to_push; {
MemoryCopyStruct(dst, to_push);
} }
MemoryZeroStruct(to_push); MemoryZeroStruct(to_push);
} }
//////////////////////////////// ////////////////////////////////
//~ rjf: Map Functions //~ rjf: Space Functions
//- rjf: string -> num internal E_Space
e_space_make(E_SpaceKind kind)
internal EVAL_String2NumMap
eval_string2num_map_make(Arena *arena, U64 slot_count)
{ {
EVAL_String2NumMap map = {0}; E_Space space = {0};
map.slots_count = slot_count; space.kind = kind;
map.slots = push_array(arena, EVAL_String2NumMapSlot, map.slots_count); return space;
return map;
}
internal void
eval_string2num_map_insert(Arena *arena, EVAL_String2NumMap *map, String8 string, U64 num)
{
U64 hash = eval_hash_from_string(string);
U64 slot_idx = hash%map->slots_count;
EVAL_String2NumMapNode *existing_node = 0;
for(EVAL_String2NumMapNode *node = map->slots[slot_idx].first; node != 0; node = node->hash_next)
{
if(str8_match(node->string, string, 0) && node->num == num)
{
existing_node = node;
break;
}
}
if(existing_node == 0)
{
EVAL_String2NumMapNode *node = push_array(arena, EVAL_String2NumMapNode, 1);
SLLQueuePush_N(map->slots[slot_idx].first, map->slots[slot_idx].last, node, hash_next);
SLLQueuePush_N(map->first, map->last, node, order_next);
node->string = push_str8_copy(arena, string);
node->num = num;
map->node_count += 1;
}
}
internal U64
eval_num_from_string(EVAL_String2NumMap *map, String8 string)
{
U64 num = 0;
if(map->slots_count != 0)
{
U64 hash = eval_hash_from_string(string);
U64 slot_idx = hash%map->slots_count;
EVAL_String2NumMapNode *existing_node = 0;
for(EVAL_String2NumMapNode *node = map->slots[slot_idx].first; node != 0; node = node->hash_next)
{
if(str8_match(node->string, string, 0))
{
existing_node = node;
break;
}
}
if(existing_node != 0)
{
num = existing_node->num;
}
}
return num;
}
internal EVAL_String2NumMapNodeArray
eval_string2num_map_node_array_from_map(Arena *arena, EVAL_String2NumMap *map)
{
EVAL_String2NumMapNodeArray result = {0};
result.count = map->node_count;
result.v = push_array(arena, EVAL_String2NumMapNode *, result.count);
U64 idx = 0;
for(EVAL_String2NumMapNode *n = map->first; n != 0; n = n->order_next, idx += 1)
{
result.v[idx] = n;
}
return result;
}
internal int
eval_string2num_map_node_qsort_compare__num_ascending(EVAL_String2NumMapNode **a, EVAL_String2NumMapNode **b)
{
int result = 0;
if(a[0]->num < b[0]->num)
{
result = -1;
}
else if(a[0]->num > b[0]->num)
{
result = +1;
}
return result;
}
internal void
eval_string2num_map_node_array_sort__in_place(EVAL_String2NumMapNodeArray *array)
{
quick_sort(array->v, array->count, sizeof(array->v[0]), eval_string2num_map_node_qsort_compare__num_ascending);
}
//- rjf: string -> expr
internal EVAL_String2ExprMap
eval_string2expr_map_make(Arena *arena, U64 slot_count)
{
EVAL_String2ExprMap map = {0};
map.slots_count = slot_count;
map.slots = push_array(arena, EVAL_String2ExprMapSlot, map.slots_count);
return map;
}
internal void
eval_string2expr_map_insert(Arena *arena, EVAL_String2ExprMap *map, String8 string, EVAL_Expr *expr)
{
U64 hash = eval_hash_from_string(string);
U64 slot_idx = hash%map->slots_count;
EVAL_String2ExprMapNode *existing_node = 0;
for(EVAL_String2ExprMapNode *node = map->slots[slot_idx].first;
node != 0;
node = node->hash_next)
{
if(str8_match(node->string, string, 0))
{
existing_node = node;
break;
}
}
if(existing_node == 0)
{
EVAL_String2ExprMapNode *node = push_array(arena, EVAL_String2ExprMapNode, 1);
SLLQueuePush_N(map->slots[slot_idx].first, map->slots[slot_idx].last, node, hash_next);
node->string = push_str8_copy(arena, string);
existing_node = node;
}
existing_node->expr = expr;
}
internal void
eval_string2expr_map_inc_poison(EVAL_String2ExprMap *map, String8 string)
{
U64 hash = eval_hash_from_string(string);
U64 slot_idx = hash%map->slots_count;
for(EVAL_String2ExprMapNode *node = map->slots[slot_idx].first;
node != 0;
node = node->hash_next)
{
if(str8_match(node->string, string, 0))
{
node->poison_count += 1;
break;
}
}
}
internal void
eval_string2expr_map_dec_poison(EVAL_String2ExprMap *map, String8 string)
{
U64 hash = eval_hash_from_string(string);
U64 slot_idx = hash%map->slots_count;
for(EVAL_String2ExprMapNode *node = map->slots[slot_idx].first;
node != 0;
node = node->hash_next)
{
if(str8_match(node->string, string, 0) && node->poison_count > 0)
{
node->poison_count -= 1;
break;
}
}
}
internal EVAL_Expr *
eval_expr_from_string(EVAL_String2ExprMap *map, String8 string)
{
EVAL_Expr *expr = &eval_expr_nil;
if(map->slots_count != 0)
{
U64 hash = eval_hash_from_string(string);
U64 slot_idx = hash%map->slots_count;
EVAL_String2ExprMapNode *existing_node = 0;
for(EVAL_String2ExprMapNode *node = map->slots[slot_idx].first; node != 0; node = node->hash_next)
{
if(str8_match(node->string, string, 0) && node->poison_count == 0)
{
existing_node = node;
break;
}
}
if(existing_node != 0)
{
expr = existing_node->expr;
}
}
return expr;
} }
+112 -183
View File
@@ -5,65 +5,134 @@
#define EVAL_CORE_H #define EVAL_CORE_H
//////////////////////////////// ////////////////////////////////
//~ rjf: Errors //~ rjf: Messages
typedef enum EVAL_ErrorKind typedef enum E_MsgKind
{ {
EVAL_ErrorKind_Null, E_MsgKind_Null,
EVAL_ErrorKind_MalformedInput, E_MsgKind_MalformedInput,
EVAL_ErrorKind_MissingInfo, E_MsgKind_MissingInfo,
EVAL_ErrorKind_ResolutionFailure, E_MsgKind_ResolutionFailure,
EVAL_ErrorKind_InterpretationError, E_MsgKind_InterpretationError,
EVAL_ErrorKind_COUNT E_MsgKind_COUNT
} }
EVAL_ErrorKind; E_MsgKind;
typedef struct EVAL_Error EVAL_Error; typedef struct E_Msg E_Msg;
struct EVAL_Error struct E_Msg
{ {
EVAL_Error *next; E_Msg *next;
EVAL_ErrorKind kind; E_MsgKind kind;
void *location; void *location;
String8 text; String8 text;
}; };
typedef struct EVAL_ErrorList EVAL_ErrorList; typedef struct E_MsgList E_MsgList;
struct EVAL_ErrorList struct E_MsgList
{ {
EVAL_Error *first; E_Msg *first;
EVAL_Error *last; E_Msg *last;
EVAL_ErrorKind max_kind; E_MsgKind max_kind;
U64 count; U64 count;
}; };
//////////////////////////////// ////////////////////////////////
//~ rjf: Operation Types //~ rjf: Register-Sized Value Type
enum typedef union E_Value E_Value;
union E_Value
{ {
EVAL_IRExtKind_Bytecode = RDI_EvalOp_COUNT, U64 u512[8];
EVAL_IRExtKind_COUNT U64 u256[4];
U128 u128;
U64 u64;
U32 u32;
U16 u16;
S64 s64;
S32 s32;
S32 s16;
F64 f64;
F32 f32;
}; };
typedef struct EVAL_Op EVAL_Op; ////////////////////////////////
struct EVAL_Op //~ rjf: Operator Info
typedef enum E_OpKind
{ {
EVAL_Op *next; E_OpKind_Null,
RDI_EvalOp opcode; E_OpKind_UnaryPrefix,
E_OpKind_Binary,
}
E_OpKind;
typedef struct E_OpInfo E_OpInfo;
struct E_OpInfo
{
E_OpKind kind;
S64 precedence;
String8 pre;
String8 sep;
String8 post;
};
////////////////////////////////
//~ rjf: Evaluation Spaces
//
// NOTE(rjf): Evaluations occur within the context of a "space". Each "space"
// refers to a different offset/address-space, but it's a bit looser of a
// concept than just address space, since it can also refer to offsets into
// a register block, and it is also used to refer to spaces of unique IDs for
// key-value stores, e.g. for information in the debugger.
//
// Effectively, when considering the result of an evaluation, you use the
// value for understanding a key *into* a space, e.g. 1+2 -> 3, in a null
// space, or &foo, in the space of PID: 1234.
typedef U64 E_SpaceKind;
enum
{
E_SpaceKind_Null,
E_SpaceKind_FileSystem,
E_SpaceKind_FirstUserDefined,
};
typedef struct E_Space E_Space;
struct E_Space
{
E_SpaceKind kind;
union union
{ {
U64 p; U64 u64s[3];
String8 bytecode; struct
{
U64 u64_0;
U128 u128;
};
}; };
}; };
typedef struct EVAL_OpList EVAL_OpList; ////////////////////////////////
struct EVAL_OpList //~ rjf: Evaluation Modes
typedef enum E_Mode
{ {
EVAL_Op *first_op; E_Mode_Null,
EVAL_Op *last_op; E_Mode_Value,
U32 op_count; E_Mode_Offset,
U32 encoded_size; }
E_Mode;
////////////////////////////////
//~ rjf: Modules
typedef struct E_Module E_Module;
struct E_Module
{
RDI_Parsed *rdi;
Rng1U64 vaddr_range;
Arch arch;
E_Space space;
}; };
//////////////////////////////// ////////////////////////////////
@@ -72,161 +141,21 @@ struct EVAL_OpList
#include "eval/generated/eval.meta.h" #include "eval/generated/eval.meta.h"
//////////////////////////////// ////////////////////////////////
//~ rjf: Expression Tree Types //~ rjf: Basic Helper Functions
typedef enum EVAL_EvalMode internal U64 e_hash_from_string(U64 seed, String8 string);
{ #define e_value_u64(v) (E_Value){.u64 = (v)}
EVAL_EvalMode_NULL,
EVAL_EvalMode_Value,
EVAL_EvalMode_Addr,
EVAL_EvalMode_Reg
}
EVAL_EvalMode;
typedef struct EVAL_Expr EVAL_Expr;
struct EVAL_Expr
{
EVAL_ExprKind kind;
void *location;
union
{
EVAL_Expr *children[3];
U32 u32;
U64 u64;
F32 f32;
F64 f64;
struct
{
EVAL_Expr *child;
U64 u64;
} child_and_constant;
String8 name;
struct
{
TG_Key type_key;
String8 bytecode;
EVAL_EvalMode mode;
};
};
};
//////////////////////////////// ////////////////////////////////
//~ rjf: IR Tree Types //~ rjf: Message Functions
typedef struct EVAL_IRTree EVAL_IRTree; internal void e_msg(Arena *arena, E_MsgList *msgs, E_MsgKind kind, void *location, String8 text);
struct EVAL_IRTree{ internal void e_msgf(Arena *arena, E_MsgList *msgs, E_MsgKind kind, void *location, char *fmt, ...);
RDI_EvalOp op; internal void e_msg_list_concat_in_place(E_MsgList *dst, E_MsgList *to_push);
EVAL_IRTree *children[3];
union{
U64 p;
String8 bytecode;
};
};
typedef struct EVAL_IRTreeAndType EVAL_IRTreeAndType;
struct EVAL_IRTreeAndType{
EVAL_IRTree *tree;
TG_Key type_key;
EVAL_EvalMode mode;
};
//////////////////////////////// ////////////////////////////////
//~ rjf: Map Types //~ rjf: Space Functions
//- rjf: string -> num internal E_Space e_space_make(E_SpaceKind kind);
typedef struct EVAL_String2NumMapNode EVAL_String2NumMapNode;
struct EVAL_String2NumMapNode
{
EVAL_String2NumMapNode *order_next;
EVAL_String2NumMapNode *hash_next;
String8 string;
U64 num;
};
typedef struct EVAL_String2NumMapNodeArray EVAL_String2NumMapNodeArray;
struct EVAL_String2NumMapNodeArray
{
EVAL_String2NumMapNode **v;
U64 count;
};
typedef struct EVAL_String2NumMapSlot EVAL_String2NumMapSlot;
struct EVAL_String2NumMapSlot
{
EVAL_String2NumMapNode *first;
EVAL_String2NumMapNode *last;
};
typedef struct EVAL_String2NumMap EVAL_String2NumMap;
struct EVAL_String2NumMap
{
U64 slots_count;
U64 node_count;
EVAL_String2NumMapSlot *slots;
EVAL_String2NumMapNode *first;
EVAL_String2NumMapNode *last;
};
//- rjf: string -> expr
typedef struct EVAL_String2ExprMapNode EVAL_String2ExprMapNode;
struct EVAL_String2ExprMapNode
{
EVAL_String2ExprMapNode *hash_next;
String8 string;
EVAL_Expr *expr;
U64 poison_count;
};
typedef struct EVAL_String2ExprMapSlot EVAL_String2ExprMapSlot;
struct EVAL_String2ExprMapSlot
{
EVAL_String2ExprMapNode *first;
EVAL_String2ExprMapNode *last;
};
typedef struct EVAL_String2ExprMap EVAL_String2ExprMap;
struct EVAL_String2ExprMap
{
U64 slots_count;
EVAL_String2ExprMapSlot *slots;
};
////////////////////////////////
//~ rjf: Globals
global read_only EVAL_Expr eval_expr_nil = {0};
global read_only EVAL_IRTree eval_irtree_nil = {0};
////////////////////////////////
//~ rjf: Basic Functions
internal U64 eval_hash_from_string(String8 string);
////////////////////////////////
//~ rjf: Error List Building Functions
internal void eval_error(Arena *arena, EVAL_ErrorList *list, EVAL_ErrorKind kind, void *location, String8 text);
internal void eval_errorf(Arena *arena, EVAL_ErrorList *list, EVAL_ErrorKind kind, void *location, char *fmt, ...);
internal void eval_error_list_concat_in_place(EVAL_ErrorList *dst, EVAL_ErrorList *to_push);
////////////////////////////////
//~ rjf: Map Functions
//- rjf: string -> num
internal EVAL_String2NumMap eval_string2num_map_make(Arena *arena, U64 slot_count);
internal void eval_string2num_map_insert(Arena *arena, EVAL_String2NumMap *map, String8 string, U64 num);
internal U64 eval_num_from_string(EVAL_String2NumMap *map, String8 string);
internal EVAL_String2NumMapNodeArray eval_string2num_map_node_array_from_map(Arena *arena, EVAL_String2NumMap *map);
internal int eval_string2num_map_node_qsort_compare__num_ascending(EVAL_String2NumMapNode **a, EVAL_String2NumMapNode **b);
internal void eval_string2num_map_node_array_sort__in_place(EVAL_String2NumMapNodeArray *array);
//- rjf: string -> expr
internal EVAL_String2ExprMap eval_string2expr_map_make(Arena *arena, U64 slot_count);
internal void eval_string2expr_map_insert(Arena *arena, EVAL_String2ExprMap *map, String8 string, EVAL_Expr *expr);
internal void eval_string2expr_map_inc_poison(EVAL_String2ExprMap *map, String8 string);
internal void eval_string2expr_map_dec_poison(EVAL_String2ExprMap *map, String8 string);
internal EVAL_Expr *eval_expr_from_string(EVAL_String2ExprMap *map, String8 string);
#endif // EVAL_CORE_H #endif // EVAL_CORE_H
-50
View File
@@ -1,50 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
// NOTE(allen): Eval Decode Function
internal void
eval_print_decode_from_bytecode(FILE *out, String8 bytecode){
U8 *ptr = bytecode.str;
U8 *opl = bytecode.str + bytecode.size;
for (;ptr < opl;){
// consume opcode
SYMS_EvalOp op = (SYMS_EvalOp)*ptr;
if (op >= SYMS_EvalOp_COUNT){
fprintf(out, "decode error: undefined op code\n");
goto done;
}
U8 ctrlbits = syms_eval_opcode_ctrlbits[op];
ptr += 1;
// decode
U64 imm = 0;
U32 decode_size = (ctrlbits >> SYMS_EvalOpCtrlBits_DecodeShft)&SYMS_EvalOpCtrlBits_DecodeMask;
{
U8 *next_ptr = ptr + decode_size;
if (next_ptr > opl){
fprintf(out, "decode error: expected constant goes past the end of bytecode\n");
goto done;
}
// TODO(allen): to improve this:
// gaurantee 8 bytes padding after the end of serialized bytecode
// read 8 bytes and mask
switch (decode_size){
case 1: imm = *ptr; break;
case 2: imm = *(U16*)ptr; break;
case 4: imm = *(U32*)ptr; break;
case 8: imm = *(U64*)ptr; break;
}
ptr = next_ptr;
}
// op string & control bits
SYMS_String8 op_string = syms_eval_opcode_strings[op];
// print
fprintf(out, "%.*s 0x%llx\n", str8_varg(op_string), imm);
}
done:;
}
-12
View File
@@ -1,12 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef EVAL_DECODE_H
#define EVAL_DECODE_H
////////////////////////////////
// NOTE(allen): Eval Decode Function
internal void eval_print_decode_from_bytecode(FILE *out, String8 bytecode);
#endif //EVAL_DECODE_H
+5 -3
View File
@@ -2,6 +2,8 @@
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
#include "eval/eval_core.c" #include "eval/eval_core.c"
#include "eval/eval_compiler.c" #include "eval/eval_types.c"
#include "eval/eval_machine.c" #include "eval/eval_parse.c"
#include "eval/eval_parser.c" #include "eval/eval_ir.c"
#include "eval/eval_interpret.c"
#include "eval/eval_bundles.c"
+5 -3
View File
@@ -5,8 +5,10 @@
#define EVAL_INC_H #define EVAL_INC_H
#include "eval/eval_core.h" #include "eval/eval_core.h"
#include "eval/eval_compiler.h" #include "eval/eval_types.h"
#include "eval/eval_machine.h" #include "eval/eval_parse.h"
#include "eval/eval_parser.h" #include "eval/eval_ir.h"
#include "eval/eval_interpret.h"
#include "eval/eval_bundles.h"
#endif // EVAL_INC_H #endif // EVAL_INC_H
+817
View File
@@ -0,0 +1,817 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Context Selection Functions (Selection Required For All Subsequent APIs)
internal E_InterpretCtx *
e_selected_interpret_ctx(void)
{
return e_interpret_ctx;
}
internal void
e_select_interpret_ctx(E_InterpretCtx *ctx)
{
e_interpret_ctx = ctx;
}
////////////////////////////////
//~ rjf: Space Reading Helpers
internal B32
e_space_read(E_Space space, void *out, Rng1U64 range)
{
ProfBeginFunction();
B32 result = 0;
if(e_interpret_ctx->space_read != 0)
{
result = e_interpret_ctx->space_read(e_interpret_ctx->space_rw_user_data, space, out, range);
}
ProfEnd();
return result;
}
internal B32
e_space_write(E_Space space, void *in, Rng1U64 range)
{
ProfBeginFunction();
B32 result = 0;
if(e_interpret_ctx->space_write != 0)
{
result = e_interpret_ctx->space_write(e_interpret_ctx->space_rw_user_data, space, in, range);
}
ProfEnd();
return result;
}
////////////////////////////////
//~ rjf: Interpretation Functions
internal E_Interpretation
e_interpret(String8 bytecode)
{
E_Interpretation result = {0};
Temp scratch = scratch_begin(0, 0);
//- rjf: allocate stack & "registers"
U64 stack_cap = 128; // TODO(rjf): scan bytecode; determine maximum stack depth
E_Value *stack = push_array_no_zero(scratch.arena, E_Value, stack_cap);
U64 stack_count = 0;
E_Space selected_space = e_interpret_ctx->primary_space;
//- rjf: iterate bytecode & perform ops
U8 *ptr = bytecode.str;
U8 *opl = bytecode.str + bytecode.size;
for(;ptr < opl;)
{
// rjf: consume next opcode
RDI_EvalOp op = (RDI_EvalOp)*ptr;
U16 ctrlbits = 0;
if(op < RDI_EvalOp_COUNT)
{
ctrlbits = rdi_eval_op_ctrlbits_table[op];
}
else switch(op)
{
case E_IRExtKind_SetSpace:{ctrlbits = RDI_EVAL_CTRLBITS(32, 0, 0);}break;
default:
{
result.code = E_InterpretationCode_BadOp;
goto done;
}break;
}
ptr += 1;
// rjf: decode
E_Value imm = {0};
{
U32 decode_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits);
U8 *next_ptr = ptr + decode_size;
if(next_ptr > opl)
{
result.code = E_InterpretationCode_BadOp;
goto done;
}
// TODO(rjf): guarantee 8 bytes padding after the end of serialized
// bytecode; read 8 bytes and mask
MemoryCopy(&imm, ptr, decode_size);
ptr = next_ptr;
}
// rjf: pop
E_Value *svals = 0;
{
U32 pop_count = RDI_POPN_FROM_CTRLBITS(ctrlbits);
if(pop_count > stack_count)
{
result.code = E_InterpretationCode_BadOp;
goto done;
}
if(pop_count <= stack_count)
{
stack_count -= pop_count;
svals = stack + stack_count;
}
}
// rjf: interpret op, given decodes/pops
E_Value nval = {0};
switch(op)
{
case E_IRExtKind_SetSpace:
{
MemoryCopy(&selected_space, &imm, sizeof(selected_space));
}break;
case RDI_EvalOp_Stop:
{
goto done;
}break;
case RDI_EvalOp_Noop:
{
// do nothing
}break;
case RDI_EvalOp_Cond:
if(svals[0].u64)
{
ptr += imm.u64;
}break;
case RDI_EvalOp_Skip:
{
ptr += imm.u64;
}break;
case RDI_EvalOp_MemRead:
{
U64 addr = svals[0].u64;
U64 size = imm.u64;
B32 good_read = e_space_read(selected_space, &nval, r1u64(addr, addr+size));
if(!good_read)
{
result.code = E_InterpretationCode_BadMemRead;
goto done;
}
}break;
case RDI_EvalOp_RegRead:
{
U8 rdi_reg_code = (imm.u64&0x0000FF)>>0;
U8 byte_size = (imm.u64&0x00FF00)>>8;
U8 byte_off = (imm.u64&0xFF0000)>>16;
REGS_RegCode base_reg_code = regs_reg_code_from_arch_rdi_code(e_interpret_ctx->reg_arch, rdi_reg_code);
REGS_Rng rng = regs_reg_code_rng_table_from_arch(e_interpret_ctx->reg_arch)[base_reg_code];
U64 off = (U64)rng.byte_off + byte_off;
U64 size = (U64)byte_size;
B32 good_read = e_space_read(e_interpret_ctx->reg_space, &nval, r1u64(off, off+size));
if(!good_read)
{
result.code = E_InterpretationCode_BadRegRead;
goto done;
}
}break;
case RDI_EvalOp_RegReadDyn:
{
U64 off = svals[0].u64;
U64 size = bit_size_from_arch(e_interpret_ctx->reg_arch)/8;
B32 good_read = e_space_read(e_interpret_ctx->reg_space, &nval, r1u64(off, off+size));
if(!good_read)
{
result.code = E_InterpretationCode_BadRegRead;
goto done;
}
}break;
case RDI_EvalOp_FrameOff:
{
if(e_interpret_ctx->frame_base != 0)
{
nval.u64 = *e_interpret_ctx->frame_base + imm.u64;
}
else
{
result.code = E_InterpretationCode_BadFrameBase;
goto done;
}
}break;
case RDI_EvalOp_ModuleOff:
{
if(e_interpret_ctx->module_base != 0)
{
nval.u64 = *e_interpret_ctx->module_base + imm.u64;
}
else
{
result.code = E_InterpretationCode_BadModuleBase;
goto done;
}
}break;
case RDI_EvalOp_TLSOff:
{
if(e_interpret_ctx->tls_base != 0)
{
nval.u64 = *e_interpret_ctx->tls_base + imm.u64;
}
else
{
result.code = E_InterpretationCode_BadTLSBase;
goto done;
}
}break;
case RDI_EvalOp_ConstU8:
case RDI_EvalOp_ConstU16:
case RDI_EvalOp_ConstU32:
case RDI_EvalOp_ConstU64:
case RDI_EvalOp_ConstU128:
{
nval = imm;
}break;
case RDI_EvalOp_ConstString:
{
MemoryCopy(&nval, ptr, imm.u64);
ptr += imm.u64;
}break;
case RDI_EvalOp_Abs:
{
if(imm.u64 == RDI_EvalTypeGroup_F32)
{
nval.f32 = svals[0].f32;
if(svals[0].f32 < 0)
{
nval.f32 = -svals[0].f32;
}
}
else if(imm.u64 == RDI_EvalTypeGroup_F64)
{
nval.f64 = svals[0].f64;
if(svals[0].f64 < 0)
{
nval.f64 = -svals[0].f64;
}
}
else
{
nval.s64 = svals[0].s64;
if(svals[0].s64 < 0)
{
nval.s64 = -svals[0].s64;
}
}
}break;
case RDI_EvalOp_Neg:
{
if(imm.u64 == RDI_EvalTypeGroup_F32)
{
nval.f32 = -svals[0].f32;
}
else if(imm.u64 == RDI_EvalTypeGroup_F64)
{
nval.f64 = -svals[0].f64;
}
else
{
nval.u64 = (~svals[0].u64) + 1;
}
}break;
case RDI_EvalOp_Add:
{
if(imm.u64 == RDI_EvalTypeGroup_F32)
{
nval.f32 = svals[0].f32 + svals[1].f32;
}
else if(imm.u64 == RDI_EvalTypeGroup_F64)
{
nval.f64 = svals[0].f64 + svals[1].f64;
}
else
{
nval.u64 = svals[0].u64 + svals[1].u64;
}
}break;
case RDI_EvalOp_Sub:
{
if(imm.u64 == RDI_EvalTypeGroup_F32)
{
nval.f32 = svals[0].f32 - svals[1].f32;
}
else if(imm.u64 == RDI_EvalTypeGroup_F64)
{
nval.f64 = svals[0].f64 - svals[1].f64;
}
else
{
nval.u64 = svals[0].u64 - svals[1].u64;
}
}break;
case RDI_EvalOp_Mul:
{
if(imm.u64 == RDI_EvalTypeGroup_F32)
{
nval.f32 = svals[0].f32*svals[1].f32;
}
else if(imm.u64 == RDI_EvalTypeGroup_F64)
{
nval.f64 = svals[0].f64*svals[1].f64;
}
else
{
nval.u64 = svals[0].u64*svals[1].u64;
}
}break;
case RDI_EvalOp_Div:
{
if(imm.u64 == RDI_EvalTypeGroup_F32)
{
if(svals[1].f32 != 0.f)
{
nval.f32 = svals[0].f32/svals[1].f32;
}
else
{
result.code = E_InterpretationCode_DivideByZero;
goto done;
}
}
else if(imm.u64 == RDI_EvalTypeGroup_F64)
{
if(svals[1].f64 != 0.)
{
nval.f64 = svals[0].f64/svals[1].f64;
}
else
{
result.code = E_InterpretationCode_DivideByZero;
goto done;
}
}
else if(imm.u64 == RDI_EvalTypeGroup_U ||
imm.u64 == RDI_EvalTypeGroup_S)
{
if(svals[1].u64 != 0)
{
nval.u64 = svals[0].u64/svals[1].u64;
}
else
{
result.code = E_InterpretationCode_DivideByZero;
goto done;
}
}
else
{
result.code = E_InterpretationCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_Mod:
{
if(imm.u64 == RDI_EvalTypeGroup_U ||
imm.u64 == RDI_EvalTypeGroup_S)
{
if(svals[1].u64 != 0)
{
nval.u64 = svals[0].u64%svals[1].u64;
}
}
else
{
result.code = E_InterpretationCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_LShift:
{
if(imm.u64 == RDI_EvalTypeGroup_U ||
imm.u64 == RDI_EvalTypeGroup_S)
{
nval.u64 = svals[0].u64 << svals[1].u64;
}
else
{
result.code = E_InterpretationCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_RShift:
{
if(imm.u64 == RDI_EvalTypeGroup_U)
{
nval.u64 = svals[0].u64 >> svals[1].u64;
}
else if(imm.u64 == RDI_EvalTypeGroup_S)
{
nval.u64 = svals[0].s64 >> svals[1].u64;
}
else
{
result.code = E_InterpretationCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_BitAnd:
{
if(imm.u64 == RDI_EvalTypeGroup_U ||
imm.u64 == RDI_EvalTypeGroup_S)
{
nval.u64 = svals[0].u64&svals[1].u64;
}
else
{
result.code = E_InterpretationCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_BitOr:
{
if(imm.u64 == RDI_EvalTypeGroup_U ||
imm.u64 == RDI_EvalTypeGroup_S)
{
nval.u64 = svals[0].u64|svals[1].u64;
}
else
{
result.code = E_InterpretationCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_BitXor:
{
if(imm.u64 == RDI_EvalTypeGroup_U ||
imm.u64 == RDI_EvalTypeGroup_S)
{
nval.u64 = svals[0].u64^svals[1].u64;
}
else
{
result.code = E_InterpretationCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_BitNot:
{
if(imm.u64 == RDI_EvalTypeGroup_U ||
imm.u64 == RDI_EvalTypeGroup_S)
{
nval.u64 = ~svals[0].u64;
}
else
{
result.code = E_InterpretationCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_LogAnd:
{
if(imm.u64 == RDI_EvalTypeGroup_U ||
imm.u64 == RDI_EvalTypeGroup_S)
{
nval.u64 = (svals[0].u64 && svals[1].u64);
}
else
{
result.code = E_InterpretationCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_LogOr:
{
if(imm.u64 == RDI_EvalTypeGroup_U ||
imm.u64 == RDI_EvalTypeGroup_S)
{
nval.u64 = (svals[0].u64 || svals[1].u64);
}
else
{
result.code = E_InterpretationCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_LogNot:
{
if(imm.u64 == RDI_EvalTypeGroup_U ||
imm.u64 == RDI_EvalTypeGroup_S)
{
nval.u64 = (!svals[0].u64);
}
else
{
result.code = E_InterpretationCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_EqEq:
{
B32 result = MemoryMatchArray(svals[0].u512, svals[1].u512);
nval.u64 = !!result;
}break;
case RDI_EvalOp_NtEq:
{
B32 result = MemoryMatchArray(svals[0].u512, svals[1].u512);
nval.u64 = !result;
}break;
case RDI_EvalOp_LsEq:
{
if(imm.u64 == RDI_EvalTypeGroup_F32)
{
nval.u64 = (svals[0].f32 <= svals[1].f32);
}
else if(imm.u64 == RDI_EvalTypeGroup_F64)
{
nval.u64 = (svals[0].f64 <= svals[1].f64);
}
else if(imm.u64 == RDI_EvalTypeGroup_U)
{
nval.u64 = (svals[0].u64 <= svals[1].u64);
}
else if(imm.u64 == RDI_EvalTypeGroup_S)
{
nval.u64 = (svals[0].s64 <= svals[1].s64);
}
else
{
result.code = E_InterpretationCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_GrEq:
{
if(imm.u64 == RDI_EvalTypeGroup_F32)
{
nval.u64 = (svals[0].f32 >= svals[1].f32);
}
else if(imm.u64 == RDI_EvalTypeGroup_F64)
{
nval.u64 = (svals[0].f64 >= svals[1].f64);
}
else if(imm.u64 == RDI_EvalTypeGroup_U)
{
nval.u64 = (svals[0].u64 >= svals[1].u64);
}
else if(imm.u64 == RDI_EvalTypeGroup_S)
{
nval.u64 = (svals[0].s64 >= svals[1].s64);
}
else
{
result.code = E_InterpretationCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_Less:
{
if(imm.u64 == RDI_EvalTypeGroup_F32)
{
nval.u64 = (svals[0].f32 < svals[1].f32);
}
else if(imm.u64 == RDI_EvalTypeGroup_F64)
{
nval.u64 = (svals[0].f64 < svals[1].f64);
}
else if(imm.u64 == RDI_EvalTypeGroup_U)
{
nval.u64 = (svals[0].u64 < svals[1].u64);
}
else if(imm.u64 == RDI_EvalTypeGroup_S)
{
nval.u64 = (svals[0].s64 < svals[1].s64);
}
else
{
result.code = E_InterpretationCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_Grtr:
{
if(imm.u64 == RDI_EvalTypeGroup_F32)
{
nval.u64 = (svals[0].f32 > svals[1].f32);
}
else if(imm.u64 == RDI_EvalTypeGroup_F64)
{
nval.u64 = (svals[0].f64 > svals[1].f64);
}
else if(imm.u64 == RDI_EvalTypeGroup_U)
{
nval.u64 = (svals[0].u64 > svals[1].u64);
}
else if(imm.u64 == RDI_EvalTypeGroup_S)
{
nval.u64 = (svals[0].s64 > svals[1].s64);
}
else
{
result.code = E_InterpretationCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_Trunc:
{
if(0 < imm.u64)
{
U64 mask = 0;
if(imm.u64 < 64)
{
mask = max_U64 >> (64 - imm.u64);
}
nval.u64 = svals[0].u64&mask;
}
}break;
case RDI_EvalOp_TruncSigned:
{
if(0 < imm.u64)
{
U64 mask = 0;
if(imm.u64 < 64)
{
mask = max_U64 >> (64 - imm.u64);
}
U64 high = 0;
if(svals[0].u64 & (1 << (imm.u64 - 1)))
{
high = ~mask;
}
nval.u64 = high|(svals[0].u64&mask);
}
}break;
case RDI_EvalOp_Convert:
{
U32 in = imm.u64&0xFF;
U32 out = (imm.u64 >> 8)&0xFF;
if(in != out)
{
switch(in + out*RDI_EvalTypeGroup_COUNT)
{
case RDI_EvalTypeGroup_F32 + RDI_EvalTypeGroup_U*RDI_EvalTypeGroup_COUNT:
{
nval.u64 = (U64)svals[0].f32;
}break;
case RDI_EvalTypeGroup_F64 + RDI_EvalTypeGroup_U*RDI_EvalTypeGroup_COUNT:
{
nval.u64 = (U64)svals[0].f64;
}break;
case RDI_EvalTypeGroup_F32 + RDI_EvalTypeGroup_S*RDI_EvalTypeGroup_COUNT:
{
nval.s64 = (S64)svals[0].f32;
}break;
case RDI_EvalTypeGroup_F64 + RDI_EvalTypeGroup_S*RDI_EvalTypeGroup_COUNT:
{
nval.s64 = (S64)svals[0].f64;
}break;
case RDI_EvalTypeGroup_U + RDI_EvalTypeGroup_F32*RDI_EvalTypeGroup_COUNT:
{
nval.f32 = (F32)svals[0].u64;
}break;
case RDI_EvalTypeGroup_S + RDI_EvalTypeGroup_F32*RDI_EvalTypeGroup_COUNT:
{
nval.f32 = (F32)svals[0].s64;
}break;
case RDI_EvalTypeGroup_F64 + RDI_EvalTypeGroup_F32*RDI_EvalTypeGroup_COUNT:
{
nval.f32 = (F32)svals[0].f64;
}break;
case RDI_EvalTypeGroup_U + RDI_EvalTypeGroup_F64*RDI_EvalTypeGroup_COUNT:
{
nval.f64 = (F64)svals[0].u64;
}break;
case RDI_EvalTypeGroup_S + RDI_EvalTypeGroup_F64*RDI_EvalTypeGroup_COUNT:
{
nval.f64 = (F64)svals[0].s64;
}break;
case RDI_EvalTypeGroup_F32 + RDI_EvalTypeGroup_F64*RDI_EvalTypeGroup_COUNT:
{
nval.f64 = (F64)svals[0].f32;
}break;
}
}
}break;
case RDI_EvalOp_Pick:
{
if(stack_count > imm.u64)
{
nval = stack[stack_count - imm.u64 - 1];
}
else
{
result.code = E_InterpretationCode_BadOp;
goto done;
}
}break;
case RDI_EvalOp_Pop:
{
// do nothing - the pop is handled by the control bits
}break;
case RDI_EvalOp_Insert:
{
if(stack_count > imm.u64)
{
if(imm.u64 > 0)
{
E_Value tval = stack[stack_count - 1];
E_Value *dst = stack + stack_count - 1 - imm.u64;
E_Value *shift = dst + 1;
MemoryCopy(shift, dst, imm.u64*sizeof(E_Value));
*dst = tval;
}
}
else
{
result.code = E_InterpretationCode_BadOp;
goto done;
}
}break;
case RDI_EvalOp_ValueRead:
{
U64 bytes_to_read = imm.u64;
U64 offset = svals[0].u64;
if(offset + bytes_to_read <= sizeof(E_Value))
{
E_Value src_val = svals[1];
MemoryCopy(&nval.u512[0], (U8 *)(&src_val.u512[0]) + offset, bytes_to_read);
}
}break;
case RDI_EvalOp_ByteSwap:
{
U64 byte_size = imm.u64;
switch(byte_size)
{
default:
{
result.code = E_InterpretationCode_BadOp;
goto done;
}break;
case 2:{nval.u16 = bswap_u16(svals[0].u16);}break;
case 4:{nval.u32 = bswap_u32(svals[0].u32);}break;
case 8:{nval.u64 = bswap_u64(svals[0].u64);}break;
}
}break;
}
// rjf: push
{
U64 push_count = RDI_PUSHN_FROM_CTRLBITS(ctrlbits);
if(push_count == 1)
{
if(stack_count < stack_cap)
{
stack[stack_count] = nval;
stack_count += 1;
}
else
{
result.code = E_InterpretationCode_InsufficientStackSpace;
goto done;
}
}
}
}
done:;
if(stack_count >= 1)
{
result.value = stack[0];
}
scratch_end(scratch);
return result;
}
+59
View File
@@ -0,0 +1,59 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef EVAL_INTERPRET_H
#define EVAL_INTERPRET_H
////////////////////////////////
//~ rjf: Bytecode Interpretation Types
typedef struct E_Interpretation E_Interpretation;
struct E_Interpretation
{
E_Value value;
E_InterpretationCode code;
};
////////////////////////////////
//~ rjf: Interpretation Context
typedef B32 E_SpaceRWFunction(void *user_data, E_Space space, void *out, Rng1U64 offset_range);
typedef struct E_InterpretCtx E_InterpretCtx;
struct E_InterpretCtx
{
void *space_rw_user_data;
E_SpaceRWFunction *space_read;
E_SpaceRWFunction *space_write;
E_Space primary_space;
Arch reg_arch;
E_Space reg_space;
U64 reg_unwind_count;
U64 *module_base;
U64 *frame_base;
U64 *tls_base;
};
////////////////////////////////
//~ rjf: Globals
thread_static E_InterpretCtx *e_interpret_ctx = 0;
////////////////////////////////
//~ rjf: Context Selection Functions (Selection Required For All Subsequent APIs)
internal E_InterpretCtx *e_selected_interpret_ctx(void);
internal void e_select_interpret_ctx(E_InterpretCtx *ctx);
////////////////////////////////
//~ rjf: Space Reading Helpers
internal B32 e_space_read(E_Space space, void *out, Rng1U64 range);
internal B32 e_space_write(E_Space space, void *in, Rng1U64 range);
////////////////////////////////
//~ rjf: Interpretation Functions
internal E_Interpretation e_interpret(String8 bytecode);
#endif // EVAL_INTERPRET_H
+1539
View File
File diff suppressed because it is too large Load Diff
+125
View File
@@ -0,0 +1,125 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef EVAL_IR_H
#define EVAL_IR_H
////////////////////////////////
//~ rjf: Bytecode Operation Types
enum
{
E_IRExtKind_Bytecode = RDI_EvalOp_COUNT,
E_IRExtKind_SetSpace,
E_IRExtKind_COUNT
};
typedef struct E_Op E_Op;
struct E_Op
{
E_Op *next;
RDI_EvalOp opcode;
E_Value value;
String8 string;
};
typedef struct E_OpList E_OpList;
struct E_OpList
{
E_Op *first;
E_Op *last;
U64 op_count;
U64 encoded_size;
};
////////////////////////////////
//~ rjf: IR Tree Types
typedef struct E_IRNode E_IRNode;
struct E_IRNode
{
E_IRNode *first;
E_IRNode *last;
E_IRNode *next;
RDI_EvalOp op;
String8 string;
E_Value value;
};
typedef struct E_IRTreeAndType E_IRTreeAndType;
struct E_IRTreeAndType
{
E_IRNode *root;
E_TypeKey type_key;
E_Mode mode;
E_Space space;
E_MsgList msgs;
};
////////////////////////////////
//~ rjf: Parse Context
typedef struct E_IRCtx E_IRCtx;
struct E_IRCtx
{
E_String2ExprMap *macro_map;
};
////////////////////////////////
//~ rjf: Globals
global read_only E_IRNode e_irnode_nil = {&e_irnode_nil, &e_irnode_nil, &e_irnode_nil};
thread_static E_IRCtx *e_ir_ctx = 0;
////////////////////////////////
//~ rjf: Expr Kind Enum Functions
internal RDI_EvalOp e_opcode_from_expr_kind(E_ExprKind kind);
internal B32 e_expr_kind_is_comparison(E_ExprKind kind);
////////////////////////////////
//~ rjf: Context Selection Functions (Selection Required For All Subsequent APIs)
internal E_IRCtx *e_selected_ir_ctx(void);
internal void e_select_ir_ctx(E_IRCtx *ctx);
////////////////////////////////
//~ rjf: IR-ization Functions
//- rjf: op list functions
internal void e_oplist_push_op(Arena *arena, E_OpList *list, RDI_EvalOp opcode, E_Value value);
internal void e_oplist_push_uconst(Arena *arena, E_OpList *list, U64 x);
internal void e_oplist_push_sconst(Arena *arena, E_OpList *list, S64 x);
internal void e_oplist_push_bytecode(Arena *arena, E_OpList *list, String8 bytecode);
internal void e_oplist_push_set_space(Arena *arena, E_OpList *list, E_Space space);
internal void e_oplist_push_string_literal(Arena *arena, E_OpList *list, String8 string);
internal void e_oplist_concat_in_place(E_OpList *dst, E_OpList *to_push);
//- rjf: ir tree core building helpers
internal E_IRNode *e_push_irnode(Arena *arena, RDI_EvalOp op);
internal void e_irnode_push_child(E_IRNode *parent, E_IRNode *child);
//- rjf: ir subtree building helpers
internal E_IRNode *e_irtree_const_u(Arena *arena, U64 v);
internal E_IRNode *e_irtree_unary_op(Arena *arena, RDI_EvalOp op, RDI_EvalTypeGroup group, E_IRNode *c);
internal E_IRNode *e_irtree_binary_op(Arena *arena, RDI_EvalOp op, RDI_EvalTypeGroup group, E_IRNode *l, E_IRNode *r);
internal E_IRNode *e_irtree_binary_op_u(Arena *arena, RDI_EvalOp op, E_IRNode *l, E_IRNode *r);
internal E_IRNode *e_irtree_conditional(Arena *arena, E_IRNode *c, E_IRNode *l, E_IRNode *r);
internal E_IRNode *e_irtree_bytecode_no_copy(Arena *arena, String8 bytecode);
internal E_IRNode *e_irtree_string_literal(Arena *arena, String8 string);
internal E_IRNode *e_irtree_set_space(Arena *arena, E_Space space, E_IRNode *c);
internal E_IRNode *e_irtree_mem_read_type(Arena *arena, E_Space space, E_IRNode *c, E_TypeKey type_key);
internal E_IRNode *e_irtree_convert_lo(Arena *arena, E_IRNode *c, RDI_EvalTypeGroup out, RDI_EvalTypeGroup in);
internal E_IRNode *e_irtree_trunc(Arena *arena, E_IRNode *c, E_TypeKey type_key);
internal E_IRNode *e_irtree_convert_hi(Arena *arena, E_IRNode *c, E_TypeKey out, E_TypeKey in);
internal E_IRNode *e_irtree_resolve_to_value(Arena *arena, E_Space from_space, E_Mode from_mode, E_IRNode *tree, E_TypeKey type_key);
//- rjf: top-level irtree/type extraction
internal E_IRTreeAndType e_irtree_and_type_from_expr(Arena *arena, E_Expr *expr);
//- rjf: irtree -> linear ops/bytecode
internal void e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_OpList *out);
internal E_OpList e_oplist_from_irtree(Arena *arena, E_IRNode *root);
internal String8 e_bytecode_from_oplist(Arena *arena, E_OpList *oplist);
#endif // EVAL_IR_H
-648
View File
@@ -1,648 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ allen: Eval Machine Functions
internal EVAL_Result
eval_interpret(EVAL_Machine *machine, String8 bytecode)
{
ProfBeginFunction();
EVAL_Result result = {0};
// TODO(allen): We could scan the bytecode and figure out the
// maximum depth of the stack
Temp scratch = scratch_begin(0, 0);
U64 stack_cap = 128;
EVAL_Slot *stack = push_array_no_zero(scratch.arena, EVAL_Slot, stack_cap);
U64 stack_count = 0;
U8 *ptr = bytecode.str;
U8 *opl = bytecode.str + bytecode.size;
for (;ptr < opl;){
// consume opcode
RDI_EvalOp op = (RDI_EvalOp)*ptr;
if (op >= RDI_EvalOp_COUNT){
result.code = EVAL_ResultCode_BadOp;
goto done;
}
U8 ctrlbits = rdi_eval_op_ctrlbits_table[op];
ptr += 1;
// decode
U64 imm = 0;
{
U32 decode_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits);
U8 *next_ptr = ptr + decode_size;
if (next_ptr > opl){
result.code = EVAL_ResultCode_BadOp;
goto done;
}
// TODO(allen): to improve this:
// gaurantee 8 bytes padding after the end of serialized bytecode
// read 8 bytes and mask
switch (decode_size){
case 1: imm = *ptr; break;
case 2: imm = *(U16*)ptr; break;
case 4: imm = *(U32*)ptr; break;
case 8: imm = *(U64*)ptr; break;
}
ptr = next_ptr;
}
// pop
EVAL_Slot *svals = 0;
{
U32 pop_count = RDI_POPN_FROM_CTRLBITS(ctrlbits);
if (pop_count > stack_count){
result.code = EVAL_ResultCode_BadOp;
goto done;
}
if (pop_count <= stack_count){
stack_count -= pop_count;
svals = stack + stack_count;
}
}
// interpret
EVAL_Slot nval = {0};
switch (op){
case RDI_EvalOp_Stop:
{
goto done;
}break;
case RDI_EvalOp_Noop:
{
// do nothing
}break;
case RDI_EvalOp_Cond:
{
if (svals[0].u64){
ptr += imm;
}
}break;
case RDI_EvalOp_Skip:
{
ptr += imm;
}break;
case RDI_EvalOp_MemRead:
{
U64 addr = svals[0].u64;
U64 size = imm;
B32 good_read = 0;
if (machine->memory_read != 0 &&
machine->memory_read(machine->u, &nval, addr, size)){
good_read = 1;
}
if (!good_read){
result.code = EVAL_ResultCode_BadMemRead;
goto done;
}
}break;
case RDI_EvalOp_RegRead:
{
U8 rdi_reg_code = (imm&0x0000FF)>>0;
U8 byte_size = (imm&0x00FF00)>>8;
U8 byte_off = (imm&0xFF0000)>>16;
REGS_RegCode base_reg_code = regs_reg_code_from_arch_rdi_code(machine->arch, rdi_reg_code);
REGS_Rng rng = regs_reg_code_rng_table_from_architecture(machine->arch)[base_reg_code];
U64 off = (U64)rng.byte_off + byte_off;
U64 size = (U64)byte_size;
if (off + size <= machine->reg_size){
MemoryCopy(&nval, (U8*)machine->reg_data + off, size);
}
else{
result.code = EVAL_ResultCode_BadRegRead;
goto done;
}
}break;
case RDI_EvalOp_RegReadDyn:
{
U64 off = svals[0].u64;
U64 size = bit_size_from_arch(machine->arch)/8;
if (off + size <= machine->reg_size){
MemoryCopy(&nval, (U8*)machine->reg_data + off, size);
}
else{
result.code = EVAL_ResultCode_BadRegRead;
goto done;
}
}break;
case RDI_EvalOp_FrameOff:
{
if (machine->frame_base != 0){
nval.u64 = *machine->frame_base + imm;
}
else{
result.code = EVAL_ResultCode_BadFrameBase;
goto done;
}
}break;
case RDI_EvalOp_ModuleOff:
{
if (machine->module_base != 0){
nval.u64 = *machine->module_base + imm;
}
else{
result.code = EVAL_ResultCode_BadModuleBase;
goto done;
}
}break;
case RDI_EvalOp_TLSOff:
{
if (machine->tls_base != 0){
nval.u64 = *machine->tls_base + imm;
}
else{
result.code = EVAL_ResultCode_BadTLSBase;
goto done;
}
}break;
case RDI_EvalOp_ConstU8:
case RDI_EvalOp_ConstU16:
case RDI_EvalOp_ConstU32:
case RDI_EvalOp_ConstU64:
{
nval.u64 = imm;
}break;
case RDI_EvalOp_Abs:
{
if (imm == RDI_EvalTypeGroup_F32){
nval.f32 = svals[0].f32;
if (svals[0].f32 < 0){
nval.f32 = -svals[0].f32;
}
}
else if (imm == RDI_EvalTypeGroup_F64){
nval.f64 = svals[0].f64;
if (svals[0].f64 < 0){
nval.f64 = -svals[0].f64;
}
}
else{
nval.s64 = svals[0].s64;
if (svals[0].s64 < 0){
nval.s64 = -svals[0].s64;
}
}
}break;
case RDI_EvalOp_Neg:
{
if (imm == RDI_EvalTypeGroup_F32){
nval.f32 = -svals[0].f32;
}
else if (imm == RDI_EvalTypeGroup_F64){
nval.f64 = -svals[0].f64;
}
else{
nval.u64 = (~svals[0].u64) + 1;
}
}break;
case RDI_EvalOp_Add:
{
if (imm == RDI_EvalTypeGroup_F32){
nval.f32 = svals[0].f32 + svals[1].f32;
}
else if (imm == RDI_EvalTypeGroup_F64){
nval.f64 = svals[0].f64 + svals[1].f64;
}
else{
nval.u64 = svals[0].u64 + svals[1].u64;
}
}break;
case RDI_EvalOp_Sub:
{
if (imm == RDI_EvalTypeGroup_F32){
nval.f32 = svals[0].f32 - svals[1].f32;
}
else if (imm == RDI_EvalTypeGroup_F64){
nval.f64 = svals[0].f64 - svals[1].f64;
}
else{
nval.u64 = svals[0].u64 - svals[1].u64;
}
}break;
case RDI_EvalOp_Mul:
{
if (imm == RDI_EvalTypeGroup_F32){
nval.f32 = svals[0].f32*svals[1].f32;
}
else if (imm == RDI_EvalTypeGroup_F64){
nval.f64 = svals[0].f64*svals[1].f64;
}
else{
nval.u64 = svals[0].u64*svals[1].u64;
}
}break;
case RDI_EvalOp_Div:
{
if (imm == RDI_EvalTypeGroup_F32){
if (svals[1].f32 != 0.f){
nval.f32 = svals[0].f32/svals[1].f32;
}
else
{
result.code = EVAL_ResultCode_DivideByZero;
goto done;
}
}
else if (imm == RDI_EvalTypeGroup_F64){
if (svals[1].f64 != 0.){
nval.f64 = svals[0].f64/svals[1].f64;
}
else
{
result.code = EVAL_ResultCode_DivideByZero;
goto done;
}
}
else if (imm == RDI_EvalTypeGroup_U ||
imm == RDI_EvalTypeGroup_S){
if (svals[1].u64 != 0){
nval.u64 = svals[0].u64/svals[1].u64;
}
else
{
result.code = EVAL_ResultCode_DivideByZero;
goto done;
}
}
else{
result.code = EVAL_ResultCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_Mod:
{
if (imm == RDI_EvalTypeGroup_U ||
imm == RDI_EvalTypeGroup_S){
if (svals[1].u64 != 0){
nval.u64 = svals[0].u64%svals[1].u64;
}
}
else{
result.code = EVAL_ResultCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_LShift:
{
if (imm == RDI_EvalTypeGroup_U ||
imm == RDI_EvalTypeGroup_S){
nval.u64 = svals[0].u64 << svals[1].u64;
}
else{
result.code = EVAL_ResultCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_RShift:
{
if (imm == RDI_EvalTypeGroup_U){
nval.u64 = svals[0].u64 >> svals[1].u64;
}
else if (imm == RDI_EvalTypeGroup_S){
nval.u64 = svals[0].s64 >> svals[1].u64;
}
else{
result.code = EVAL_ResultCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_BitAnd:
{
if (imm == RDI_EvalTypeGroup_U ||
imm == RDI_EvalTypeGroup_S){
nval.u64 = svals[0].u64&svals[1].u64;
}
else{
result.code = EVAL_ResultCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_BitOr:
{
if (imm == RDI_EvalTypeGroup_U ||
imm == RDI_EvalTypeGroup_S){
nval.u64 = svals[0].u64|svals[1].u64;
}
else{
result.code = EVAL_ResultCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_BitXor:
{
if (imm == RDI_EvalTypeGroup_U ||
imm == RDI_EvalTypeGroup_S){
nval.u64 = svals[0].u64^svals[1].u64;
}
else{
result.code = EVAL_ResultCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_BitNot:
{
if (imm == RDI_EvalTypeGroup_U ||
imm == RDI_EvalTypeGroup_S){
nval.u64 = ~svals[0].u64;
}
else{
result.code = EVAL_ResultCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_LogAnd:
{
if (imm == RDI_EvalTypeGroup_U ||
imm == RDI_EvalTypeGroup_S){
nval.u64 = (svals[0].u64 && svals[1].u64);
}
else{
result.code = EVAL_ResultCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_LogOr:
{
if (imm == RDI_EvalTypeGroup_U ||
imm == RDI_EvalTypeGroup_S){
nval.u64 = (svals[0].u64 || svals[1].u64);
}
else{
result.code = EVAL_ResultCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_LogNot:
{
if (imm == RDI_EvalTypeGroup_U ||
imm == RDI_EvalTypeGroup_S){
nval.u64 = (!svals[0].u64);
}
else{
result.code = EVAL_ResultCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_EqEq:
{
nval.u64 = (svals[0].u64 == svals[1].u64);
}break;
case RDI_EvalOp_NtEq:
{
nval.u64 = (svals[0].u64 != svals[1].u64);
}break;
case RDI_EvalOp_LsEq:
{
if (imm == RDI_EvalTypeGroup_F32){
nval.u64 = (svals[0].f32 <= svals[1].f32);
}
else if (imm == RDI_EvalTypeGroup_F64){
nval.u64 = (svals[0].f64 <= svals[1].f64);
}
else if (imm == RDI_EvalTypeGroup_U){
nval.u64 = (svals[0].u64 <= svals[1].u64);
}
else if (imm == RDI_EvalTypeGroup_S){
nval.u64 = (svals[0].s64 <= svals[1].s64);
}
else{
result.code = EVAL_ResultCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_GrEq:
{
if (imm == RDI_EvalTypeGroup_F32){
nval.u64 = (svals[0].f32 >= svals[1].f32);
}
else if (imm == RDI_EvalTypeGroup_F64){
nval.u64 = (svals[0].f64 >= svals[1].f64);
}
else if (imm == RDI_EvalTypeGroup_U){
nval.u64 = (svals[0].u64 >= svals[1].u64);
}
else if (imm == RDI_EvalTypeGroup_S){
nval.u64 = (svals[0].s64 >= svals[1].s64);
}
else{
result.code = EVAL_ResultCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_Less:
{
if (imm == RDI_EvalTypeGroup_F32){
nval.u64 = (svals[0].f32 < svals[1].f32);
}
else if (imm == RDI_EvalTypeGroup_F64){
nval.u64 = (svals[0].f64 < svals[1].f64);
}
else if (imm == RDI_EvalTypeGroup_U){
nval.u64 = (svals[0].u64 < svals[1].u64);
}
else if (imm == RDI_EvalTypeGroup_S){
nval.u64 = (svals[0].s64 < svals[1].s64);
}
else{
result.code = EVAL_ResultCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_Grtr:
{
if (imm == RDI_EvalTypeGroup_F32){
nval.u64 = (svals[0].f32 > svals[1].f32);
}
else if (imm == RDI_EvalTypeGroup_F64){
nval.u64 = (svals[0].f64 > svals[1].f64);
}
else if (imm == RDI_EvalTypeGroup_U){
nval.u64 = (svals[0].u64 > svals[1].u64);
}
else if (imm == RDI_EvalTypeGroup_S){
nval.u64 = (svals[0].s64 > svals[1].s64);
}
else{
result.code = EVAL_ResultCode_BadOpTypes;
goto done;
}
}break;
case RDI_EvalOp_Trunc:
{
if (0 < imm){
U64 mask = 0;
if (imm < 64){
mask = max_U64 >> (64 - imm);
}
nval.u64 = svals[0].u64&mask;
}
}break;
case RDI_EvalOp_TruncSigned:
{
if (0 < imm){
U64 mask = 0;
if (imm < 64){
mask = max_U64 >> (64 - imm);
}
U64 high = 0;
if (svals[0].u64 & (1 << (imm - 1))){
high = ~mask;
}
nval.u64 = high|(svals[0].u64&mask);
}
}break;
case RDI_EvalOp_Convert:
{
U32 in = imm&0xFF;
U32 out = (imm >> 8)&0xFF;
if (in != out){
switch (in + out*RDI_EvalTypeGroup_COUNT){
case RDI_EvalTypeGroup_F32 + RDI_EvalTypeGroup_U*RDI_EvalTypeGroup_COUNT:
{
nval.u64 = (U64)svals[0].f32;
}break;
case RDI_EvalTypeGroup_F64 + RDI_EvalTypeGroup_U*RDI_EvalTypeGroup_COUNT:
{
nval.u64 = (U64)svals[0].f64;
}break;
case RDI_EvalTypeGroup_F32 + RDI_EvalTypeGroup_S*RDI_EvalTypeGroup_COUNT:
{
nval.s64 = (S64)svals[0].f32;
}break;
case RDI_EvalTypeGroup_F64 + RDI_EvalTypeGroup_S*RDI_EvalTypeGroup_COUNT:
{
nval.s64 = (S64)svals[0].f64;
}break;
case RDI_EvalTypeGroup_U + RDI_EvalTypeGroup_F32*RDI_EvalTypeGroup_COUNT:
{
nval.f32 = (F32)svals[0].u64;
}break;
case RDI_EvalTypeGroup_S + RDI_EvalTypeGroup_F32*RDI_EvalTypeGroup_COUNT:
{
nval.f32 = (F32)svals[0].s64;
}break;
case RDI_EvalTypeGroup_F64 + RDI_EvalTypeGroup_F32*RDI_EvalTypeGroup_COUNT:
{
nval.f32 = (F32)svals[0].f64;
}break;
case RDI_EvalTypeGroup_U + RDI_EvalTypeGroup_F64*RDI_EvalTypeGroup_COUNT:
{
nval.f64 = (F64)svals[0].u64;
}break;
case RDI_EvalTypeGroup_S + RDI_EvalTypeGroup_F64*RDI_EvalTypeGroup_COUNT:
{
nval.f64 = (F64)svals[0].s64;
}break;
case RDI_EvalTypeGroup_F32 + RDI_EvalTypeGroup_F64*RDI_EvalTypeGroup_COUNT:
{
nval.f64 = (F64)svals[0].f32;
}break;
}
}
}break;
case RDI_EvalOp_Pick:
{
if (stack_count > imm){
nval = stack[stack_count - imm - 1];
}
else{
result.code = EVAL_ResultCode_BadOp;
goto done;
}
}break;
case RDI_EvalOp_Pop:
{
// do nothing - the pop is handled by the control bits
}break;
case RDI_EvalOp_Insert:
{
if (stack_count > imm){
if (imm > 0){
EVAL_Slot tval = stack[stack_count - 1];
EVAL_Slot *dst = stack + stack_count - 1 - imm;
EVAL_Slot *shift = dst + 1;
MemoryCopy(shift, dst, imm*sizeof(EVAL_Slot));
*dst = tval;
}
}
else{
result.code = EVAL_ResultCode_BadOp;
goto done;
}
}break;
}
// push
{
U64 push_count = RDI_PUSHN_FROM_CTRLBITS(ctrlbits);
if (push_count == 1){
if (stack_count < stack_cap){
stack[stack_count] = nval;
stack_count += 1;
}
else{
result.code = EVAL_ResultCode_InsufficientStackSpace;
goto done;
}
}
}
}
done:;
if (stack_count == 1){
result.value = stack[0];
}
else if(result.code == EVAL_ResultCode_Good){
result.code = EVAL_ResultCode_MalformedBytecode;
}
scratch_end(scratch);
ProfEnd();
return(result);
}
-48
View File
@@ -1,48 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef EVAL2_MACHINE_H
#define EVAL2_MACHINE_H
////////////////////////////////
//~ allen: Eval Machine Types
typedef B32 EVAL_MemoryRead(void *u, void *out, U64 addr, U64 size);
typedef struct EVAL_Machine EVAL_Machine;
struct EVAL_Machine
{
void *u;
Architecture arch;
EVAL_MemoryRead *memory_read;
void *reg_data;
U64 reg_size;
U64 *module_base;
U64 *frame_base;
U64 *tls_base;
};
typedef union EVAL_Slot EVAL_Slot;
union EVAL_Slot
{
U64 u256[4];
U64 u128[2];
U64 u64;
S64 s64;
F64 f64;
F32 f32;
};
typedef struct EVAL_Result EVAL_Result;
struct EVAL_Result
{
EVAL_Slot value;
EVAL_ResultCode code;
};
////////////////////////////////
//~ allen: Eval Machine Functions
internal EVAL_Result eval_interpret(EVAL_Machine *machine, String8 bytecode);
#endif //EVAL2_MACHINE_H
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More