From 8e37e54645d78f00c59fbbfd641f9adb498d6cad Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Fri, 20 Sep 2024 12:29:23 +0200 Subject: [PATCH] Add `env::COMPILER_BUILD_HASH` and `env::COMPILER_BUILD_DATE` --- lib/std/core/env.c3 | 2 + releasenotes.md | 1 + src/compiler/compiler.c | 89 ++++++++++++++++++++++++++------ src/compiler/compiler_internal.h | 5 +- src/compiler/expr.c | 17 +++++- src/compiler/sema_expr.c | 57 ++++++++++---------- src/compiler/sema_stmts.c | 3 +- 7 files changed, 123 insertions(+), 51 deletions(-) diff --git a/lib/std/core/env.c3 b/lib/std/core/env.c3 index fb590310f..06650385e 100644 --- a/lib/std/core/env.c3 +++ b/lib/std/core/env.c3 @@ -115,6 +115,8 @@ enum ArchType XTENSA, // Xtensa } +const String COMPILER_BUILD_HASH = $$BUILD_HASH; +const String COMPILER_BUILD_DATE = $$BUILD_DATE; const OsType OS_TYPE = (OsType)$$OS_TYPE; const ArchType ARCH_TYPE = (ArchType)$$ARCH_TYPE; const bool ARCH_32_BIT = $$REGISTER_SIZE == 32; diff --git a/releasenotes.md b/releasenotes.md index b86f16966..6b7104a40 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -14,6 +14,7 @@ - Support casting bitstructs to bool. - Allow user-defined attributes to have typed parameters. - Add `.gitkeep` files to project subfolders. +- Add `env::COMPILER_BUILD_HASH` and `env::COMPILER_BUILD_DATE` ### Fixes - Issue where a lambda wasn't correctly registered as external. #1408 diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 51f4096c6..187346c4a 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -11,7 +11,8 @@ #endif #if LLVM_AVAILABLE #include "c3_llvm.h" -#endif +#endif +#include "git_hash.h" #include #define MAX_OUTPUT_FILES 1000000 @@ -832,10 +833,18 @@ void compile_file_list(BuildOptions *options) compile(); } -static void setup_int_define(const char *id, uint64_t i, Type *type) +static inline void setup_define(const char *id, Expr *expr) { TokenType token_type = TOKEN_CONST_IDENT; id = symtab_add(id, (uint32_t) strlen(id), fnv1a(id, (uint32_t) strlen(id)), &token_type); + void *previous = htable_set(&compiler.context.compiler_defines, (void*)id, expr); + if (previous) + { + error_exit("Redefined ident %s", id); + } +} +static void setup_int_define(const char *id, uint64_t i, Type *type) +{ Type *flat = type_flatten(type); assert(type_is_integer(flat)); Expr *expr = expr_new_const_int(INVALID_SPAN, flat, i); @@ -844,23 +853,17 @@ static void setup_int_define(const char *id, uint64_t i, Type *type) { error_exit("Integer define %s overflow.", id); } - void *previous = htable_set(&compiler.context.compiler_defines, (void*)id, expr); - if (previous) - { - error_exit("Redefined ident %s", id); - } + setup_define(id, expr); +} + +static void setup_string_define(const char *id, const char *value) +{ + setup_define(id, expr_new_const_string(INVALID_SPAN, value)); } static void setup_bool_define(const char *id, bool value) { - TokenType token_type = TOKEN_CONST_IDENT; - id = symtab_add(id, (uint32_t) strlen(id), fnv1a(id, (uint32_t) strlen(id)), &token_type); - Expr *expr = expr_new_const_bool(INVALID_SPAN, type_bool, value); - void *previous = htable_set(&compiler.context.compiler_defines, (void *)id, expr); - if (previous) - { - error_exit("Redefined ident %s", id); - } + setup_define(id, expr_new_const_bool(INVALID_SPAN, type_bool, value)); } #if FETCH_AVAILABLE @@ -1228,6 +1231,59 @@ static void check_sanitizer_options(BuildTarget *target) } } +const char *compiler_date_to_iso(void) +{ + const char *comp_date = __DATE__; + static char iso[11] = "2000-01-01"; + iso[2] = comp_date[9]; + iso[3] = comp_date[10]; + int month; + switch (comp_date[0]) + { + case 'O': + month = 10; + break; + case 'D': + month = 12; + break; + case 'N': + month = 11; + break; + case 'J': + if (comp_date[1] == 'a') + { + month = 1; + break; + } + if (comp_date[2] == 'n') + { + month = 6; + break; + } + month = 7; + break; + case 'F': + month = 2; + break; + case 'A': + month = comp_date[2] == 'p' ? 4 : 8; + break; + case 'M': + month = comp_date[2] == 'r' ? 3 : 5; + break; + case 'S': + month = 9; + break; + default: + UNREACHABLE + } + iso[5] = month / 10 + '0'; + iso[6] = month % 10 + '0'; + iso[8] = comp_date[4] == ' ' ? '0' : comp_date[4]; + iso[9] = comp_date[5]; + return iso; +} + void compile() { symtab_init(compiler.build.symtab_size); @@ -1300,9 +1356,10 @@ void compile() setup_bool_define("ADDRESS_SANITIZER", compiler.build.feature.sanitize_address); setup_bool_define("MEMORY_SANITIZER", compiler.build.feature.sanitize_memory); setup_bool_define("THREAD_SANITIZER", compiler.build.feature.sanitize_thread); + setup_string_define("BUILD_HASH", GIT_HASH); + setup_string_define("BUILD_DATE", compiler_date_to_iso()); type_init_cint(); - compiler_init_time = bench_mark(); if (!vec_size(compiler.build.sources) && !compiler.build.read_stdin) error_exit("No files to compile."); diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 334cbb0fc..7277e4a21 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -2168,6 +2168,7 @@ Expr *expr_new(ExprKind kind, SourceSpan start); Expr *expr_new_const_int(SourceSpan span, Type *type, uint64_t v); Expr *expr_new_const_bool(SourceSpan span, Type *type, bool value); Expr *expr_new_const_typeid(SourceSpan span, Type *type); +Expr *expr_new_const_string(SourceSpan span, const char *string); bool expr_is_simple(Expr *expr, bool to_float); bool expr_is_pure(Expr *expr); bool expr_is_runtime_const(Expr *expr); @@ -2207,10 +2208,10 @@ INLINE void expr_rewrite_const_int(Expr *expr, Type *type, uint64_t v); INLINE void expr_rewrite_const_typeid(Expr *expr, Type *type); INLINE void expr_rewrite_const_initializer(Expr *expr, Type *type, ConstInitializer *initializer); INLINE void expr_rewrite_const_untyped_list(Expr *expr, Expr **elements); +void expr_rewrite_const_string(Expr *expr_to_rewrite, const char *string); +void expr_rewrite_const_ref(Expr *expr_to_rewrite, Decl *decl); void expr_rewrite_to_builtin_access(Expr *expr, Expr *parent, BuiltinAccessKind kind, Type *type); -void expr_rewrite_to_string(Expr *expr_to_rewrite, const char *string); -void expr_rewrite_to_const_ref(Expr *expr_to_rewrite, Decl *decl); void expr_rewrite_to_const_zero(Expr *expr, Type *type); bool expr_rewrite_to_const_initializer_index(Type *list_type, ConstInitializer *list, Expr *result, unsigned index, bool from_back); diff --git a/src/compiler/expr.c b/src/compiler/expr.c index 1f2634583..618958f71 100644 --- a/src/compiler/expr.c +++ b/src/compiler/expr.c @@ -863,6 +863,19 @@ Expr *expr_new_const_bool(SourceSpan span, Type *type, bool value) return expr; } +Expr *expr_new_const_string(SourceSpan span, const char *string) +{ + Expr *expr = expr_calloc(); + expr->expr_kind = EXPR_CONST; + expr->span = span; + expr->type = type_string; + expr->const_expr.const_kind = CONST_STRING; + expr->const_expr.bytes.ptr = string; + expr->const_expr.bytes.len = strlen(string); + expr->resolve_status = RESOLVE_DONE; + return expr; +} + void expr_rewrite_to_builtin_access(Expr *expr, Expr *parent, BuiltinAccessKind kind, Type *type) { expr->expr_kind = EXPR_BUILTIN_ACCESS; @@ -915,7 +928,7 @@ void expr_rewrite_insert_deref(Expr *original) } } -void expr_rewrite_to_const_ref(Expr *expr_to_rewrite, Decl *decl) +void expr_rewrite_const_ref(Expr *expr_to_rewrite, Decl *decl) { expr_to_rewrite->const_expr = (ExprConst) { .global_ref = decl, @@ -924,7 +937,7 @@ void expr_rewrite_to_const_ref(Expr *expr_to_rewrite, Decl *decl) expr_to_rewrite->expr_kind = EXPR_CONST; } -void expr_rewrite_to_string(Expr *expr_to_rewrite, const char *string) +void expr_rewrite_const_string(Expr *expr_to_rewrite, const char *string) { expr_to_rewrite->expr_kind = EXPR_CONST; expr_to_rewrite->const_expr.const_kind = CONST_STRING; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 26b8c4f75..04a5cafc5 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -3418,7 +3418,7 @@ static inline bool sema_expr_replace_with_enum_name_array(SemaContext *context, { Decl *decl = values[i]; Expr *expr = expr_new(EXPR_CONST, span); - expr_rewrite_to_string(expr, decl->name); + expr_rewrite_const_string(expr, decl->name); vec_add(element_values, expr); } initializer->initializer_list = element_values; @@ -3579,7 +3579,7 @@ static inline bool sema_expr_analyse_member_access(SemaContext *context, Expr *e case TYPE_PROPERTY_QNAMEOF: break; case TYPE_PROPERTY_NAMEOF: - expr_rewrite_to_string(expr, decl->name ? decl->name : ""); + expr_rewrite_const_string(expr, decl->name ? decl->name : ""); return true; case TYPE_PROPERTY_ALIGNOF: expr_rewrite_const_int(expr, type_usz, @@ -3850,8 +3850,7 @@ static inline bool sema_create_const_paramsof(SemaContext *context, Expr *expr, for (unsigned i = 0; i < params; i++) { Decl *decl = sig->params[i]; - Expr *name_expr = expr_new(EXPR_CONST, span); - expr_rewrite_to_string(name_expr, decl->name ? decl->name : ""); + Expr *name_expr = expr_new_const_string(span, decl->name ? decl->name : ""); Expr *type_expr = expr_new(EXPR_CONST, span); expr_rewrite_const_typeid(type_expr, decl->type->canonical); Expr *values[] = { name_expr, type_expr }; @@ -4787,7 +4786,7 @@ static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr, bo { if (sema_cast_const(current_parent)) { - expr_rewrite_to_string(expr, current_parent->const_expr.enum_err_val->name); + expr_rewrite_const_string(expr, current_parent->const_expr.enum_err_val->name); return true; } else @@ -4800,7 +4799,7 @@ static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr, bo { if (sema_cast_const(current_parent)) { - expr_rewrite_to_string(expr, current_parent->const_expr.enum_err_val->name); + expr_rewrite_const_string(expr, current_parent->const_expr.enum_err_val->name); return true; } expr_rewrite_to_builtin_access(expr, current_parent, ACCESS_FAULTNAME, type_string); @@ -6737,7 +6736,7 @@ static inline bool sema_expr_analyse_addr(SemaContext *context, Expr *expr, bool Decl *ident = inner->identifier_expr.decl; if (decl_is_global(ident)) { - expr_rewrite_to_const_ref(expr, ident); + expr_rewrite_const_ref(expr, ident); return true; } } @@ -7437,35 +7436,35 @@ static inline bool sema_expr_analyse_compiler_const(SemaContext *context, Expr * switch (def) { case BUILTIN_DEF_TIME: - expr_rewrite_to_string(expr, time_get()); + expr_rewrite_const_string(expr, time_get()); return true; case BUILTIN_DEF_DATE: - expr_rewrite_to_string(expr, date_get()); + expr_rewrite_const_string(expr, date_get()); return true; case BUILTIN_DEF_FILE: if (context->call_env.current_function) { - expr_rewrite_to_string(expr, context->call_env.current_function->unit->file->name); + expr_rewrite_const_string(expr, context->call_env.current_function->unit->file->name); return true; } - expr_rewrite_to_string(expr, context->compilation_unit->file->name); + expr_rewrite_const_string(expr, context->compilation_unit->file->name); return true; case BUILTIN_DEF_FILEPATH: if (context->call_env.current_function) { - expr_rewrite_to_string(expr, context->call_env.current_function->unit->file->full_path); + expr_rewrite_const_string(expr, context->call_env.current_function->unit->file->full_path); return true; } - expr_rewrite_to_string(expr, context->compilation_unit->file->full_path); + expr_rewrite_const_string(expr, context->compilation_unit->file->full_path); return true; case BUILTIN_DEF_MODULE: if (context->original_module) { - expr_rewrite_to_string(expr, context->original_module->name->module); + expr_rewrite_const_string(expr, context->original_module->name->module); } else { - expr_rewrite_to_string(expr, context->compilation_unit->module->name->module); + expr_rewrite_const_string(expr, context->compilation_unit->module->name->module); } return true; case BUILTIN_DEF_LINE: @@ -7502,7 +7501,7 @@ static inline bool sema_expr_analyse_compiler_const(SemaContext *context, Expr * switch (context->call_env.kind) { case CALL_ENV_GLOBAL_INIT: - expr_rewrite_to_string(expr, ""); + expr_rewrite_const_string(expr, ""); return true; case CALL_ENV_FUNCTION_STATIC: case CALL_ENV_FUNCTION: @@ -7515,14 +7514,14 @@ static inline bool sema_expr_analyse_compiler_const(SemaContext *context, Expr * scratch_buffer_append(func_type->type->name); scratch_buffer_append_char('.'); scratch_buffer_append(current_func->name); - expr_rewrite_to_string(expr, scratch_buffer_copy()); + expr_rewrite_const_string(expr, scratch_buffer_copy()); return true; } - expr_rewrite_to_string(expr, current_func->name); + expr_rewrite_const_string(expr, current_func->name); return true; } case CALL_ENV_ATTR: - expr_rewrite_to_string(expr, ""); + expr_rewrite_const_string(expr, ""); return true; } UNREACHABLE @@ -7815,18 +7814,18 @@ static inline void sema_expr_rewrite_to_type_nameof(Expr *expr, Type *type, Toke if (type_is_user_defined(type)) { scratch_buffer_set_extern_decl_name(type->decl, true); - expr_rewrite_to_string(expr, scratch_buffer_copy()); + expr_rewrite_const_string(expr, scratch_buffer_copy()); } else { - expr_rewrite_to_string(expr, type->name); + expr_rewrite_const_string(expr, type->name); } return; } if (name_type == TOKEN_CT_NAMEOF || type_is_builtin(type->type_kind)) { - expr_rewrite_to_string(expr, type->name); + expr_rewrite_const_string(expr, type->name); return; } scratch_buffer_clear(); @@ -7838,7 +7837,7 @@ static inline void sema_expr_rewrite_to_type_nameof(Expr *expr, Type *type, Toke scratch_buffer_append("::"); } scratch_buffer_append(type->name); - expr_rewrite_to_string(expr, scratch_buffer_copy()); + expr_rewrite_const_string(expr, scratch_buffer_copy()); } static inline bool sema_expr_analyse_ct_nameof(SemaContext *context, Expr *expr) @@ -7914,19 +7913,19 @@ static inline bool sema_expr_analyse_ct_nameof(SemaContext *context, Expr *expr) } RETURN_CT: scratch_buffer_set_extern_decl_name(decl, true); - expr_rewrite_to_string(expr, scratch_buffer_to_string()); + expr_rewrite_const_string(expr, scratch_buffer_to_string()); return true; } if (!decl->unit || name_type == TOKEN_CT_NAMEOF || decl_is_var_local(decl)) { - expr_rewrite_to_string(expr, decl->name); + expr_rewrite_const_string(expr, decl->name); return true; } scratch_buffer_clear(); scratch_buffer_append(decl->unit->module->name->module); scratch_buffer_append("::"); scratch_buffer_append(decl->name); - expr_rewrite_to_string(expr, scratch_buffer_copy()); + expr_rewrite_const_string(expr, scratch_buffer_copy()); return true; } @@ -8267,7 +8266,7 @@ static inline bool sema_expr_analyse_lambda(SemaContext *context, Type *target_t if (decl_cached) { expr->type = type_get_func_ptr(decl_cached->type); - expr_rewrite_to_const_ref(expr, decl_cached); + expr_rewrite_const_ref(expr, decl_cached); return true; } } @@ -8367,7 +8366,7 @@ static inline bool sema_expr_analyse_lambda(SemaContext *context, Type *target_t vec_add(original->func_decl.generated_lambda, decl); } decl->resolve_status = RESOLVE_DONE; - expr_rewrite_to_const_ref(expr, decl); + expr_rewrite_const_ref(expr, decl); return true; FAIL_NO_INFER: SEMA_ERROR(expr, "Inferred lambda expressions cannot be used unless the type can be determined."); @@ -8778,7 +8777,7 @@ static inline bool sema_expr_analyse_ct_stringify(SemaContext *context, Expr *ex SEMA_ERROR(expr, "Failed to stringify hash variable contents - they must be a single line and not exceed 255 characters."); return false; } - expr_rewrite_to_string(expr, desc); + expr_rewrite_const_string(expr, desc); return true; } diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index 25f051a0d..367c1e2c9 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -328,8 +328,7 @@ static inline bool assert_create_from_contract(SemaContext *context, Ast *direct Ast *assert = new_ast(AST_ASSERT_STMT, expr->span); assert->assert_stmt.is_ensure = true; assert->assert_stmt.expr = exprid(expr); - Expr *comment_expr = expr_new(EXPR_CONST, expr->span); - expr_rewrite_to_string(comment_expr, comment); + Expr *comment_expr = expr_new_const_string(expr->span, comment); assert->assert_stmt.message = exprid(comment_expr); ast_append(asserts, assert); }