Skip to content

Commit

Permalink
Replace static initializer with @init / @Finalizer
Browse files Browse the repository at this point in the history
  • Loading branch information
lerno committed Oct 3, 2023
1 parent 757a5b5 commit 0ffecff
Show file tree
Hide file tree
Showing 28 changed files with 119 additions and 263 deletions.
4 changes: 1 addition & 3 deletions lib/std/core/builtin.c3
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,6 @@ enum CallLocation : int(String name)
MACRO("macro"),
LAMBDA("lambda"),
TEST("test"),
INITIALIZER("initializer"),
FINALIZER("finalizer")
}

struct CallstackElement
Expand Down Expand Up @@ -427,7 +425,7 @@ fn void install_signal_handler(CInt signal, SignalFunction func) @local
}

// Clean this up
static initialize @priority(101)
fn void install_signal_handlers() @init(101) @local
{
install_signal_handler(libc::SIGBUS, &sig_bus_error);
install_signal_handler(libc::SIGSEGV, &sig_segmentation_fault);
Expand Down
2 changes: 1 addition & 1 deletion lib/std/core/mem.c3
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,7 @@ module std::core::mem @if(WASM_NOLIBC);
SimpleHeapAllocator wasm_allocator @private;
extern int __heap_base;

static initialize @priority(1)
fn void initialize_wasm_mem() @init(1) @private
{
allocator::wasm_memory.allocate_block(mem::DEFAULT_MEM_ALIGNMENT)!!; // Give us a valid null.
// Check if we need to move the heap.
Expand Down
2 changes: 0 additions & 2 deletions src/compiler/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,10 @@ const char *decl_to_a_name(Decl *decl)
case DECL_ERASED: return "an erased declaration";
case DECL_FAULT: return "a fault";
case DECL_FAULTVALUE: return "a fault value";
case DECL_FINALIZE: return "a static finalizer";
case DECL_FNTYPE: return "a function type";
case DECL_FUNC: return "a function";
case DECL_GLOBALS: return "globals";
case DECL_IMPORT: return "an import";
case DECL_INITIALIZE: return "a static initializer";
case DECL_LABEL: return "a label";
case DECL_MACRO: return "a macro";
case DECL_POISONED: return "a poisoned decl";
Expand Down
14 changes: 3 additions & 11 deletions src/compiler/compiler_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -551,9 +551,12 @@ typedef struct
bool attr_winmain : 1;
bool attr_dynamic : 1;
bool attr_interface : 1;
bool attr_init : 1;
bool attr_finalizer : 1;
bool is_lambda : 1;
union
{
uint32_t priority;
DeclId any_prototype;
Decl **generated_lambda;
Decl **lambda_ct_parameters;
Expand Down Expand Up @@ -640,13 +643,6 @@ typedef struct
AstId parent;
} LabelDecl;

typedef struct
{
unsigned priority;
AstId init;
} InitializerDecl;


typedef struct Decl_
{
const char *name;
Expand Down Expand Up @@ -696,7 +692,6 @@ typedef struct Decl_
Type *type;
union
{
InitializerDecl xxlizer;
Decl** decl_list;
struct
{
Expand Down Expand Up @@ -1607,7 +1602,6 @@ struct CompilationUnit_
Decl **ct_asserts;
Decl **ct_echos;
Decl **ct_includes;
Decl **xxlizers;
Decl **vars;
Decl **macros;
Decl **methods;
Expand Down Expand Up @@ -1901,10 +1895,8 @@ extern const char *kw_at_require;
extern const char *kw_at_return;
extern const char *kw_check_assign;
extern const char *kw_deprecated;
extern const char *kw_finalize;
extern const char *kw_in;
extern const char *kw_incr;
extern const char *kw_initialize;
extern const char *kw_inout;
extern const char *kw_kind;
extern const char *kw_len;
Expand Down
6 changes: 0 additions & 6 deletions src/compiler/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,6 @@ void decl_register(Decl *decl)
{
case DECL_ERASED:
return;
case DECL_INITIALIZE:
case DECL_FINALIZE:
case DECL_POISONED:
case DECL_CT_ASSERT:
case DECL_CT_ECHO:
Expand Down Expand Up @@ -246,10 +244,6 @@ void unit_register_global_decl(CompilationUnit *unit, Decl *decl)
case DECL_CT_ASSERT:
vec_add(unit->ct_asserts, decl);
return;
case DECL_INITIALIZE:
case DECL_FINALIZE:
vec_add(unit->xxlizers, decl);
return;
}
DEBUG_LOG("Registering symbol '%s' in %s.", decl->name, unit->module->name->module);

Expand Down
4 changes: 0 additions & 4 deletions src/compiler/copying.c
Original file line number Diff line number Diff line change
Expand Up @@ -890,10 +890,6 @@ Decl *copy_decl(CopyStruct *c, Decl *decl)
case DECL_CT_INCLUDE:
MACRO_COPY_EXPR(copy->include.filename);
break;
case DECL_INITIALIZE:
case DECL_FINALIZE:
MACRO_COPY_ASTID(copy->xxlizer.init);
break;
case DECL_BODYPARAM:
MACRO_COPY_DECL_LIST(copy->body_params);
break;
Expand Down
16 changes: 6 additions & 10 deletions src/compiler/enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,10 @@ typedef enum
DECL_ERASED,
DECL_FAULT,
DECL_FAULTVALUE,
DECL_FINALIZE,
DECL_FNTYPE,
DECL_FUNC,
DECL_GLOBALS,
DECL_IMPORT,
DECL_INITIALIZE,
DECL_LABEL,
DECL_MACRO,
DECL_STRUCT,
Expand All @@ -155,8 +153,8 @@ typedef enum

#define NON_TYPE_DECLS DECL_IMPORT: case DECL_MACRO: \
case DECL_DECLARRAY: case DECL_ATTRIBUTE: case DECL_LABEL: \
case DECL_DEFINE: case DECL_CT_ASSERT: case DECL_INITIALIZE: case DECL_CT_EXEC: \
case DECL_FINALIZE: case DECL_CT_ECHO: case DECL_CT_INCLUDE: case DECL_GLOBALS: \
case DECL_DEFINE: case DECL_CT_ASSERT: case DECL_CT_EXEC: \
case DECL_CT_ECHO: case DECL_CT_INCLUDE: case DECL_GLOBALS: \
case DECL_BODYPARAM: case DECL_VAR: case DECL_ENUM_CONSTANT: case DECL_FAULTVALUE: \
case DECL_POISONED

Expand Down Expand Up @@ -751,11 +749,8 @@ typedef enum
ATTR_CALL = 1 << 12,
ATTR_BITSTRUCT = 1 << 13,
ATTR_MACRO = 1 << 14,
ATTR_INITIALIZER = 1 << 15,
ATTR_FINALIZER = 1 << 16,
ATTR_DEFINE = 1 << 17,
ATTR_ENUM_VALUE = 1 << 18,
ATTR_XXLIZER = ATTR_INITIALIZER | ATTR_FINALIZER
ATTR_DEFINE = 1 << 15,
ATTR_ENUM_VALUE = 1 << 16,
} AttributeDomain;

typedef enum
Expand All @@ -777,8 +772,10 @@ typedef enum
ATTRIBUTE_DYNAMIC,
ATTRIBUTE_EXPORT,
ATTRIBUTE_EXTERN,
ATTRIBUTE_FINALIZER,
ATTRIBUTE_IF,
ATTRIBUTE_INLINE,
ATTRIBUTE_INIT,
ATTRIBUTE_INTERFACE,
ATTRIBUTE_LITTLEENDIAN,
ATTRIBUTE_LOCAL,
Expand All @@ -793,7 +790,6 @@ typedef enum
ATTRIBUTE_OPERATOR,
ATTRIBUTE_OVERLAP,
ATTRIBUTE_PACKED,
ATTRIBUTE_PRIORITY,
ATTRIBUTE_PRIVATE,
ATTRIBUTE_PUBLIC,
ATTRIBUTE_PURE,
Expand Down
2 changes: 0 additions & 2 deletions src/compiler/json_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,10 @@ static inline const char *decl_type_to_string(Decl *type)
case DECL_ENUM_CONSTANT: return "enum_const";
case DECL_FAULT: return "fault";
case DECL_FAULTVALUE: return "fault_val";
case DECL_FINALIZE: return "finalizer";
case DECL_FNTYPE: return "fntype";
case DECL_FUNC: return "function";
case DECL_GLOBALS: return "global";
case DECL_IMPORT: return "import";
case DECL_INITIALIZE: return "initializer";
case DECL_MACRO: return "macro";
case DECL_STRUCT: return "struct";
case DECL_UNION: return "union";
Expand Down
7 changes: 0 additions & 7 deletions src/compiler/llvm_codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -1125,8 +1125,6 @@ LLVMValueRef llvm_get_ref(GenContext *c, Decl *decl)
case DECL_TYPEDEF:
case DECL_UNION:
case DECL_DECLARRAY:
case DECL_INITIALIZE:
case DECL_FINALIZE:
case DECL_BODYPARAM:
case DECL_CT_ECHO:
case DECL_CT_EXEC:
Expand Down Expand Up @@ -1436,11 +1434,6 @@ static GenContext *llvm_gen_module(Module *module, LLVMContextRef shared_context
.debug_file = unit->llvm.debug_file,
.file_id = unit->file->file_id };

FOREACH_BEGIN(Decl *initializer, unit->xxlizers)
has_elements = true;
llvm_emit_xxlizer(gen_context, initializer);
FOREACH_END();

FOREACH_BEGIN(Decl *method, unit->methods)
if (only_used && !method->is_live) continue;
llvm_emit_function_decl(gen_context, method);
Expand Down
55 changes: 12 additions & 43 deletions src/compiler/llvm_codegen_function.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "llvm_codegen_internal.h"

static LLVMValueRef llvm_add_xxlizer(GenContext *c, unsigned priority, bool is_finalizer);
static void llvm_append_xxlizer(GenContext *c, unsigned priority, bool is_initializer, LLVMValueRef function);
static void llvm_emit_param_attributes(GenContext *c, LLVMValueRef function, ABIArgInfo *info, bool is_return, int index, int last_index);
static inline void llvm_emit_return_value(GenContext *context, LLVMValueRef value);
static void llvm_expand_from_args(GenContext *c, Type *type, LLVMValueRef ref, unsigned *index, AlignSize alignment);
Expand Down Expand Up @@ -412,6 +413,10 @@ void llvm_emit_function_body(GenContext *c, Decl *decl, StacktraceType type)
DEBUG_LOG("Generating function %s.", decl->extname);
if (decl->func_decl.attr_dynamic) vec_add(c->dynamic_functions, decl);
assert(decl->backend_ref);
if (decl->func_decl.attr_init || decl->func_decl.attr_finalizer)
{
llvm_append_xxlizer(c, decl->func_decl.priority, decl->func_decl.attr_init, decl->backend_ref);
}
llvm_emit_body(c,
decl->backend_ref,
type_get_resolved_prototype(decl->type),
Expand Down Expand Up @@ -549,12 +554,6 @@ void llvm_emit_body(GenContext *c, LLVMValueRef function, FunctionPrototype *pro
case ST_MACRO:
function_name = decl->name;
break;
case ST_INITIALIZER:
function_name = "[static initializer]";
break;
case ST_FINALIZER:
function_name = "[static finalizer]";
break;
default:
UNREACHABLE
}
Expand Down Expand Up @@ -658,6 +657,13 @@ void llvm_emit_body(GenContext *c, LLVMValueRef function, FunctionPrototype *pro
c->function = prev_function;
}

static void llvm_append_xxlizer(GenContext *c, unsigned priority, bool is_initializer, LLVMValueRef function)
{
LLVMValueRef **array_ref = is_initializer ? &c->constructors : &c->destructors;
LLVMValueRef vals[3] = { llvm_const_int(c, type_int, priority), function, llvm_get_zero(c, type_voidptr) };
vec_add(*array_ref, LLVMConstStructInContext(c->context, vals, 3, false));
}

static LLVMValueRef llvm_add_xxlizer(GenContext *c, unsigned priority, bool is_initializer)
{
LLVMTypeRef initializer_type = LLVMFunctionType(LLVMVoidTypeInContext(c->context), NULL, 0, false);
Expand All @@ -671,43 +677,6 @@ static LLVMValueRef llvm_add_xxlizer(GenContext *c, unsigned priority, bool is_i
return function;
}

void llvm_emit_xxlizer(GenContext *c, Decl *decl)
{
Ast *body = astptrzero(decl->xxlizer.init);
if (!body)
{
// Skip if it doesn't have a body.
return;
}
bool is_initializer = decl->decl_kind == DECL_INITIALIZE;
LLVMValueRef function = llvm_add_xxlizer(c, decl->xxlizer.priority, is_initializer);
if (llvm_use_debug(c))
{
uint32_t row = decl->span.row;
if (!row) row = 1;
LLVMMetadataRef type = LLVMDIBuilderCreateSubroutineType(c->debug.builder, c->debug.file.debug_file, NULL, 0, 0);

c->debug.function = LLVMDIBuilderCreateFunction(c->debug.builder,
c->debug.file.debug_file,
scratch_buffer.str, scratch_buffer.len,
scratch_buffer.str, scratch_buffer.len,
c->debug.file.debug_file,
row,
type,
true,
true,
row,
LLVMDIFlagZero,
active_target.optlevel != OPTIMIZATION_NONE);
LLVMSetSubprogram(function, c->debug.function);
}
llvm_emit_body(c,
function,
NULL,
NULL,
body, decl, is_initializer ? ST_INITIALIZER : ST_FINALIZER);
}


void llvm_emit_dynamic_functions(GenContext *c, Decl **funcs)
{
Expand Down
3 changes: 0 additions & 3 deletions src/compiler/llvm_codegen_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ typedef enum
ST_LAMBDA,
ST_BENCHMARK,
ST_TEST,
ST_INITIALIZER,
ST_FINALIZER
} StacktraceType;

typedef struct
Expand Down Expand Up @@ -345,7 +343,6 @@ LLVMMetadataRef llvm_get_debug_type(GenContext *c, Type *type);
LLVMTypeRef llvm_get_type(GenContext *c, Type *any_type);
LLVMTypeRef llvm_get_pointee_type(GenContext *c, Type *any_type);
void llvm_emit_function_decl(GenContext *c, Decl *decl);
void llvm_emit_xxlizer(GenContext *c, Decl *decl);
bool llvm_types_are_similar(LLVMTypeRef original, LLVMTypeRef coerce);

// -- Attributes ---
Expand Down
41 changes: 3 additions & 38 deletions src/compiler/parse_global.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ static bool context_next_is_path_prefix_start(ParseContext *c);
static inline Decl *parse_func_definition(ParseContext *c, AstId contracts, bool is_interface);
static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl);
static inline bool parse_enum_param_list(ParseContext *c, Decl*** parameters_ref);
static inline Decl *parse_static_top_level(ParseContext *c);
static Decl *parse_include(ParseContext *c);
static Decl *parse_exec(ParseContext *c);
static bool parse_attributes_for_global(ParseContext *c, Decl *decl);
Expand Down Expand Up @@ -2297,39 +2296,6 @@ static inline Decl *parse_func_definition(ParseContext *c, AstId contracts, bool
return func;
}

static inline Decl *parse_static_top_level(ParseContext *c)
{
advance_and_verify(c, TOKEN_STATIC);
Decl *init = decl_calloc();
if (!tok_is(c, TOKEN_IDENT))
{
if (token_is_any_type(c->tok))
{
SEMA_ERROR_HERE("'static' can only used with local variables, to hide global variables and functions, use 'private'.");
return poisoned_decl;
}
SEMA_ERROR_HERE("Expected 'static initialize' or 'static finalize'.");
return poisoned_decl;
}
init->decl_kind = DECL_INITIALIZE;
if (c->data.string == kw_finalize)
{
init->decl_kind = DECL_FINALIZE;
}
else if (c->data.string != kw_initialize)
{
SEMA_ERROR_HERE("Expected 'static initialize' or 'static finalize'.");
return poisoned_decl;
}
advance(c);
Attr *attr = NULL;
bool is_cond;
if (!parse_attributes(c, &init->attributes, NULL, NULL, &is_cond)) return poisoned_decl;
init->is_cond = is_cond;
ASSIGN_ASTID_OR_RET(init->xxlizer.init, parse_compound_stmt(c), poisoned_decl);
RANGE_EXTEND_PREV(init);
return init;
}


/**
Expand Down Expand Up @@ -2746,10 +2712,6 @@ Decl *parse_top_level_statement(ParseContext *c, ParseContext **c_ref)
case TOKEN_FN:
decl = parse_func_definition(c, contracts, c->unit->is_interface_file);
break;
case TOKEN_STATIC:
if (contracts) goto CONTRACT_NOT_ALLOWED;
decl = parse_static_top_level(c);
break;
case TOKEN_CT_ASSERT:
{
if (contracts) goto CONTRACT_NOT_ALLOWED;
Expand Down Expand Up @@ -2822,6 +2784,9 @@ Decl *parse_top_level_statement(ParseContext *c, ParseContext **c_ref)
case TOKEN_EOF:
SEMA_ERROR_LAST("Expected a top level declaration.");
return poisoned_decl;
case TOKEN_STATIC:
SEMA_ERROR_HERE("'static' is only used with local variable declarations.");
return poisoned_decl;
case TOKEN_CT_CONST_IDENT:
if (peek(c) == TOKEN_EQ)
{
Expand Down
Loading

0 comments on commit 0ffecff

Please sign in to comment.