mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
Compacted section list. Somewhat more controlled ctarg search.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.");
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.4.567"
|
||||
#define COMPILER_VERSION "0.4.568"
|
||||
15
test/test_suite/abi/macho_section.c3t
Normal file
15
test/test_suite/abi/macho_section.c3t
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user