mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-01 04:10:07 +00:00
Update Tilde for the new TB_Passes approach
This commit is contained in:
+50
-56
@@ -15,20 +15,21 @@
|
||||
#define TB_VERSION_MINOR 2
|
||||
#define TB_VERSION_PATCH 0
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define TB_EXTERN extern "C"
|
||||
#else
|
||||
#define TB_EXTERN
|
||||
#endif
|
||||
|
||||
#ifdef TB_DLL
|
||||
# ifdef TB_IMPORT_DLL
|
||||
# define TB_API TB_EXTERN __declspec(dllimport)
|
||||
#ifndef TB_API
|
||||
# ifdef __cplusplus
|
||||
# define TB_EXTERN extern "C"
|
||||
# else
|
||||
# define TB_API TB_EXTERN __declspec(dllexport)
|
||||
# define TB_EXTERN
|
||||
# endif
|
||||
# ifdef TB_DLL
|
||||
# ifdef TB_IMPORT_DLL
|
||||
# define TB_API TB_EXTERN __declspec(dllimport)
|
||||
# else
|
||||
# define TB_API TB_EXTERN __declspec(dllexport)
|
||||
# endif
|
||||
# else
|
||||
# define TB_API TB_EXTERN
|
||||
# endif
|
||||
#else
|
||||
# define TB_API TB_EXTERN
|
||||
#endif
|
||||
|
||||
// These are flags
|
||||
@@ -171,7 +172,6 @@ typedef enum TB_FloatFormat {
|
||||
typedef union TB_DataType {
|
||||
struct {
|
||||
uint8_t type;
|
||||
// 2^N where N is the width value.
|
||||
// Only integers and floats can be wide.
|
||||
uint8_t width;
|
||||
// for integers it's the bitwidth
|
||||
@@ -406,8 +406,6 @@ typedef struct TB_Symbol {
|
||||
|
||||
typedef int TB_Reg;
|
||||
|
||||
#define TB_NULL_REG NULL
|
||||
|
||||
typedef struct TB_Node TB_Node;
|
||||
struct TB_Node {
|
||||
TB_NodeType type;
|
||||
@@ -586,29 +584,13 @@ typedef struct {
|
||||
|
||||
typedef void (*TB_PrintCallback)(void* user_data, const char* fmt, ...);
|
||||
|
||||
////////////////////////////////
|
||||
// Arena
|
||||
////////////////////////////////
|
||||
// the goal is to move more things to transparent arenas, for now it's just function
|
||||
// IR which is a big one if you're interested in freeing them in whatever organization
|
||||
// you please.
|
||||
|
||||
// allocations can make no guarentees about being sequential
|
||||
// tho it would be greatly appreciated at least to some degree.
|
||||
// defined in common/arena.h
|
||||
typedef struct TB_Arena TB_Arena;
|
||||
struct TB_Arena {
|
||||
// alignment never goes past max_align_t
|
||||
void* (*alloc)(TB_Arena* arena, size_t size, size_t align);
|
||||
|
||||
// clearing but we're not done with it yet, cheap
|
||||
void (*clear)(TB_Arena* arena);
|
||||
|
||||
// frees everything within the arena, potentially expensive
|
||||
void (*free)(TB_Arena* arena);
|
||||
};
|
||||
|
||||
// allocates in 16MiB chunks and does linear allocation in 'em
|
||||
TB_API TB_Arena* tb_default_arena(void);
|
||||
// 0 for default
|
||||
TB_API void tb_arena_create(TB_Arena* restrict arena, size_t chunk_size);
|
||||
TB_API void tb_arena_destroy(TB_Arena* restrict arena);
|
||||
TB_API bool tb_arena_is_empty(TB_Arena* arena);
|
||||
|
||||
////////////////////////////////
|
||||
// Module management
|
||||
@@ -651,8 +633,7 @@ struct TB_Assembly {
|
||||
// this is where the machine code and other relevant pieces go.
|
||||
typedef struct TB_FunctionOutput TB_FunctionOutput;
|
||||
|
||||
// returns NULL if it fails
|
||||
TB_API TB_FunctionOutput* tb_module_compile_function(TB_Module* m, TB_Function* f, TB_ISelMode isel_mode, bool emit_asm);
|
||||
TB_API void tb_output_print_asm(TB_FunctionOutput* out, FILE* fp);
|
||||
|
||||
TB_API uint8_t* tb_output_get_code(TB_FunctionOutput* out, size_t* out_length);
|
||||
|
||||
@@ -865,6 +846,9 @@ TB_API TB_DebugType* tb_debug_create_func(TB_Module* m, TB_CallingConv cc, size_
|
||||
|
||||
TB_API TB_DebugType* tb_debug_field_type(TB_DebugType* type);
|
||||
|
||||
TB_API size_t tb_debug_func_return_count(TB_DebugType* type);
|
||||
TB_API size_t tb_debug_func_param_count(TB_DebugType* type);
|
||||
|
||||
// you'll need to fill these if you make a function
|
||||
TB_API TB_DebugType** tb_debug_func_params(TB_DebugType* type);
|
||||
TB_API TB_DebugType** tb_debug_func_returns(TB_DebugType* type);
|
||||
@@ -895,9 +879,6 @@ TB_API void tb_default_print_callback(void* user_data, const char* fmt, ...);
|
||||
|
||||
TB_API void tb_inst_set_location(TB_Function* f, TB_FileID file, int line);
|
||||
|
||||
// this only allows for power of two vector types
|
||||
TB_API TB_DataType tb_vector_type(TB_DataTypeEnum type, int width);
|
||||
|
||||
// if section is NULL, default to .text
|
||||
TB_API TB_Function* tb_function_create(TB_Module* m, ptrdiff_t len, const char* name, TB_Linkage linkage, TB_ComdatType comdat);
|
||||
|
||||
@@ -1073,25 +1054,40 @@ TB_API void tb_inst_branch(TB_Function* f, TB_DataType dt, TB_Node* key, TB_Node
|
||||
TB_API void tb_inst_ret(TB_Function* f, size_t count, TB_Node** values);
|
||||
|
||||
////////////////////////////////
|
||||
// Optimizer
|
||||
// Passes
|
||||
////////////////////////////////
|
||||
// Function analysis, optimizations, and codegen are all part of this
|
||||
typedef struct TB_FuncOpt TB_FuncOpt;
|
||||
typedef struct TB_Passes TB_Passes;
|
||||
|
||||
// the arena is used to allocate the nodes
|
||||
TB_API TB_FuncOpt* tb_funcopt_enter(TB_Function* f, TB_Arena* arena);
|
||||
TB_API void tb_funcopt_exit(TB_FuncOpt* opt);
|
||||
// the arena is used to allocate the nodes while passes are being done.
|
||||
TB_API TB_Passes* tb_pass_enter(TB_Function* f, TB_Arena* arena);
|
||||
TB_API void tb_pass_exit(TB_Passes* opt);
|
||||
|
||||
TB_API bool tb_funcopt_peephole(TB_FuncOpt* opt);
|
||||
TB_API bool tb_funcopt_mem2reg(TB_FuncOpt* opt);
|
||||
TB_API bool tb_funcopt_loop(TB_FuncOpt* opt);
|
||||
// transformation passes:
|
||||
// peephole: runs most simple reductions on the code,
|
||||
// should be run after any bigger passes (it's incremental
|
||||
// so it's not that bad)
|
||||
//
|
||||
// mem2reg: lowers TB_LOCALs into SSA values, this makes more
|
||||
// data flow analysis possible on the code and allows to codegen
|
||||
// to place variables into registers.
|
||||
//
|
||||
// loop: NOT READY
|
||||
//
|
||||
TB_API bool tb_pass_peephole(TB_Passes* opt);
|
||||
TB_API bool tb_pass_mem2reg(TB_Passes* opt);
|
||||
TB_API bool tb_pass_loop(TB_Passes* opt);
|
||||
|
||||
// isn't an optimization, just does the name flat form of IR printing
|
||||
TB_API bool tb_funcopt_print(TB_FuncOpt* opt);
|
||||
// analysis
|
||||
// print: prints IR in a flattened text form.
|
||||
TB_API bool tb_pass_print(TB_Passes* opt);
|
||||
|
||||
TB_API void tb_funcopt_kill(TB_FuncOpt* opt, TB_Node* n);
|
||||
TB_API bool tb_funcopt_mark(TB_FuncOpt* opt, TB_Node* n);
|
||||
TB_API void tb_funcopt_mark_users(TB_FuncOpt* opt, TB_Node* n);
|
||||
// codegen
|
||||
TB_API TB_FunctionOutput* tb_pass_codegen(TB_Passes* opt, bool emit_asm);
|
||||
|
||||
TB_API void tb_pass_kill_node(TB_Passes* opt, TB_Node* n);
|
||||
TB_API bool tb_pass_mark(TB_Passes* opt, TB_Node* n);
|
||||
TB_API void tb_pass_mark_users(TB_Passes* opt, TB_Node* n);
|
||||
|
||||
////////////////////////////////
|
||||
// IR access
|
||||
@@ -1099,8 +1095,6 @@ TB_API void tb_funcopt_mark_users(TB_FuncOpt* opt, TB_Node* n);
|
||||
TB_API const char* tb_node_get_name(TB_Node* n);
|
||||
|
||||
TB_API TB_Node* tb_get_parent_region(TB_Node* n);
|
||||
TB_API bool tb_has_effects(TB_Node* n);
|
||||
|
||||
TB_API bool tb_node_is_constant_non_zero(TB_Node* n);
|
||||
TB_API bool tb_node_is_constant_zero(TB_Node* n);
|
||||
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef TB_API
|
||||
# ifdef __cplusplus
|
||||
# define TB_EXTERN extern "C"
|
||||
# else
|
||||
# define TB_EXTERN
|
||||
# endif
|
||||
# ifdef TB_DLL
|
||||
# ifdef TB_IMPORT_DLL
|
||||
# define TB_API TB_EXTERN __declspec(dllimport)
|
||||
# else
|
||||
# define TB_API TB_EXTERN __declspec(dllexport)
|
||||
# endif
|
||||
# else
|
||||
# define TB_API TB_EXTERN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
enum {
|
||||
TB_ARENA_SMALL_CHUNK_SIZE = 4 * 1024,
|
||||
TB_ARENA_MEDIUM_CHUNK_SIZE = 512 * 1024,
|
||||
TB_ARENA_LARGE_CHUNK_SIZE = 2 * 1024 * 1024,
|
||||
|
||||
TB_ARENA_ALIGNMENT = 16,
|
||||
};
|
||||
|
||||
typedef struct TB_ArenaChunk TB_ArenaChunk;
|
||||
struct TB_ArenaChunk {
|
||||
TB_ArenaChunk* next;
|
||||
size_t pad;
|
||||
char data[];
|
||||
};
|
||||
|
||||
typedef struct TB_Arena {
|
||||
size_t chunk_size;
|
||||
TB_ArenaChunk* base;
|
||||
TB_ArenaChunk* top;
|
||||
|
||||
// top of the allocation space
|
||||
char* watermark;
|
||||
char* high_point; // &top->data[chunk_size]
|
||||
} TB_Arena;
|
||||
|
||||
typedef struct TB_ArenaSavepoint {
|
||||
TB_ArenaChunk* top;
|
||||
char* watermark;
|
||||
} TB_ArenaSavepoint;
|
||||
|
||||
#define TB_ARENA_FOR(it, arena) for (TB_ArenaChunk* it = (arena)->base; it != NULL; it = it->next)
|
||||
|
||||
#define TB_ARENA_ALLOC(arena, T) tb_arena_alloc(arena, sizeof(T))
|
||||
#define TB_ARENA_ARR_ALLOC(arena, count, T) tb_arena_alloc(arena, (count) * sizeof(T))
|
||||
|
||||
TB_API void tb_arena_create(TB_Arena* restrict arena, size_t chunk_size);
|
||||
TB_API void tb_arena_destroy(TB_Arena* restrict arena);
|
||||
|
||||
TB_API void* tb_arena_unaligned_alloc(TB_Arena* restrict arena, size_t size);
|
||||
TB_API void* tb_arena_alloc(TB_Arena* restrict arena, size_t size);
|
||||
|
||||
// asserts if ptr+size != watermark
|
||||
TB_API void tb_arena_pop(TB_Arena* restrict arena, void* ptr, size_t size);
|
||||
|
||||
// in case you wanna mix unaligned and aligned arenas
|
||||
TB_API void tb_arena_realign(TB_Arena* restrict arena);
|
||||
|
||||
TB_API bool tb_arena_is_empty(TB_Arena* arena);
|
||||
|
||||
// savepoints
|
||||
TB_API TB_ArenaSavepoint tb_arena_save(TB_Arena* arena);
|
||||
TB_API void tb_arena_restore(TB_Arena* arena, TB_ArenaSavepoint sp);
|
||||
|
||||
// resets to only having one chunk
|
||||
TB_API void tb_arena_clear(TB_Arena* arena);
|
||||
Reference in New Issue
Block a user