diff --git a/releasenotes.md b/releasenotes.md index 564ea8ed2..b1a70fd9e 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -158,7 +158,8 @@ - Anonymous bitstructs check of duplicate member names fixed. - Assignment to anonymous bitstruct members in structs. - Fix casts on empty initializers. -- Fix to DString reserve +- Fix to DString reserve. +- Fix where aliases did not do arithmetic promotion. - @local declarations in generic modules available by accident. - Fixes missing checks to body arguments. - Do not create debug declaration for value-only parameter. diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 8d759d1c4..61ddc8cff 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -4,6 +4,7 @@ #include "compiler_internal.h" #include +#include "../utils/whereami.h" #define MAX_OUTPUT_FILES 1000000 #define MAX_MODULES 100000 @@ -981,3 +982,38 @@ const char *scratch_buffer_interned(void) fnv1a(scratch_buffer.str, scratch_buffer.len), &type); } +File *compile_and_invoke(const char *file, const char *args) +{ + char *name; + if (!file_namesplit(compiler_exe_name, &name, NULL)) + { + error_exit("Failed to extract file name from '%s'", compiler_exe_name); + } + const char *compiler_path = file_append_path(find_executable_path(), name); + scratch_buffer_clear(); + scratch_buffer_append(compiler_path); +#if (_MSC_VER) + const char *output = "__c3_exec.exe"; +#else + const char *output = "__c3_exec"; +#endif + scratch_buffer_printf(" compile %s -o %s", file, output); + const char *out; + if (!execute_cmd_failable(scratch_buffer_to_string(), &out)) + { + error_exit("Failed to compile script %s.", file); + } + DEBUG_LOG("EXEC OUT: %s", out); + scratch_buffer_clear(); +#if (!_MSC_VER) + scratch_buffer_append("./"); +#endif + scratch_buffer_append(output); + scratch_buffer_append(" "); + scratch_buffer_append(args); + if (!execute_cmd_failable(scratch_buffer_to_string(), &out)) + { + error_exit("Error invoking script %s with arguments %s.", file, args); + } + return source_file_text_load(file, out); +} \ No newline at end of file diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 4a03ab074..fef8084ac 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -2305,6 +2305,7 @@ File *source_file_by_id(FileId file); File *source_file_load(const char *filename, bool *already_loaded, const char **error); File *source_file_text_load(const char *filename, const char *content); +File *compile_and_invoke(const char *file, const char *args); void compiler_parse(void); void emit_json(void); diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index f020c57a2..c3d712e97 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -2077,13 +2077,14 @@ bool cast_widen_top_down(SemaContext *context, Expr *expr, Type *type) Type *cast_numeric_arithmetic_promotion(Type *type) { if (!type) return NULL; - switch (type->type_kind) + Type *canonical = type->canonical; + switch (canonical->type_kind) { case ALL_SIGNED_INTS: - if (type->builtin.bitsize < platform_target.width_c_int) return type_cint; + if (canonical->builtin.bitsize < platform_target.width_c_int) return type_cint; return type; case ALL_UNSIGNED_INTS: - if (type->builtin.bitsize < platform_target.width_c_int) return type_cuint; + if (canonical->builtin.bitsize < platform_target.width_c_int) return type_cuint; return type; case TYPE_F16: // Promote F16 to a real type. diff --git a/src/compiler/sema_passes.c b/src/compiler/sema_passes.c index d3190d110..e790541bf 100644 --- a/src/compiler/sema_passes.c +++ b/src/compiler/sema_passes.c @@ -198,15 +198,21 @@ static Decl **sema_run_exec(CompilationUnit *unit, Decl *decl) FOREACH_END(); sema_context_destroy(&context); if (!success) return NULL; - scratch_buffer_clear(); if (!expr_is_const_string(filename)) { SEMA_ERROR(filename, "A filename was expected as the first argument to '$exec'."); return NULL; } - scratch_buffer_append(filename->const_expr.bytes.ptr); - FOREACH_BEGIN(Expr *arg, decl->exec_decl.args) + scratch_buffer_clear(); + const char *file_str = filename->const_expr.bytes.ptr; + bool c3_script = str_has_suffix(file_str, ".c3"); + if (!c3_script) + { + scratch_buffer_append(file_str); scratch_buffer_append(" "); + } + FOREACH_BEGIN_IDX(i, Expr *arg, decl->exec_decl.args) + if (i) scratch_buffer_append(" "); assert(expr_is_const(arg)); switch (arg->const_expr.const_kind) { @@ -246,8 +252,16 @@ static Decl **sema_run_exec(CompilationUnit *unit, Decl *decl) } UNREACHABLE FOREACH_END(); - const char *output = execute_cmd(scratch_buffer_to_string()); - File *file = source_file_text_load(scratch_buffer_to_string(), output); + File *file; + if (c3_script) + { + file = compile_and_invoke(file_str, scratch_buffer_copy()); + } + else + { + const char *output = execute_cmd(scratch_buffer_to_string()); + file = source_file_text_load(scratch_buffer_to_string(), output); + } if (global_context.includes_used++ > MAX_INCLUDES) { SEMA_ERROR(decl, "This $include would cause the maximum number of includes (%d) to be exceeded.", MAX_INCLUDES); diff --git a/src/main.c b/src/main.c index ee7317e49..0dba24b8e 100644 --- a/src/main.c +++ b/src/main.c @@ -22,9 +22,11 @@ static void cleanup() memory_release(); } +const char *compiler_exe_name; int main_real(int argc, const char *argv[]) { + compiler_exe_name = argv[0]; bench_begin(); // Setjmp will allow us to add things like fuzzing with diff --git a/src/utils/file_utils.c b/src/utils/file_utils.c index 9d6431c6b..1d7d53cbf 100644 --- a/src/utils/file_utils.c +++ b/src/utils/file_utils.c @@ -611,6 +611,46 @@ const char *execute_cmd(const char *cmd) return str_trim(output); } +bool execute_cmd_failable(const char *cmd, const char **result) +{ + char buffer[BUFSIZE]; + char *output = ""; + FILE *process = NULL; +#if (_MSC_VER) + if (!(process = _wpopen(win_utf8to16(cmd), L"r"))) return false; +#else + if (!(process = popen(cmd, "r"))) return false; +#endif + while (fgets(buffer, BUFSIZE - 1, process)) + { + output = str_cat(output, buffer); + } +#if PLATFORM_WINDOWS + int err = _pclose(process); +#else + int err = pclose(process); +#endif + if (err) return false; + + while (output[0] != 0) + { + switch (output[0]) + { + case ' ': + case '\t': + case '\n': + case '\r': + output++; + continue; + default: + break; + } + break; + } + *result = str_trim(output); + return true; +} + #if PLATFORM_WINDOWS char *realpath(const char *path, char *const resolved_path) diff --git a/src/utils/lib.h b/src/utils/lib.h index dcc707c99..679b87c3d 100644 --- a/src/utils/lib.h +++ b/src/utils/lib.h @@ -15,6 +15,8 @@ const char *download_file(const char *url, const char *resource, const char *file_path); #endif +extern const char *compiler_exe_name; + typedef struct StringSlice_ { const char *ptr; @@ -84,6 +86,7 @@ void file_add_wildcard_files(const char ***files, const char *path, bool recursi const char *file_append_path(const char *path, const char *name); const char *execute_cmd(const char *cmd); +bool execute_cmd_failable(const char *cmd, const char **result); void *cmalloc(size_t size); void *ccalloc(size_t size, size_t elements); void memory_init(void); diff --git a/src/version.h b/src/version.h index fbe02ff0f..d6b603ef9 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.4.601" \ No newline at end of file +#define COMPILER_VERSION "0.4.602" \ No newline at end of file diff --git a/test/test_suite/cast/cast_narrow_alias.c3t b/test/test_suite/cast/cast_narrow_alias.c3t new file mode 100644 index 000000000..77b106e4e --- /dev/null +++ b/test/test_suite/cast/cast_narrow_alias.c3t @@ -0,0 +1,31 @@ +module abc; +def UInt8 = char; +fn void! main() +{ + UInt8 x = 17; + UInt8 y = 5; + UInt8 z = (x >> y) & 0x1; +} +/* #expect: abc.ll + +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-darwin" +; Function Attrs: nounwind +define i64 @abc.main() #0 { +entry: + %x = alloca i8, align 1 + %y = alloca i8, align 1 + %z = alloca i8, align 1 + store i8 17, ptr %x, align 1 + store i8 5, ptr %y, align 1 + %0 = load i8, ptr %x, align 1 + %zext = zext i8 %0 to i32 + %1 = load i8, ptr %y, align 1 + %zext1 = zext i8 %1 to i32 + %lshr = lshr i32 %zext, %zext1 + %2 = freeze i32 %lshr + %and = and i32 %2, 1 + %trunc = trunc i32 %and to i8 + store i8 %trunc, ptr %z, align 1 + ret i64 0 +}