// only 32-bits of flags to play with
typedef enum AstFlags {
// Top-level flags
- Ast_Flag_Exported = BH_BIT(1),
- Ast_Flag_Foreign = BH_BIT(2),
- Ast_Flag_Const = BH_BIT(3),
- Ast_Flag_Comptime = BH_BIT(4),
- Ast_Flag_Private_Package = BH_BIT(5),
- Ast_Flag_Private_File = BH_BIT(6),
-
- // Global flags
- Ast_Flag_Global_Stack_Top = BH_BIT(7),
+ Ast_Flag_Const = BH_BIT(1),
+ Ast_Flag_Comptime = BH_BIT(2),
+ Ast_Flag_Private_Package = BH_BIT(3),
+ Ast_Flag_Private_File = BH_BIT(4),
// Function flags
- Ast_Flag_Already_Checked = BH_BIT(8),
- Ast_Flag_Intrinsic = BH_BIT(10),
- Ast_Flag_Function_Used = BH_BIT(11),
+ Ast_Flag_Function_Used = BH_BIT(5),
// Expression flags
- Ast_Flag_Expr_Ignored = BH_BIT(13),
- Ast_Flag_Param_Use = BH_BIT(14), // Unneeded, just use a bool on AstParam
- Ast_Flag_Address_Taken = BH_BIT(15),
+ Ast_Flag_Expr_Ignored = BH_BIT(6),
+ Ast_Flag_Address_Taken = BH_BIT(7),
// Type flags
- Ast_Flag_Type_Is_Resolved = BH_BIT(16),
-
- // Enum flags
- Ast_Flag_Enum_Is_Flags = BH_BIT(17), // Unneeded, just use a bool on AstEnum
-
- // Struct flags
- Ast_Flag_Struct_Is_Union = BH_BIT(18), // Unneeded, just a usea bool on AstStruct
-
- Ast_Flag_No_Clone = BH_BIT(19),
+ Ast_Flag_Type_Is_Resolved = BH_BIT(8),
- Ast_Flag_Cannot_Take_Addr = BH_BIT(20),
+ Ast_Flag_No_Clone = BH_BIT(9),
- Ast_Flag_Struct_Mem_Used = BH_BIT(21), // Unneeded, just a usea bool on AstStructMember
+ Ast_Flag_Cannot_Take_Addr = BH_BIT(10),
// HACK: NullProcHack
- Ast_Flag_Proc_Is_Null = BH_BIT(22),
+ Ast_Flag_Proc_Is_Null = BH_BIT(11),
- Ast_Flag_From_Polymorphism = BH_BIT(23),
+ Ast_Flag_From_Polymorphism = BH_BIT(12),
- Ast_Flag_Incomplete_Body = BH_BIT(24),
+ Ast_Flag_Incomplete_Body = BH_BIT(13),
- Ast_Flag_Array_Literal_Typed = BH_BIT(25),
+ Ast_Flag_Array_Literal_Typed = BH_BIT(14),
- Ast_Flag_Has_Been_Symres = BH_BIT(26),
+ Ast_Flag_Has_Been_Symres = BH_BIT(15),
- Ast_Flag_Has_Been_Checked = BH_BIT(27),
+ Ast_Flag_Has_Been_Checked = BH_BIT(16),
- Ast_Flag_Static_If_Resolved = BH_BIT(28),
+ Ast_Flag_Static_If_Resolved = BH_BIT(17),
- // :TEMPORARY
- Ast_Flag_Params_Introduced = BH_BIT(29),
-
- Ast_Flag_Symbol_Invisible = BH_BIT(30),
+ Ast_Flag_Symbol_Invisible = BH_BIT(18),
} AstFlags;
typedef enum UnaryOp {
struct Entity* entity_defaults;
b32 stcache_is_valid : 1;
+ b32 is_union : 1;
};
struct AstStructMember {
AstTyped_base;
AstTyped* initial_value;
bh_arr(AstTyped *) meta_tags;
+
+ b32 is_used : 1;
};
struct AstPolyStructParam {
AstTyped_base;
// NOTE: Used to cache the actual type for the same reason as above.
Type *etcache;
+
+ b32 is_flags : 1;
};
struct AstEnumValue { AstTyped_base; AstNumLit* value; };
struct AstTypeAlias { AstType_base; AstType* to; };
AstTyped *default_value;
VarArgKind vararg_kind;
+ b32 is_used : 1;
b32 use_processed : 1;
b32 is_baked : 1;
};
// NOTE: This is NULL, unless this function was generated from a polymorphic
// procedure call. Then it is set to the token of the call node.
OnyxToken* generated_from;
+ Scope* poly_scope;
// NOTE: This is NULL, unless this function is used in a "#export" directive.
// It is undefined which name it will have if there are multiple export directives
struct Entity* entity_header;
struct Entity* entity_body;
+
+ b32 is_exported : 1;
+ b32 is_foreign : 1;
+ b32 is_intrinsic : 1;
};
typedef struct OverloadOption OverloadOption;
struct AstSolidifiedFunction {
AstFunction* func;
- Scope* poly_scope;
b32 header_complete: 1;
};
Entity_Type_Polymorphic_Proc,
Entity_Type_Macro,
Entity_Type_Foreign_Function_Header,
- Entity_Type_Foreign_Global_Header,
Entity_Type_Function_Header,
Entity_Type_Global_Header,
Entity_Type_Process_Directive,
u32 next_tls_offset;
u32 next_elem_idx;
u32 foreign_function_count;
- u32 foreign_global_count;
i32 *stack_top_ptr;
i32 *tls_size_ptr;
"Polymorphic Proc",
"Macro",
"Foreign_Function Header",
- "Foreign_Global Header",
"Function Header",
"Global Header",
"Process Directive",
static OnyxToken builtin_tls_base_token = { Token_Type_Symbol, 10, "__tls_base ", { 0 } };
static OnyxToken builtin_tls_size_token = { Token_Type_Symbol, 10, "__tls_size ", { 0 } };
AstNumLit builtin_heap_start = { Ast_Kind_NumLit, Ast_Flag_Const, &builtin_heap_start_token, NULL, NULL, (AstType *) &basic_type_rawptr, NULL, 0 };
-AstGlobal builtin_stack_top = { Ast_Kind_Global, Ast_Flag_Global_Stack_Top, &builtin_stack_top_token, NULL, NULL, (AstType *) &basic_type_rawptr, NULL };
+AstGlobal builtin_stack_top = { Ast_Kind_Global, 0, &builtin_stack_top_token, NULL, NULL, (AstType *) &basic_type_rawptr, NULL };
AstGlobal builtin_tls_base = { Ast_Kind_Global, 0, &builtin_tls_base_token, NULL, NULL, (AstType *) &basic_type_rawptr, NULL };
AstGlobal builtin_tls_size = { Ast_Kind_Global, 0, &builtin_tls_size_token, NULL, NULL, (AstType *) &basic_type_u32, NULL };
// NOTE: If we are calling an intrinsic function, translate the
// call into an intrinsic call node.
- if (callee->flags & Ast_Flag_Intrinsic) {
+ if (callee->kind == Ast_Kind_Function && callee->is_intrinsic) {
call->kind = Ast_Kind_Intrinsic_Call;
call->callee = NULL;
}
CheckStatus check_function(AstFunction* func) {
- if (func->flags & Ast_Flag_Already_Checked) return Check_Success;
+ if (func->flags & Ast_Flag_Has_Been_Checked) return Check_Success;
if (func->entity_header && func->entity_header->state < Entity_State_Code_Gen)
YIELD(func->token->pos, "Waiting for procedure header to pass type-checking");
*expected_return_type = &basic_types[Basic_Kind_Void];
}
- func->flags |= Ast_Flag_Already_Checked;
+ func->flags |= Ast_Flag_Has_Been_Checked;
return Check_Success;
}
while (type->kind == Ast_Kind_Type_Alias)
type = ((AstTypeAlias *) type)->to;
- if (type->flags & Ast_Flag_Already_Checked) return Check_Success;
+ if (type->flags & Ast_Flag_Has_Been_Checked) return Check_Success;
switch (type->kind) {
case Ast_Kind_Poly_Call_Type: {
type = ((AstTypeAlias *) type)->to;
}
- type->flags |= Ast_Flag_Already_Checked;
+ type->flags |= Ast_Flag_Has_Been_Checked;
return Check_Success;
}
AstFunction* df = (AstFunction *) nn;
AstFunction* sf = (AstFunction *) node;
- if (sf->flags & Ast_Flag_Foreign) return node;
+ if (sf->is_foreign) return node;
df->return_type = (AstType *) ast_clone(a, sf->return_type);
df->body = (AstBlock *) ast_clone(a, sf->body);
new_param.local = (AstLocal *) ast_clone(a, param->local);
new_param.default_value = (AstTyped *) ast_clone(a, param->default_value);
new_param.vararg_kind = param->vararg_kind;
+ new_param.is_used = param->is_used;
bh_arr_push(df->params, new_param);
}
AstFunction* clone_function_header(bh_allocator a, AstFunction* func) {
if (func->kind != Ast_Kind_Function) return NULL;
- if (func->flags & Ast_Flag_Foreign) return func;
+ if (func->is_foreign) return func;
AstFunction* new_func = onyx_ast_node_new(a, sizeof(AstFunction), func->kind);
memmove(new_func, func, sizeof(AstFunction));
new_param.local = (AstLocal *) ast_clone(a, param->local);
new_param.default_value = (AstTyped *) ast_clone(a, param->default_value);
new_param.vararg_kind = param->vararg_kind;
+ new_param.is_used = param->is_used;
bh_arr_push(new_func->params, new_param);
}
}
case Ast_Kind_Function: {
- if ((node->flags & Ast_Flag_Foreign) != 0) {
+ if (((AstFunction *) node)->is_foreign != 0) {
ent.type = Entity_Type_Foreign_Function_Header;
ent.function = (AstFunction *) node;
ENTITY_INSERT(ent);
}
case Ast_Kind_Global: {
- if ((node->flags & Ast_Flag_Foreign) != 0) {
- ent.type = Entity_Type_Foreign_Global_Header;
- ent.global = (AstGlobal *) node;
- ENTITY_INSERT(ent);
-
- } else {
- ent.type = Entity_Type_Global_Header;
- ent.global = (AstGlobal *) node;
- ENTITY_INSERT(ent);
+ ent.type = Entity_Type_Global_Header;
+ ent.global = (AstGlobal *) node;
+ ENTITY_INSERT(ent);
- ent.id = entities->next_id++;
- ent.type = Entity_Type_Global;
- ent.global = (AstGlobal *) node;
- ENTITY_INSERT(ent);
- }
+ ent.id = entities->next_id++;
+ ent.type = Entity_Type_Global;
+ ent.global = (AstGlobal *) node;
+ ENTITY_INSERT(ent);
break;
}
while (parser->curr->type == '#') {
if (parser->hit_unexpected_token) return NULL;
- if (parse_possible_directive(parser, "union")) {
- s_node->flags |= Ast_Flag_Struct_Is_Union;
- }
+ if (parse_possible_directive(parser, "union")) s_node->is_union = 1;
else if (parse_possible_directive(parser, "align")) {
AstNumLit* numlit = parse_int_literal(parser);
mem->initial_value = initial_value;
mem->meta_tags = meta_tags;
- if (member_is_used) mem->flags |= Ast_Flag_Struct_Mem_Used;
+ if (member_is_used) mem->is_used = 1;
bh_arr_push(s_node->members, mem);
}
curr_param.local->kind = Ast_Kind_Param;
if (param_use) {
- curr_param.local->flags |= Ast_Flag_Param_Use;
+ curr_param.is_used = 1;
param_use = 0;
}
while (parser->curr->type == '#') {
if (parse_possible_directive(parser, "intrinsic")) {
- func_def->flags |= Ast_Flag_Intrinsic;
+ func_def->is_intrinsic = 1;
if (parser->curr->type == Token_Type_Literal_String) {
func_def->intrinsic_name = expect_token(parser, Token_Type_Literal_String);
func_def->foreign_module = expect_token(parser, Token_Type_Literal_String);
func_def->foreign_name = expect_token(parser, Token_Type_Literal_String);
- func_def->flags |= Ast_Flag_Foreign;
+ func_def->is_foreign = 1;
}
// HACK: NullProcHack
AstGlobal* global_node = make_node(AstGlobal, Ast_Kind_Global);
global_node->token = expect_token(parser, Token_Type_Keyword_Global);
- while (parser->curr->type == '#') {
- if (parse_possible_directive(parser, "foreign")) {
- global_node->foreign_module = expect_token(parser, Token_Type_Literal_String);
- global_node->foreign_name = expect_token(parser, Token_Type_Literal_String);
-
- global_node->flags |= Ast_Flag_Foreign;
- }
-
- else {
- OnyxToken* directive_token = expect_token(parser, '#');
- OnyxToken* symbol_token = expect_token(parser, Token_Type_Symbol);
-
- onyx_report_error(directive_token->pos, "unknown directive '#%b'.", symbol_token->text, symbol_token->length);
- }
- }
-
global_node->type_node = parse_type(parser);
ENTITY_SUBMIT(global_node);
while (parser->curr->type == '#') {
if (parse_possible_directive(parser, "flags")) {
- enum_node->flags |= Ast_Flag_Enum_Is_Flags;
+ enum_node->is_flags = 1;
} else {
OnyxToken* directive_token = expect_token(parser, '#');
OnyxToken* symbol_token = expect_token(parser, Token_Type_Symbol);
.type = Entity_Type_Function_Header,
.function = solidified_func.func,
.package = NULL,
- .scope = solidified_func.poly_scope,
+ .scope = solidified_func.func->poly_scope,
};
entity_bring_to_state(&func_header_entity, Entity_State_Code_Gen);
.type = Entity_Type_Function,
.function = solidified_func.func,
.package = NULL,
- .scope = solidified_func.poly_scope,
+ .scope = solidified_func.func->poly_scope,
};
Entity* entity_header = entity_heap_insert(&context.entities, func_header_entity);
OnyxFilePos poly_scope_pos = { 0 };
if (tkn) poly_scope_pos = tkn->pos;
- solidified_func.poly_scope = scope_create(context.ast_alloc, pp->poly_scope, poly_scope_pos);
- insert_poly_slns_into_scope(solidified_func.poly_scope, slns);
-
if (header_only) {
solidified_func.func = (AstFunction *) clone_function_header(context.ast_alloc, pp->base_func);
solidified_func.func->flags |= Ast_Flag_Incomplete_Body;
solidified_func.func = (AstFunction *) ast_clone(context.ast_alloc, pp->base_func);
}
+ solidified_func.func->poly_scope = scope_create(context.ast_alloc, pp->poly_scope, poly_scope_pos);
+ insert_poly_slns_into_scope(solidified_func.func->poly_scope, slns);
+
solidified_func.func->flags |= Ast_Flag_From_Polymorphism;
solidified_func.func->generated_from = tkn;
.type = Entity_Type_Function_Header,
.function = solidified_func.func,
.package = NULL,
- .scope = solidified_func.poly_scope,
+ .scope = solidified_func.func->poly_scope,
};
// HACK: Everything with entity_bring_to_state is a big hack...
goto struct_symres_done;
}
- if (member->flags & Ast_Flag_Struct_Mem_Used) {
+ if (member->is_used) {
AstType *used = (AstType *) member->type_node;
while (used->kind == Ast_Kind_Type_Alias) {
}
}
- if ((func->flags & Ast_Flag_Params_Introduced) == 0) {
- bh_arr_each(AstParam, param, func->params) {
- symbol_introduce(curr_scope, param->local->token, (AstNode *) param->local);
- }
-
- func->flags |= Ast_Flag_Params_Introduced;
- }
-
bh_arr_each(AstParam, param, func->params) {
+ symbol_introduce(curr_scope, param->local->token, (AstNode *) param->local);
+
if (param->local->type_node != NULL) {
SYMRES(type, ¶m->local->type_node);
}
// The 'use t : T' member requires completely knowing the type of T, to know which
// members should be brought in. At the moment, that requires completely building the
// type of Foo($T).
- if ((param->local->flags & Ast_Flag_Param_Use) != 0 && param->use_processed == 0) {
+ if (param->is_used && !param->use_processed) {
if (param->local->type_node != NULL && param->local->type == NULL) {
param->local->type = type_build_from_ast(context.ast_alloc, param->local->type_node);
type_build_from_ast(context.ast_alloc, (AstType *) enum_node);
- u64 next_assign_value = (enum_node->flags & Ast_Flag_Enum_Is_Flags) ? 1 : 0;
+ u64 next_assign_value = enum_node->is_flags ? 1 : 0;
bh_arr_each(AstEnumValue *, value, enum_node->values) {
symbol_introduce(enum_node->scope, (*value)->token, (AstNode *) *value);
(*value)->type = enum_node->etcache;
(*value)->flags |= Ast_Flag_Comptime;
- if (enum_node->flags & Ast_Flag_Enum_Is_Flags) {
+ if (enum_node->is_flags) {
next_assign_value <<= 1;
} else {
next_assign_value++;
AstDirectiveExport *export = (AstDirectiveExport *) directive;
SYMRES(expression, &export->export);
- export->export->flags |= Ast_Flag_Exported;
if (export->export->kind == Ast_Kind_Function) {
AstFunction *func = (AstFunction *) export->export;
func->exported_name = export->export_name;
+ func->is_exported = 1;
- if ((func->flags & Ast_Flag_Exported) != 0) {
- if ((func->flags & Ast_Flag_Foreign) != 0) {
+ if (func->is_exported) {
+ if (func->is_foreign) {
onyx_report_error(export->token->pos, "exporting a foreign function");
return Symres_Error;
}
- if ((func->flags & Ast_Flag_Intrinsic) != 0) {
+ if (func->is_intrinsic) {
onyx_report_error(export->token->pos, "exporting a intrinsic function");
return Symres_Error;
}
case Entity_Type_Function_Header: ss = symres_function_header(ent->function); break;
case Entity_Type_Function: ss = symres_function(ent->function); break;
- case Entity_Type_Foreign_Global_Header:
case Entity_Type_Global_Header: ss = symres_global(ent->global); break;
case Entity_Type_Use_Package:
s_node->stcache_is_valid = 1;
- b32 is_union = (s_node->flags & Ast_Flag_Struct_Is_Union) != 0;
+ b32 is_union = s_node->is_union;
u32 size = 0;
u32 offset = 0;
u32 alignment = 1, mem_alignment;
.name = bh_strdup(alloc, (*member)->token->text),
.initial_value = &(*member)->initial_value,
.included_through_use = 0,
- .used = (((*member)->flags & Ast_Flag_Struct_Mem_Used) != 0),
+ .used = (*member)->is_used,
.meta_tags = (*member)->meta_tags,
};
enum_type->ast_type = type_node;
enum_type->Enum.backing = enum_node->backing_type;
enum_type->Enum.name = enum_node->name;
- enum_type->Enum.is_flags = enum_node->flags & Ast_Flag_Enum_Is_Flags;
+ enum_type->Enum.is_flags = enum_node->is_flags;
type_register(enum_type);
return enum_type;
(AstNode *) ((AstArgument *) call->args.values[i])->value);
}
- if (template->flags & Ast_Flag_From_Polymorphism) {
- // SLOW DUMB HACKY WAY TO DO THIS!!!!! FIX IT!!!!!
-
- AstPolyProc* pp = (AstPolyProc *) macro->body;
- bh_table_each_start(AstSolidifiedFunction, pp->concrete_funcs);
-
- if (value.func == template) {
- scope_include(argument_scope, value.poly_scope, call->token->pos);
- break;
- }
-
- bh_table_each_end;
- }
+ if (template->poly_scope != NULL)
+ scope_include(argument_scope, template->poly_scope, call->token->pos);
*(AstNode **) pcall = subst;
return;
.type = Entity_Type_Function_Header,
.function = solidified_func.func,
.package = NULL,
- .scope = solidified_func.poly_scope,
+ .scope = solidified_func.func->poly_scope,
};
b32 successful = entity_bring_to_state(&func_header_entity, Entity_State_Code_Gen);
static inline b32 should_emit_function(AstFunction* fd) {
// NOTE: Don't output intrinsic functions
- if (fd->flags & Ast_Flag_Intrinsic) return 0;
+ if (fd->is_intrinsic) return 0;
// NOTE: Don't output functions that are not used, only if
// they are also not exported.
if ((fd->flags & Ast_Flag_Function_Used) == 0) {
- if (fd->flags & Ast_Flag_Exported) {
+ if (fd->is_exported) {
return 1;
} else {
return 0;
default: assert(("Invalid global type", 0)); break;
}
- bh_arr_set_at(module->globals, global_idx - module->foreign_global_count, glob);
+ bh_arr_set_at(module->globals, global_idx, glob);
if (global == &builtin_stack_top)
- module->stack_top_ptr = &module->globals[global_idx - module->foreign_global_count].initial_value[0].data.i1;
+ module->stack_top_ptr = &module->globals[global_idx].initial_value[0].data.i1;
if (global == &builtin_tls_size)
- module->tls_size_ptr = &module->globals[global_idx - module->foreign_global_count].initial_value[0].data.i1;
-}
-
-static void emit_foreign_global(OnyxWasmModule* module, AstGlobal* global) {
- WasmType global_type = onyx_type_to_wasm_type(global->type);
-
- if (global->flags & Ast_Flag_Foreign) {
- WasmImport import = {
- .kind = WASM_FOREIGN_GLOBAL,
- .idx = global_type,
- .mod = bh_aprintf(global_heap_allocator, "%b", global->foreign_module->text, global->foreign_module->length),
- .name = bh_aprintf(global_heap_allocator, "%b", global->foreign_name->text, global->foreign_name->length),
- };
-
- bh_arr_push(module->imports, import);
- }
+ module->tls_size_ptr = &module->globals[global_idx].initial_value[0].data.i1;
}
static void emit_string_literal(OnyxWasmModule* mod, AstStrLit* strlit) {
.stack_base_idx = 0,
.foreign_function_count = 0,
- .foreign_global_count = 0,
.null_proc_func_idx = -1,
};
}
break;
- case Entity_Type_Foreign_Global_Header:
- module->foreign_global_count++;
- emit_foreign_global(module, ent->global);
- // fallthrough
-
case Entity_Type_Global_Header:
bh_imap_put(&module->index_map, (u64) ent->global, module->next_global_idx++);
break;
bh_buffer_append(&vec_buff, leb, leb_len);
break;
- case WASM_FOREIGN_GLOBAL:
- leb = uint_to_uleb128((u64) import->idx, &leb_len);
- bh_buffer_append(&vec_buff, leb, leb_len);
-
- // NOTE: All foreign globals are mutable
- bh_buffer_write_byte(&vec_buff, 0x01);
- break;
-
case WASM_FOREIGN_MEMORY:
output_limits(import->min, import->max, import->shared, &vec_buff);
break;