From 4325d017c8e7a288d6e687652776d9c80e9e3ff7 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sat, 15 Jul 2023 16:31:53 +0200 Subject: [PATCH] Compacted section list. Somewhat more controlled ctarg search. --- src/compiler/compiler.c | 20 +++++++++++++++++++ src/compiler/compiler_internal.h | 28 +++++++++++++-------------- src/compiler/llvm_codegen.c | 4 ++-- src/compiler/llvm_codegen_function.c | 4 ++-- src/compiler/sema_decls.c | 2 +- src/compiler/sema_expr.c | 25 +++++++++++++++--------- src/compiler/sema_internal.h | 2 +- src/compiler/sema_types.c | 2 +- src/version.h | 2 +- test/test_suite/abi/macho_section.c3t | 15 ++++++++++++++ 10 files changed, 72 insertions(+), 32 deletions(-) create mode 100644 test/test_suite/abi/macho_section.c3t diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 2e016d5e3..5b3a1091c 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -49,6 +49,7 @@ void compiler_init(const char *std_lib_dir) global_context.module_list = NULL; global_context.generic_module_list = NULL; global_context.method_extensions = NULL; + global_context.section_list = NULL; vmem_init(&ast_arena, 512); ast_calloc(); vmem_init(&expr_arena, 512); @@ -874,6 +875,25 @@ void global_context_add_generic_decl(Decl *decl) decltable_set(&global_context.generic_symbols, decl); } +SectionId global_context_register_section(const char *section) +{ + scratch_buffer_clear(); + scratch_buffer_append("SECTION#"); + scratch_buffer_append(section); + TokenType type = TOKEN_INVALID_TOKEN; + const char *result = scratch_buffer_interned(); + FOREACH_BEGIN_IDX(i, const char *candidate, global_context.section_list) + if (result == candidate) return i + 1; + FOREACH_END(); + unsigned len = vec_size(global_context.section_list); + if (len >= MAX_SECTIONS) + { + error_exit("Too many sections in source, max %d allowed.", MAX_SECTIONS); + } + vec_add(global_context.section_list, result); + return len + 1; +} + void global_context_clear_errors(void) { global_context.in_panic_mode = false; diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 9267be9e7..e9f750c2f 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -24,7 +24,10 @@ typedef uint32_t AlignSize; typedef int32_t ScopeId; typedef uint32_t ArraySize; typedef uint64_t BitSize; +typedef uint16_t SectionId; +#define MAX_SECTIONS 0xFFFE +#define SECTION_PREFIX_LEN 8 #define MAX_FIXUPS 0xFFFFF #define MAX_HASH_SIZE (512 * 1024 * 1024) #define INVALID_SPAN ((SourceSpan){ .row = 0 }) @@ -678,24 +681,13 @@ typedef struct Decl_ AlignSize alignment; union { - const char *section; - ExprId varef_id; + SectionId section_id; + uint16_t va_index; }; AlignSize offset : 32; AlignSize padding : 32; - /* bool is_exported : 1; - bool is_used : 1; - bool is_used_public : 1; - bool has_cname : 1; - uint32_t alignment : 5; - union - { - uint32_t offset; - uint32_t counter; - }; - uint32_t size;*/ struct CompilationUnit_ *unit; - Attr** attributes; + Attr **attributes; Type *type; union { @@ -734,7 +726,6 @@ typedef struct Decl_ - typedef struct { bool start_from_end : 1; @@ -1725,6 +1716,7 @@ typedef struct Decl *decl_stack[MAX_GLOBAL_DECL_STACK]; Decl **decl_stack_bottom; Decl **decl_stack_top; + const char **section_list; } GlobalContext; @@ -2106,6 +2098,8 @@ void global_context_clear_errors(void); void global_context_add_type(Type *type); void global_context_add_decl(Decl *type_decl); void global_context_add_generic_decl(Decl *decl); +SectionId global_context_register_section(const char *section); +INLINE const char *section_from_id(SectionId id); Module *compiler_find_or_create_module(Path *module_name, const char **parameters); Module *global_context_find_module(const char *name); @@ -3397,3 +3391,7 @@ INLINE bool expr_is_const_member(Expr *expr) return expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_MEMBER; } +INLINE const char *section_from_id(SectionId id) +{ + return id ? global_context.section_list[id - 1] + SECTION_PREFIX_LEN : NULL; +} diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 88626ec73..4d9fe3b39 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -427,9 +427,9 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl) LLVMSetUnnamedAddress(decl->backend_ref, decl_is_local(decl) ? LLVMGlobalUnnamedAddr : LLVMLocalUnnamedAddr); } - if (decl->section) + if (decl->section_id) { - LLVMSetSection(global_ref, decl->section); + LLVMSetSection(global_ref, section_from_id(decl->section_id)); } llvm_set_global_tls(decl); diff --git a/src/compiler/llvm_codegen_function.c b/src/compiler/llvm_codegen_function.c index 8356b1461..c7ca45220 100644 --- a/src/compiler/llvm_codegen_function.c +++ b/src/compiler/llvm_codegen_function.c @@ -716,9 +716,9 @@ void llvm_emit_function_decl(GenContext *c, Decl *decl) LLVMValueRef function = llvm_get_ref(c, decl); decl->backend_ref = function; - if (decl->section) + if (decl->section_id) { - LLVMSetSection(function, decl->section); + LLVMSetSection(function, section_from_id(decl->section_id)); } if (llvm_use_debug(c)) { diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 857fef03b..25af9d8c4 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -1830,7 +1830,7 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, { case ATTRIBUTE_SECTION: if (!sema_check_section(context, attr)) return false; - decl->section = expr->const_expr.bytes.ptr; + decl->section_id = global_context_register_section(expr->const_expr.bytes.ptr); break; case ATTRIBUTE_EXTERN: decl->has_extname = true; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 3d57d293f..4cea1111b 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -213,7 +213,7 @@ static inline bool sema_constant_fold_ops(Expr *expr) UNREACHABLE } -Expr *sema_expr_analyse_ct_arg_index(SemaContext *context, Expr *index_expr) +Expr *sema_expr_analyse_ct_arg_index(SemaContext *context, Expr *index_expr, unsigned *index_ref) { unsigned args = vec_size(context->macro_varargs); uint64_t index; @@ -241,6 +241,7 @@ Expr *sema_expr_analyse_ct_arg_index(SemaContext *context, Expr *index_expr) SEMA_ERROR(index_expr, "Only %u vararg%s exist.", args, args == 1 ? "" : "s"); return poisoned_expr; } + if (index_ref) *index_ref = (unsigned)index_val.i.low; return context->macro_varargs[(size_t)index_val.i.low]; } @@ -7292,14 +7293,17 @@ static inline bool sema_expr_analyse_ct_arg(SemaContext *context, Expr *expr) return true; case TOKEN_CT_VAARG: { + unsigned index; // A normal argument, this means we only evaluate it once. - ASSIGN_EXPR_OR_RET(Expr *arg_expr, sema_expr_analyse_ct_arg_index(context, exprptr(expr->ct_arg_expr.arg)), false); + ASSIGN_EXPR_OR_RET(Expr *arg_expr, sema_expr_analyse_ct_arg_index(context, exprptr(expr->ct_arg_expr.arg), &index), false); + index++; + assert(index < 0x10000); Decl *decl = NULL; // Try to find the original param. FOREACH_BEGIN(Decl *val, context->macro_params) if (!val) continue; - if (val->var.init_expr == arg_expr) + if (val->va_index == index && val->var.kind == VARDECL_PARAM) { decl = val; break; @@ -7310,6 +7314,7 @@ static inline bool sema_expr_analyse_ct_arg(SemaContext *context, Expr *expr) { decl = decl_new_generated_var(arg_expr->type, VARDECL_PARAM, arg_expr->span); decl->var.init_expr = arg_expr; + decl->va_index = (uint16_t)index; vec_add(context->macro_params, decl); } // Replace with the identifier. @@ -7320,14 +7325,14 @@ static inline bool sema_expr_analyse_ct_arg(SemaContext *context, Expr *expr) case TOKEN_CT_VAEXPR: { // An expr argument, this means we copy and evaluate. - ASSIGN_EXPR_OR_RET(Expr *arg_expr, sema_expr_analyse_ct_arg_index(context, exprptr(expr->ct_arg_expr.arg)), false); + ASSIGN_EXPR_OR_RET(Expr *arg_expr, sema_expr_analyse_ct_arg_index(context, exprptr(expr->ct_arg_expr.arg), NULL), false); expr_replace(expr, copy_expr_single(arg_expr)); return true; } case TOKEN_CT_VACONST: { // An expr argument, this means we copy and evaluate. - ASSIGN_EXPR_OR_RET(Expr *arg_expr, sema_expr_analyse_ct_arg_index(context, exprptr(expr->ct_arg_expr.arg)), false); + ASSIGN_EXPR_OR_RET(Expr *arg_expr, sema_expr_analyse_ct_arg_index(context, exprptr(expr->ct_arg_expr.arg), NULL), false); arg_expr = copy_expr_single(arg_expr); if (!expr_is_constant_eval(arg_expr, CONSTANT_EVAL_CONSTANT_VALUE)) { @@ -7340,16 +7345,18 @@ static inline bool sema_expr_analyse_ct_arg(SemaContext *context, Expr *expr) case TOKEN_CT_VAREF: { // A normal argument, this means we only evaluate it once. - ASSIGN_EXPR_OR_RET(Expr *arg_expr, sema_expr_analyse_ct_arg_index(context, exprptr(expr->ct_arg_expr.arg)), false); + unsigned index; + ASSIGN_EXPR_OR_RET(Expr *arg_expr, sema_expr_analyse_ct_arg_index(context, exprptr(expr->ct_arg_expr.arg), &index), false); if (!sema_binary_is_expr_lvalue(arg_expr, arg_expr)) return false; + index++; + assert(index < 0x10000); - ExprId va_ref_id = exprid(arg_expr); Decl *decl = NULL; // Try to find the original param. FOREACH_BEGIN(Decl *val, context->macro_params) if (!val) continue; - if (val->var.kind == VARDECL_PARAM_REF && val->varef_id == va_ref_id) + if (val->var.kind == VARDECL_PARAM_REF && val->va_index == index) { decl = val; break; @@ -7362,7 +7369,7 @@ static inline bool sema_expr_analyse_ct_arg(SemaContext *context, Expr *expr) expr_insert_addr(arg_expr); decl = decl_new_generated_var(arg_expr->type, VARDECL_PARAM_REF, arg_expr->span); decl->var.init_expr = arg_expr; - decl->varef_id = va_ref_id; + decl->va_index = (uint16_t)index; vec_add(context->macro_params, decl); } // Replace with the identifier. diff --git a/src/compiler/sema_internal.h b/src/compiler/sema_internal.h index 3af453b20..f6ab9bd1f 100644 --- a/src/compiler/sema_internal.h +++ b/src/compiler/sema_internal.h @@ -73,7 +73,7 @@ Decl *sema_find_operator(SemaContext *context, Expr *expr, OperatorOverload oper bool sema_insert_method_call(SemaContext *context, Expr *method_call, Decl *method_decl, Expr *parent, Expr **arguments); bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *expr); bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *struct_var, Decl *decl, bool optional); -Expr *sema_expr_analyse_ct_arg_index(SemaContext *context, Expr *index_expr); +Expr *sema_expr_analyse_ct_arg_index(SemaContext *context, Expr *index_expr, unsigned *index_ref); Expr *sema_ct_eval_expr(SemaContext *c, bool is_type, Expr *inner, bool report_missing); bool sema_analyse_asm(SemaContext *context, AsmInlineBlock *block, Ast *asm_stmt); bool sema_bit_assignment_check(Expr *right, Decl *member); diff --git a/src/compiler/sema_types.c b/src/compiler/sema_types.c index cbccf6483..406a3a722 100644 --- a/src/compiler/sema_types.c +++ b/src/compiler/sema_types.c @@ -302,7 +302,7 @@ INLINE bool sema_resolve_vatype(SemaContext *context, TypeInfo *type_info) { RETURN_SEMA_ERROR(type_info, "'%s' can only be used inside of a macro.", token_type_to_string(TOKEN_CT_VATYPE)); } - ASSIGN_EXPR_OR_RET(Expr *arg_expr, sema_expr_analyse_ct_arg_index(context, type_info->unresolved_type_expr), + ASSIGN_EXPR_OR_RET(Expr *arg_expr, sema_expr_analyse_ct_arg_index(context, type_info->unresolved_type_expr, NULL), false); if (arg_expr->expr_kind != EXPR_TYPEINFO) RETURN_SEMA_ERROR(arg_expr, "The argument was not a type."); diff --git a/src/version.h b/src/version.h index b43b05c05..e228f7147 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.4.567" \ No newline at end of file +#define COMPILER_VERSION "0.4.568" \ No newline at end of file diff --git a/test/test_suite/abi/macho_section.c3t b/test/test_suite/abi/macho_section.c3t new file mode 100644 index 000000000..49c5e75d4 --- /dev/null +++ b/test/test_suite/abi/macho_section.c3t @@ -0,0 +1,15 @@ +// #target: macos-x64 +module test; + +int z @section("__TEXT,__custoection"); +int w @section("__TEXT,__custoection"); + +fn void main() +{ + int a = z + w; +} + +/* #expect: test.ll + +@test.z = local_unnamed_addr global i32 0, section "__TEXT,__custoection", align 4 +@test.w = local_unnamed_addr global i32 0, section "__TEXT,__custoection", align 4