Compare commits

..

10 Commits

Author SHA1 Message Date
Christoffer Lerno
82c3facb65 --obj, --emit-stdlib, --strip-unused 2023-06-09 09:37:07 +02:00
Christoffer Lerno
266dba466c Rename to no-emit-stdlib 2023-06-06 15:25:25 +02:00
Christoffer Lerno
379a5f670f Add no-obj and no-stdlib-codegen options. 2023-06-06 15:22:28 +02:00
Christoffer Lerno
8eaad81800 Dead strip by default. Add list to_string. Fix missing check for dynamic calls. 2023-06-05 14:54:17 +02:00
Christoffer Lerno
4baacc7d52 Formatting. 2023-06-03 12:08:11 +02:00
Christoffer Lerno
0de47d7c83 Ensure panic functions are never stripped. 2023-06-02 23:19:54 +02:00
Christoffer Lerno
cfd21f8ca2 Windows thread pool. 2023-06-02 23:19:54 +02:00
Christoffer Lerno
d0e8944c56 Updated task pool. 2023-06-02 21:58:25 +02:00
Christoffer Lerno
3e54d13b62 Prefer def 2023-06-02 20:08:45 +02:00
Christoffer Lerno
b30d130d92 Configurable Linux crt/crtbegin paths. 2023-05-31 21:26:23 +02:00
86 changed files with 516 additions and 229 deletions

View File

@@ -184,7 +184,7 @@ jobs:
fail-fast: false
matrix:
build_type: [Release, Debug]
llvm_version: [16]
llvm_version: [16, 17]
steps:
- uses: actions/checkout@v3

View File

@@ -38,6 +38,26 @@ fn void List.tinit(List* list, usz initial_capacity = 16)
list.init(initial_capacity, mem::temp()) @inline;
}
fn String List.to_string(List* list, Allocator* using = mem::heap()) @dynamic
{
if (!list.size) return "[]".copy(using);
if (list.size == 1) return string::printf("[%s]", list.entries[0], .using = using);
@stack_mem(512 + 128; Allocator* mem)
{
DString str;
str.init(512, mem);
str.append("[");
foreach (i, element : list.entries[:list.size])
{
if (i != 0) str.append(", ");
str.printf("%s", element);
}
str.printf("]");
return str.copy_str(using);
};
}
fn void List.push(List* list, Type element) @inline
{
list.append(element);

View File

@@ -135,9 +135,9 @@ macro bool! Formatter.print_with_function(Formatter* this, any arg)
this.width = old_width;
this.prec = old_prec;
}
@pool()
@stack_mem(512; Allocator* mem)
{
this.out_substr(arg.to_string(mem::temp()))!;
this.out_substr(arg.to_string(mem))!;
return true;
};
}

View File

@@ -50,18 +50,18 @@ fn void! InetAddress.to_format(InetAddress* addr, Formatter* formatter) @dynamic
formatter.printf("%d.%d.%d.%d", addr.ipv4.a, addr.ipv4.b, addr.ipv4.c, addr.ipv4.d)!;
}
fn String! InetAddress.to_string(InetAddress* addr, Allocator* using = mem::heap()) @dynamic
fn String InetAddress.to_string(InetAddress* addr, Allocator* using = mem::heap()) @dynamic
{
if (addr.is_ipv6)
{
char[8 * 5 + 1] buffer;
String res = (String)io::bprintf(&buffer, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
addr.ipv6.a, addr.ipv6.b, addr.ipv6.c, addr.ipv6.d,
addr.ipv6.e, addr.ipv6.f, addr.ipv6.g, addr.ipv6.h)!;
addr.ipv6.e, addr.ipv6.f, addr.ipv6.g, addr.ipv6.h)!!;
return res.copy(using);
}
char[3 * 4 + 3 + 1] buffer;
String res = (String)io::bprintf(&buffer, "%d.%d.%d.%d", addr.ipv4.a, addr.ipv4.b, addr.ipv4.c, addr.ipv4.d)!;
String res = (String)io::bprintf(&buffer, "%d.%d.%d.%d", addr.ipv4.a, addr.ipv4.b, addr.ipv4.c, addr.ipv4.d)!!;
return res.copy(using);
}

View File

@@ -2,7 +2,7 @@ module std::thread::os;
$if thread::THREAD_MODEL == ThreadModel.WIN32:
typedef NativeThread = Win32_HANDLE;
def NativeThread = Win32_HANDLE;
struct NativeMutex
{

View File

@@ -8,8 +8,8 @@ struct Darwin_mach_timebase_info
uint denom;
}
typedef Darwin_mach_timebase_info_t = Darwin_mach_timebase_info;
typedef Darwin_mach_timebase_info_data_t = Darwin_mach_timebase_info;
def Darwin_mach_timebase_info_t = Darwin_mach_timebase_info;
def Darwin_mach_timebase_info_data_t = Darwin_mach_timebase_info;
extern fn void mach_timebase_info(Darwin_mach_timebase_info_data_t* timebase);
extern fn ulong mach_absolute_time();

View File

@@ -1,9 +1,9 @@
module std::time;
typedef Time @inline = distinct long;
typedef TimeDuration @inline = distinct long;
typedef Clock @inline = distinct ulong;
typedef NanoDuration @inline = distinct long;
def Time @inline = distinct long;
def TimeDuration @inline = distinct long;
def Clock @inline = distinct ulong;
def NanoDuration @inline = distinct long;
const TimeDuration MICROSECONDS_PER_SECOND = 1_000_000;
const TimeDuration MICROSECONDS_PER_MINUTE = MICROSECONDS_PER_SECOND * 60;

View File

@@ -95,9 +95,9 @@ int comment_level = 0;
"char" { count(); return(CHAR); }
"const" { count(); return(CONST); }
"continue" { count(); return(CONTINUE); }
"def" { count(); return(DEF); }
"default" { count(); return(DEFAULT); }
"defer" { count(); return(DEFER); }
"define" { count(); return(DEFINE); }
"distinct" { count(); return(DISTINCT); }
"do" { count(); return(DO); }
"double" { count(); return(DOUBLE); }
@@ -137,7 +137,6 @@ int comment_level = 0;
"tlocal" { count(); return(TLOCAL); }
"true" { count(); return(TRUE); }
"try" { count(); return(TRY); }
"typedef" { count(); return(TYPEDEF); }
"typeid" { count(); return(TYPEID); }
"uint" { count(); return(UINT); }
"uint128" { count(); return(UINT128); }

View File

@@ -17,7 +17,7 @@ void yyerror(char *s);
%token AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
%token SUB_ASSIGN SHL_ASSIGN SHR_ASSIGN AND_ASSIGN
%token XOR_ASSIGN OR_ASSIGN VAR NUL ELVIS NEXTCASE ANYFAULT
%token TYPEDEF MODULE IMPORT DEFINE EXTERN
%token MODULE IMPORT DEF EXTERN
%token CHAR SHORT INT LONG FLOAT DOUBLE CONST VOID USZ ISZ UPTR IPTR ANY
%token ICHAR USHORT UINT ULONG BOOL INT128 UINT128 FLOAT16 FLOAT128 BFLOAT16
%token TYPEID BITSTRUCT STATIC BANGBANG AT_CONST_IDENT HASH_TYPE_IDENT
@@ -1110,9 +1110,6 @@ typedef_type
| type opt_generic_parameters
;
typedef_declaration
: TYPEDEF TYPE_IDENT opt_attributes '=' opt_distinct_inline typedef_type ';'
;
multi_declaration
@@ -1166,8 +1163,9 @@ define_ident
;
define_declaration
: DEFINE define_ident ';'
| DEFINE define_attribute ';'
: DEF define_ident ';'
| DEF define_attribute ';'
| DEF TYPE_IDENT opt_attributes '=' opt_distinct_inline typedef_type ';'
;
tl_ct_if
@@ -1233,7 +1231,6 @@ top_level
| fault_declaration
| enum_declaration
| macro_declaration
| typedef_declaration
| define_declaration
| static_declaration
| bitstruct_declaration

View File

@@ -231,8 +231,8 @@ fn void hello() throws Errors
return;
}
typedef Foo* as Bar;
typedef fn void(int, Foo*) as Zoo;
def Foo* as Bar;
def fn void(int, Foo*) as Zoo;

View File

@@ -103,7 +103,7 @@ const uint SDL_WINDOWPOS_UNDEFINED = UndefinedDisplay(x);
#define SDL_WINDOWPOS_ISCENTERED(X) \
(((X)&0xFFFF0000) == SDL_WINDOWPOS_CENTERED_MASK)
typedef enum
def enum
{
SDL_ORIENTATION_UNKNOWN, /**< The display orientation can't be determined */
SDL_ORIENTATION_LANDSCAPE, /**< The display is in landscape mode, with the right side up, relative to portrait mode */
@@ -115,7 +115,7 @@ typedef enum
/**
* \brief An opaque handle to an OpenGL context.
*/
typedef void *SDL_GLContext;
def void *SDL_GLContext;
enum GLAttr
@@ -149,14 +149,14 @@ enum GLAttr
GL_CONTEXT_NO_ERROR
}
typedef enum
def enum
{
SDL_GL_CONTEXT_PROFILE_CORE = 0x0001,
SDL_GL_CONTEXT_PROFILE_COMPATIBILITY = 0x0002,
SDL_GL_CONTEXT_PROFILE_ES = 0x0004 /**< GLX_CONTEXT_ES2_PROFILE_BIT_EXT */
} SDL_GLprofile;
typedef enum
def enum
{
SDL_GL_CONTEXT_DEBUG_FLAG = 0x0001,
SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG = 0x0002,
@@ -164,13 +164,13 @@ typedef enum
SDL_GL_CONTEXT_RESET_ISOLATION_FLAG = 0x0008
} SDL_GLcontextFlag;
typedef enum
def enum
{
SDL_GL_CONTEXT_RELEASE_BEHAVIOR_NONE = 0x0000,
SDL_GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH = 0x0001
} SDL_GLcontextReleaseFlag;
typedef enum
def enum
{
SDL_GL_CONTEXT_RESET_NO_NOTIFICATION = 0x0000,
SDL_GL_CONTEXT_RESET_LOSE_CONTEXT = 0x0001
@@ -810,7 +810,7 @@ extern DECLSPEC int SDLCALL SDL_GetWindowGammaRamp(SDL_Window * window,
*
* \sa SDL_HitTest
*/
typedef enum
def enum
{
SDL_HITTEST_NORMAL, /**< Region is normal. No special properties. */
SDL_HITTEST_DRAGGABLE, /**< Region can drag entire window. */
@@ -829,7 +829,7 @@ typedef enum
*
* \sa SDL_SetWindowHitTest
*/
typedef SDL_HitTestResult (SDLCALL *SDL_HitTest)(SDL_Window *win,
def SDL_HitTestResult (SDLCALL *SDL_HitTest)(SDL_Window *win,
const SDL_Point *area,
void *data);

View File

@@ -114,6 +114,10 @@ static void usage(void)
OUTPUT(" --emit-llvm - Emit LLVM IR as a .ll file per module.");
OUTPUT(" --asm-out <dir> - Override asm output directory for '--emit-asm'.");
OUTPUT(" --emit-asm - Emit asm as a .s file per module.");
OUTPUT(" --obj - Emit object files. (Enabled by default)");
OUTPUT(" --no-obj - Do not output object files, this is only valid for `compile-only`.");
OUTPUT(" --emit-stdlib - Output files for the standard library. (Enabled by default)");
OUTPUT(" --no-emit-stdlib - Do not output object files (nor asm or ir) for the standard library.");
OUTPUT(" --target <target> - Compile for a particular architecture + OS target.");
OUTPUT(" --threads <number> - Set the number of threads to use for compilation.");
OUTPUT(" --safe - Set mode to 'safe', generating runtime traps on overflows and contract violations.");
@@ -134,7 +138,8 @@ static void usage(void)
OUTPUT(" --x86vec=<option> - Set max type of vector use: none, mmx, sse, avx, avx512, native.");
OUTPUT(" --riscvfloat=<option> - Set type of RISC-V float support: none, float, double");
OUTPUT(" --memory-env=<option> - Set the memory environment: normal, small, tiny, none.");
OUTPUT(" --strip-unused - Strip unused code and globals from the output (experimental)");
OUTPUT(" --strip-unused - Strip unused code and globals from the output. (Enabled by default)");
OUTPUT(" --no-strip-unused - Do not strip unused code and globals from the output.");
OUTPUT("");
OUTPUT(" --debug-stats - Print debug statistics.");
#ifndef NDEBUG
@@ -159,7 +164,11 @@ static void usage(void)
OUTPUT(" --wincrt=<option> - Windows CRT linking: none, static, dynamic (default).");
OUTPUT("");
OUTPUT(" --macossdk <dir> - Set the directory for the MacOS SDK for cross compilation.");
OUTPUT(" --macos-min-version <ver> - Set the minimum MacOS version to compile for.");
OUTPUT(" --macos-sdk-version <ver> - Set the MacOS SDK compiled for.");
OUTPUT("");
OUTPUT(" --linux-crt <dir> - Set the directory to use for finding crt1.o and related files.");
OUTPUT(" --linux-crtbegin <dir> - Set the directory to use for finding crtbegin.o and related files.");
}
@@ -545,9 +554,14 @@ static void parse_option(BuildOptions *options)
print_version();
exit_compiler(COMPILER_SUCCESS_EXIT);
}
if (match_longopt("no-strip-unused"))
{
options->no_strip_unused = true;
return;
}
if (match_longopt("strip-unused"))
{
options->strip_unused = true;
options->no_strip_unused = false;
return;
}
if ((argopt = match_argopt("x86vec")))
@@ -581,6 +595,26 @@ static void parse_option(BuildOptions *options)
OUTPUT("C3 is low level programming language based on C.");
exit_compiler(COMPILER_SUCCESS_EXIT);
}
if (match_longopt("no-obj"))
{
options->no_obj = true;
return;
}
if (match_longopt("obj"))
{
options->no_obj = false;
return;
}
if (match_longopt("no-emit-stdlib"))
{
options->no_emit_stdlib = true;
return;
}
if (match_longopt("emit-stdlib"))
{
options->no_emit_stdlib = false;
return;
}
if (match_longopt("debug-log"))
{
debug_log = true;
@@ -807,6 +841,18 @@ static void parse_option(BuildOptions *options)
options->path = check_dir(next_arg());
return;
}
if (match_longopt("linux-crt"))
{
if (at_end() || next_is_opt()) error_exit("error: --linux-crt needs a directory.");
options->linuxpaths.crt = check_dir(next_arg());
return;
}
if (match_longopt("linux-crtbegin"))
{
if (at_end() || next_is_opt()) error_exit("error: --linux-crtbegin needs a directory.");
options->linuxpaths.crtbegin = check_dir(next_arg());
return;
}
if (match_longopt("safe"))
{
options->safe_mode = 1;
@@ -855,7 +901,6 @@ BuildOptions parse_arguments(int argc, const char *argv[])
BuildOptions build_options = {
.path = ".",
.emit_llvm = false,
.emit_bitcode = true,
.optimization_setting_override = OPT_SETTING_NOT_SET,
.debug_info_override = DEBUG_INFO_NOT_SET,
.safe_mode = -1,

View File

@@ -297,6 +297,10 @@ typedef struct BuildOptions_
const char *min_version;
const char *sdk_version;
} macos;
struct {
const char *crt;
const char *crtbegin;
} linuxpaths;
int build_threads;
const char** libraries_to_fetch;
const char** files;
@@ -317,11 +321,12 @@ typedef struct BuildOptions_
int safe_mode;
bool emit_llvm;
bool emit_asm;
bool emit_bitcode;
bool test_mode;
bool no_stdlib;
bool no_entry;
bool no_libc;
bool no_obj;
bool no_emit_stdlib;
bool force_linker;
bool read_stdin;
bool print_output;
@@ -336,7 +341,7 @@ typedef struct BuildOptions_
X86CpuSet x86_cpu_set;
RiscvFloatCapability riscv_float_capability;
MemoryEnvironment memory_environment;
bool strip_unused;
bool no_strip_unused;
bool print_keywords;
bool print_attributes;
bool print_builtins;
@@ -410,7 +415,7 @@ typedef struct
bool emit_asm;
bool no_stdlib;
bool no_libc;
bool strip_unused;
bool no_strip_unused;
bool emit_object_files;
bool force_linker;
bool benchmarking;
@@ -418,6 +423,7 @@ typedef struct
bool read_stdin;
bool print_output;
bool no_entry;
bool no_emit_stdlib;
int build_threads;
OptimizationLevel optimization_level;
MemoryEnvironment memory_environment;
@@ -456,6 +462,11 @@ typedef struct
WinCrtLinking crt_linking;
bool use_win_subsystem;
} win;
struct
{
const char *crt;
const char *crtbegin;
} linuxpaths;
} BuildTarget;

View File

@@ -199,7 +199,7 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
{
target->feature.safe_mode = options->safe_mode == 1;
}
if (options->strip_unused) target->strip_unused = true;
if (options->no_strip_unused || options->test_mode) target->no_strip_unused = true;
if (options->memory_environment != MEMORY_ENV_NOT_SET)
{
@@ -243,6 +243,8 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
if (options->macos.min_version) target->macos.min_version = options->macos.min_version;
if (options->macos.sdk_version) target->macos.sdk_version = options->macos.sdk_version;
if (options->win.crt_linking != WIN_CRT_DEFAULT) target->win.crt_linking = options->win.crt_linking;
if (options->linuxpaths.crt) target->linuxpaths.crt = options->linuxpaths.crt;
if (options->linuxpaths.crtbegin) target->linuxpaths.crtbegin = options->linuxpaths.crtbegin;
if (options->x86_vector_capability != X86VECTOR_DEFAULT)
{
target->feature.x86_vector_capability = options->x86_vector_capability;
@@ -300,6 +302,11 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
target->emit_asm = false;
target->emit_object_files = false;
}
if (options->no_obj)
{
target->emit_object_files = false;
}
target->no_emit_stdlib = options->no_emit_stdlib;
for (int i = 0; i < options->lib_dir_count; i++)
{
vec_add(target->libdirs, options->lib_dir[i]);

View File

@@ -374,6 +374,12 @@ static void load_into_build_target(JSONObject *json, const char *type, BuildTarg
// macos-sdk-version
target->macos.sdk_version = get_valid_string(json, "macos-sdk-version", type, false);
// Linux crt
target->linuxpaths.crt = get_valid_string(json, "linux-crt", type, false);
// Linux crtbegin
target->linuxpaths.crtbegin = get_valid_string(json, "linux-crtbegin", type, false);
// version
const char *version = get_valid_string(json, "version", type, false);
if (version) target->version = version;

View File

@@ -432,8 +432,7 @@ void compiler_compile(void)
}
else if (task_count > 1)
{
TaskQueueRef queue = taskqueue_create(active_target.build_threads > task_count ? task_count : active_target.build_threads, tasks);
taskqueue_wait_for_completion(queue);
taskqueue_run(active_target.build_threads > task_count ? task_count : active_target.build_threads, tasks);
}
if (active_target.print_output)
@@ -485,21 +484,29 @@ void compiler_compile(void)
printf("Program finished with exit code %d.\n", ret);
}
}
if (output_static)
else if (output_static)
{
if (!static_lib_linker(output_static, obj_files, output_file_count))
{
error_exit("Failed to produce static library '%s'.", output_static);
}
compiler_link_time = bench_mark();
compiler_print_bench();
printf("Static library '%s' created.", output_static);
}
if (output_dynamic)
else if (output_dynamic)
{
if (!dynamic_lib_linker(output_dynamic, obj_files, output_file_count))
{
error_exit("Failed to produce static library '%s'.", output_dynamic);
}
printf("Dynamic library '%s' created.", output_dynamic);
compiler_link_time = bench_mark();
compiler_print_bench();
}
else
{
compiler_print_bench();
}
free(obj_files);
}

View File

@@ -286,7 +286,7 @@ static void linker_setup_macos(const char ***args_ref, LinkerType linker_type)
}
add_arg("-arch");
add_arg(arch_to_linker_arch(platform_target.arch));
if (active_target.strip_unused && active_target.type == TARGET_TYPE_EXECUTABLE)
if (!active_target.no_strip_unused && active_target.type == TARGET_TYPE_EXECUTABLE)
{
add_arg("-no_exported_symbols");
add_arg("-dead_strip");
@@ -340,6 +340,7 @@ static const char *find_freebsd_crt(void)
static const char *find_linux_crt(void)
{
if (active_target.linuxpaths.crt) return active_target.linuxpaths.crt;
#if PLATFORM_POSIX
glob_t globbuf;
if (!glob("/usr/lib/*/crt1.o", 0, NULL, &globbuf) && globbuf.gl_pathc)
@@ -362,6 +363,7 @@ static const char *find_linux_crt(void)
static const char *find_linux_crt_begin(void)
{
if (active_target.linuxpaths.crtbegin) return active_target.linuxpaths.crtbegin;
#if PLATFORM_POSIX
glob_t globbuf;
if (!glob("/usr/lib/gcc/*/*/crtbegin.o", 0, NULL, &globbuf) && globbuf.gl_pathc)
@@ -396,9 +398,9 @@ static void linker_setup_linux(const char ***args_ref, LinkerType linker_type)
const char *crt_begin_dir = find_linux_crt_begin();
const char *crt_dir = find_linux_crt();
if (active_target.strip_unused && active_target.type == TARGET_TYPE_EXECUTABLE)
if (!active_target.no_strip_unused && active_target.type == TARGET_TYPE_EXECUTABLE)
{
add_arg("-dead_strip");
add_arg("--gc-sections");
}
if (!crt_begin_dir || !crt_dir)
@@ -446,9 +448,9 @@ static void linker_setup_freebsd(const char ***args_ref, LinkerType linker_type)
{
error_exit("Failed to find the C runtime at link time.");
}
if (active_target.strip_unused && active_target.type == TARGET_TYPE_EXECUTABLE)
if (!active_target.no_strip_unused && active_target.type == TARGET_TYPE_EXECUTABLE)
{
add_arg("-dead_strip");
add_arg("--gc-sections");
}
if (is_pie_pic(platform_target.reloc_model))

View File

@@ -1265,9 +1265,21 @@ LLVMMetadataRef llvm_get_debug_file(GenContext *c, FileId file_id)
return file;
}
static bool module_is_stdlib(Module *module)
{
if (module->name->len < 3) return false;
if (module->name->len == 3 && strcmp(module->name->module, "std") == 0) return true;
if (module->name->len > 5 && memcmp(module->name->module, "std::", 5) == 0) return true;
if (module->name->len == 4 && strcmp(module->name->module, "libc") == 0) return true;
if (module->name->len > 6 && memcmp(module->name->module, "libc::", 6) == 0) return true;
return false;
}
static GenContext *llvm_gen_module(Module *module, LLVMContextRef shared_context)
{
if (!vec_size(module->units)) return NULL;
if (active_target.no_emit_stdlib && module_is_stdlib(module)) return NULL;
assert(intrinsics_setup);
bool has_elements = false;
@@ -1275,7 +1287,7 @@ static GenContext *llvm_gen_module(Module *module, LLVMContextRef shared_context
gencontext_init(gen_context, module, shared_context);
gencontext_begin_module(gen_context);
bool only_used = active_target.strip_unused && !active_target.testing;
bool only_used = !active_target.no_strip_unused;
FOREACH_BEGIN(CompilationUnit *unit, module->units)
@@ -1296,10 +1308,12 @@ static GenContext *llvm_gen_module(Module *module, LLVMContextRef shared_context
FOREACH_END();
FOREACH_BEGIN(Decl *type_decl, unit->types)
if (only_used && !type_decl->is_live) continue;
llvm_emit_type_decls(gen_context, type_decl);
FOREACH_END();
FOREACH_BEGIN(Decl *enum_decl, unit->enums)
if (only_used && !enum_decl->is_live) continue;
llvm_emit_type_decls(gen_context, enum_decl);
FOREACH_END();
@@ -1384,8 +1398,6 @@ static GenContext *llvm_gen_module(Module *module, LLVMContextRef shared_context
llvm_emit_constructors_and_destructors(gen_context);
// EmitDeferred()
if (llvm_use_debug(gen_context))
{
LLVMDIBuilderFinalize(gen_context->debug.builder);

View File

@@ -1745,7 +1745,11 @@ static inline void decl_add_type(Decl *decl, TypeKind kind)
*/
static inline Decl *parse_typedef_declaration(ParseContext *c)
{
if (!try_consume(c, TOKEN_DEF)) advance_and_verify(c, TOKEN_TYPEDEF);
if (!try_consume(c, TOKEN_DEF))
{
sema_warning_at(c->span, "The use of 'typedef' is deprecated, please use 'def'.");
advance_and_verify(c, TOKEN_TYPEDEF);
}
Decl *decl = decl_new(DECL_POISONED, symstr(c), c->span);
DEBUG_LOG("Parse typedef %s", decl->name);
@@ -1849,20 +1853,28 @@ static inline Decl *parse_typedef_declaration(ParseContext *c)
static inline Decl *parse_define_ident(ParseContext *c)
{
// 1. Store the beginning of the "define".
if (!try_consume(c, TOKEN_DEF)) advance_and_verify(c, TOKEN_DEFINE);
if (!try_consume(c, TOKEN_DEF))
{
sema_warning_at(c->span, "The use of 'define' is deprecated, please use 'def'.");
advance_and_verify(c, TOKEN_DEFINE);
}
// 2. At this point we expect an ident or a const token.
// since the Type is handled.
TokenType alias_type = c->tok;
if (alias_type != TOKEN_IDENT && alias_type != TOKEN_CONST_IDENT && alias_type != TOKEN_AT_IDENT)
{
if (alias_type == TOKEN_TYPE_IDENT)
if (token_is_keyword_ident(alias_type) && alias_type != TOKEN_FN)
{
SEMA_ERROR_HERE("'%s' is a reserved keyword, try another name.", token_type_to_string(alias_type));
}
else if (alias_type == TOKEN_TYPE_IDENT)
{
SEMA_ERROR_HERE("A variable, constant or attribute name was expected here. If you want to define a new type, use 'typedef' instead.");
}
else
{
SEMA_ERROR_HERE("A variable, constant or attribute name was expected here.");
SEMA_ERROR_HERE("A type, variable, constant or attribute name was expected here.");
}
return poisoned_decl;
}

View File

@@ -2332,6 +2332,7 @@ static inline bool sema_analyse_func(SemaContext *context, Decl *decl)
return false;
}
global_context.test_func = decl;
if (active_target.testing) decl->no_strip = true;
}
bool is_test = decl->func_decl.attr_test;
Signature *sig = &decl->func_decl.signature;

View File

@@ -178,12 +178,14 @@ static void sema_trace_stmt_liveness(Ast *ast)
static void sema_trace_const_initializer_liveness(ConstInitializer *const_init)
{
RETRY:
switch (const_init->kind)
{
case CONST_INIT_ZERO:
return;
case CONST_INIT_ARRAY_VALUE:
UNREACHABLE
const_init = const_init->init_array_value.element;
goto RETRY;
case CONST_INIT_ARRAY_FULL:
{
bool was_modified = false;
@@ -204,8 +206,8 @@ static void sema_trace_const_initializer_liveness(ConstInitializer *const_init)
return;
}
case CONST_INIT_UNION:
sema_trace_const_initializer_liveness(const_init->init_union.element);
return;
const_init = const_init->init_union.element;
goto RETRY;
case CONST_INIT_STRUCT:
{
Decl *decl = const_init->type->decl;
@@ -353,8 +355,16 @@ RETRY:
sema_trace_expr_list_liveness(expr->designated_init_list);
return;
case EXPR_EXPR_BLOCK:
sema_trace_stmt_liveness(astptr(expr->expr_block.first_stmt));
{
AstId current = expr->expr_block.first_stmt;
if (!current) return;
do
{
Ast *value = ast_next(&current);
sema_trace_stmt_liveness(value);
} while (current);
return;
}
case EXPR_IDENTIFIER:
sema_trace_decl_liveness(expr->identifier_expr.decl);
return;
@@ -452,10 +462,15 @@ void sema_trace_liveness(void)
{
sema_trace_decl_liveness(global_context.main);
}
bool keep_tests = active_target.testing;
FOREACH_BEGIN(Decl *function, global_context.method_extensions)
if (function->func_decl.attr_dynamic) function->no_strip = true;
if (function->is_export || function->no_strip) sema_trace_decl_liveness(function);
FOREACH_END();
FOREACH_BEGIN(Module *module, global_context.module_list)
FOREACH_BEGIN(CompilationUnit *unit, module->units)
FOREACH_BEGIN(Decl *function, unit->functions)
if (function->is_export || function->no_strip) sema_trace_decl_liveness(function);
if (function->is_export || function->no_strip || (function->func_decl.attr_test && keep_tests)) sema_trace_decl_liveness(function);
FOREACH_END();
FOREACH_BEGIN(Decl *method, unit->methods)
if (method->is_export || method->no_strip) sema_trace_decl_liveness(method);
@@ -463,26 +478,67 @@ void sema_trace_liveness(void)
FOREACH_BEGIN(Decl *var, unit->vars)
if (var->is_export || var->no_strip) sema_trace_decl_liveness(var);
FOREACH_END();
FOREACH_BEGIN(Decl *method, unit->local_method_extensions)
if (method->is_export || method->no_strip) sema_trace_decl_liveness(method);
FOREACH_END();
FOREACH_BEGIN(Decl *xxlizer, unit->xxlizers)
sema_trace_decl_liveness(xxlizer);
FOREACH_END();
FOREACH_END();
FOREACH_END();
}
INLINE void sema_trace_type_liveness(Type *type)
{
if (!type || !type_is_user_defined(type)) return;
sema_trace_decl_liveness(type->decl);
}
INLINE void sema_trace_decl_dynamic_methods(Decl *decl)
{
Decl **methods = decl->methods;
unsigned method_count = vec_size(methods);
if (!method_count) return;
for (unsigned i = 0; i < method_count; i++)
{
Decl *method = methods[i];
if (!method->func_decl.attr_dynamic) continue;
sema_trace_decl_liveness(method);
}
}
static void sema_trace_decl_liveness(Decl *decl)
{
RETRY:
if (!decl || decl->is_live) return;
decl->is_live = true;
switch (decl->decl_kind)
{
case DECL_POISONED:
case DECL_ATTRIBUTE:
case DECL_BITSTRUCT:
case DECL_TYPEDEF:
if (!decl->typedef_decl.is_func)
{
sema_trace_type_liveness(decl->typedef_decl.type_info->type);
return;
}
FOREACH_BEGIN(Decl *param, decl->typedef_decl.function_signature.params)
sema_trace_decl_liveness(param);
FOREACH_END();
sema_trace_type_liveness(typeinfotype(decl->typedef_decl.function_signature.rtype));
return;
case DECL_DEFINE:
decl = decl->define_decl.alias;
goto RETRY;
case DECL_DISTINCT:
case DECL_ENUM:
case DECL_ENUM_CONSTANT:
case DECL_BITSTRUCT:
case DECL_FAULT:
case DECL_STRUCT:
case DECL_UNION:
sema_trace_decl_dynamic_methods(decl);
return;
case DECL_POISONED:
case DECL_ATTRIBUTE:
case DECL_ENUM_CONSTANT:
case DECL_FAULTVALUE:
return;
case DECL_CT_CASE:
@@ -508,20 +564,27 @@ static void sema_trace_decl_liveness(Decl *decl)
{
case VARDECL_REWRAPPED:
case VARDECL_UNWRAPPED:
return;
break;
case VARDECL_PARAM_EXPR:
case VARDECL_PARAM_CT:
case VARDECL_PARAM_REF:
case VARDECL_PARAM:
sema_trace_type_liveness(decl->type);
if (decl->var.init_expr && decl->var.init_expr->resolve_status == RESOLVE_DONE)
{
sema_trace_expr_liveness(decl->var.init_expr);
}
break;
default:
sema_trace_type_liveness(decl->type);
sema_trace_expr_liveness(decl->var.init_expr);
break;
}
sema_trace_expr_liveness(decl->var.init_expr);
return;
case DECL_INITIALIZE:
case DECL_FINALIZE:
sema_trace_stmt_liveness(astptrzero(decl->xxlizer.init));
return;
case DECL_STRUCT:
case DECL_TYPEDEF:
case DECL_UNION:
return;
case DECL_DECLARRAY:
UNREACHABLE
}

View File

@@ -2927,6 +2927,49 @@ bool sema_analyse_function_body(SemaContext *context, Decl *func)
func->name);
return false;
}
Signature any_sig = any->func_decl.signature;
Signature this_sig = func->func_decl.signature;
Type *any_rtype = typeinfotype(any_sig.rtype);
Type *this_rtype = typeinfotype(this_sig.rtype);
if (any_rtype->canonical != this_rtype->canonical)
{
SEMA_ERROR(type_infoptr(this_sig.rtype), "The prototype method has a return type %s, but this function returns %s, they need to match.",
type_quoted_error_string(any_rtype), type_quoted_error_string(this_rtype));
SEMA_NOTE(type_infoptr(any_sig.rtype), "The interface definition is here.");
return false;
}
Decl **any_params = any_sig.params;
Decl **this_params = this_sig.params;
unsigned any_param_count = vec_size(any_params);
unsigned this_param_count = vec_size(this_params);
if (any_param_count != this_param_count)
{
if (any_param_count > this_param_count)
{
SEMA_ERROR(func, "This function is missing parameters, %d parameters were expected.", any_param_count);
SEMA_NOTE(any_params[this_param_count], "Compare with the interface definition.");
return false;
}
else
{
SEMA_ERROR(this_params[any_param_count], "This function has too many parameters (%d).", this_param_count);
SEMA_NOTE(any, "Compare with the interface, which has only %d parameter%s.",
any_param_count, any_param_count == 1 ? "" : "s");
}
return false;
}
FOREACH_BEGIN_IDX(i, Decl *param, this_params)
if (i == 0) continue;
if (param->type->canonical != any_params[i]->type->canonical)
{
SEMA_ERROR(param->var.type_info, "The prototype argument has type %s, but in this function it has type %s. Please make them match.",
type_quoted_error_string(any_params[i]->type), type_quoted_error_string(param->type));
SEMA_NOTE(any_params[i]->var.type_info, "The interface definition is here.");
return false;
}
FOREACH_END();
func->func_decl.any_prototype = declid(any);
}
Signature *signature = &func->func_decl.signature;

View File

@@ -261,6 +261,8 @@ static void assign_panicfn(void)
error_exit("Expected panic function to have the signature fn void(String, String, String, uint).");
}
global_context.panic_var = decl;
decl->no_strip = true;
if (active_target.no_stdlib) return;
const char *panicf = "std::core::builtin::panicf";
@@ -275,6 +277,8 @@ static void assign_panicfn(void)
return;
}
panicf_decl->no_strip = true;
Type *panicf_fn_type = panicf_decl->type->canonical;
if (panicf_decl->decl_kind != DECL_FUNC)
{
@@ -369,12 +373,13 @@ RESOLVE_LAMBDA:;
if (found_lambda) goto RESOLVE_LAMBDA;
halt_on_error();
if (active_target.strip_unused && !active_target.testing)
assign_panicfn();
if (!active_target.no_strip_unused)
{
sema_trace_liveness();
}
assign_panicfn();
compiler_sema_time = bench_mark();

View File

@@ -25,6 +25,15 @@ static void cleanup()
int main_real(int argc, const char *argv[])
{
printf("------------------------------------------------------------\n"
" PLEASE NOTE, this version of the compiler has enabled dead\n"
" code stripping by default. This functionality has not been\n"
" completely audited, so if you run into any linking error, \n"
" please use --no-strip-unused to disable the feature. \n"
" If possible, file an error here: \n"
" https://github.com/c3lang/c3c/issues\n"
" Thank you!\n"
"------------------------------------------------------------\n");
bench_begin();
// Setjmp will allow us to add things like fuzzing with

View File

@@ -57,8 +57,6 @@ typedef struct Task_
void *arg;
} Task;
typedef void *TaskQueueRef;
uint16_t *win_utf8to16(const char *name);
char *win_utf16to8(const uint16_t *name);
// Use as if it was mkdir(..., 0755) == 0
@@ -98,8 +96,7 @@ char *calloc_string(size_t len);
void free_arena(void);
void print_arena_status(void);
void run_arena_allocator_tests(void);
TaskQueueRef taskqueue_create(int threads, Task **task_list);
void taskqueue_wait_for_completion(TaskQueueRef queue);
void taskqueue_run(int threads, Task **task_list);
int cpus(void);
const char *date_get(void);
const char *time_get(void);

View File

@@ -9,8 +9,6 @@
typedef struct TaskQueue_
{
pthread_t *threads;
int thread_count;
pthread_mutex_t lock;
Task **queue;
} TaskQueue;
@@ -35,48 +33,80 @@ SHUTDOWN:
return NULL;
}
TaskQueueRef taskqueue_create(int threads, Task **task_list)
void taskqueue_run(int threads, Task **task_list)
{
assert(threads > 0);
TaskQueue *queue = CALLOCS(TaskQueue);
queue->threads = MALLOC(sizeof(pthread_t) * (unsigned)threads);
queue->thread_count = threads;
queue->queue = task_list;
if (pthread_mutex_init(&queue->lock, NULL)) error_exit("Failed to set up mutex");
pthread_t *pthreads = malloc(sizeof(pthread_t) * (unsigned)threads);
TaskQueue queue = { .queue = task_list };
if (pthread_mutex_init(&queue.lock, NULL)) error_exit("Failed to set up mutex");
for (int i = 0; i < threads; i++)
{
if (pthread_create(queue->threads + i, NULL, taskqueue_thread, queue)) error_exit("Fail to set up thread pool");
if (pthread_create(&pthreads[i], NULL, taskqueue_thread, &queue)) error_exit("Fail to set up thread pool");
}
return queue;
}
void taskqueue_wait_for_completion(TaskQueueRef queue_ref)
{
assert(queue_ref);
TaskQueue *queue = queue_ref;
for (int i = 0; i < queue->thread_count; i++)
for (int i = 0; i < threads; i++)
{
if (pthread_join(queue->threads[i], NULL) != 0) error_exit("Failed to join thread.");
if (pthread_join(pthreads[i], NULL) != 0) error_exit("Failed to join thread.");
}
pthread_mutex_destroy(&queue->lock);
free(pthreads);
pthread_mutex_destroy(&queue.lock);
}
#elif PLATFORM_WINDOWS
#include <Windows.h>
#include <process.h>
typedef struct TaskQueue_
{
CRITICAL_SECTION lock;
Task **queue;
} TaskQueue;
static DWORD WINAPI taskqueue_thread(LPVOID lpParam)
{
TaskQueue *task_queue = (TaskQueue *)lpParam;
bool is_active = false;
while (1)
{
EnterCriticalSection(&task_queue->lock);
unsigned task_count = vec_size(task_queue->queue);
if (!task_count) goto SHUTDOWN;
Task *task = (Task*)task_queue->queue[task_count - 1];
vec_pop(task_queue->queue);
LeaveCriticalSection(&task_queue->lock);
task->task(task->arg);
}
SHUTDOWN:
LeaveCriticalSection(&task_queue->lock);
return 0;
}
void taskqueue_run(int threads, Task **task_list)
{
assert(threads > 0);
HANDLE *handles = malloc(sizeof(HANDLE) * (unsigned)threads);
TaskQueue queue = { .queue = task_list };
InitializeCriticalSection(&queue.lock);
for (int i = 0; i < threads; i++)
{
handles[i] = (HANDLE)_beginthreadex(NULL, 0, taskqueue_thread, &queue, 0, NULL);
if (handles[i] == NULL) error_exit("Fail to set up thread pool");
}
WaitForMultipleObjects(threads, handles, TRUE, INFINITE);
for (int i = 0; i < threads; i++)
{
CloseHandle(handles[i]);
}
free((void*)handles);
DeleteCriticalSection(&queue.lock);
}
#else
void taskqueue_add(TaskQueueRef queue_ref, Task *task)
void taskqueue_run(int threads, Task **task_list)
{
}
TaskQueueRef taskqueue_create(int threads, Task **tasks)
{
return tasks;
}
void taskqueue_wait_for_completion(TaskQueueRef queue)
{
Task **tasks = queue;
FOREACH_BEGIN(Task *task, tasks)
FOREACH_BEGIN(Task *task, task_list)
task->task(task->arg);
FOREACH_END();
}

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.4.518"
#define COMPILER_VERSION "0.4.525"

View File

@@ -1,7 +1,7 @@
// #target: macos-aarch64
module test;
typedef Int8x16 = ichar[<16>];
typedef Float32x3 = float[<3>];
def Int8x16 = ichar[<16>];
def Float32x3 = float[<3>];
struct HFAv3
{

View File

@@ -2,7 +2,7 @@
// #opt: --x86cpu=avx1
module test;
typedef Mm256 = float[<8>];
def Mm256 = float[<8>];
struct St256 {
Mm256 m;
}
@@ -19,7 +19,7 @@ fn void f39() { f38(x38); f37(x37); }
// CHECK: declare void @func40(%struct.t128* byval(%struct.t128) align 16)
typedef Mm128 = float[<4>];
def Mm128 = float[<4>];
struct Two128 {
Mm128 m;
Mm128 n;
@@ -44,7 +44,7 @@ fn void func43(Sa s) {
}
typedef Vec46 = float[<2>];
def Vec46 = float[<2>];
extern fn void f46(Vec46,Vec46,Vec46,Vec46,Vec46,Vec46,Vec46,Vec46,Vec46,Vec46);
fn void test46() { Vec46 x = {1,2}; f46(x,x,x,x,x,x,x,x,x,x); }
@@ -69,7 +69,7 @@ fn void test54() {
test54_helper(x54, x54, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, Complex { 0, 1.0 });
}
typedef Mm512 = float[<16>];
def Mm512 = float[<16>];
struct St512 {
Mm512 m;
}

View File

@@ -2,8 +2,8 @@
// #opt: --x86cpu=avx512
module test;
typedef Mm256 = float[<8>];
typedef Mm512 = float[<16>];
def Mm256 = float[<8>];
def Mm512 = float[<16>];
struct St512 {
Mm512 m;
}

View File

@@ -2,7 +2,7 @@
// #opt: --x86cpu=sse4
module test;
typedef Mm256 = float[<8>];
def Mm256 = float[<8>];
struct St256 {
Mm256 m;
}
@@ -19,7 +19,7 @@ fn void f39() { f38(x38); f37(x37); }
// CHECK: declare void @func40(%struct.t128* byval(%struct.t128) align 16)
typedef Mm128 = float[<4>];
def Mm128 = float[<4>];
struct Two128 {
Mm128 m;
Mm128 n;

View File

@@ -86,7 +86,7 @@ fn V4f32wrapper f27(V4f32wrapper x) {
// PR22563 - We should unwrap simple structs and arrays to pass
// and return them in the appropriate vector registers if possible.
typedef V8f32 = float[<8>];
def V8f32 = float[<8>];
struct V8f32wrapper {
V8f32 v;
}
@@ -133,15 +133,15 @@ fn float f31(F31foo x) {
return x.c;
}
typedef V1i64 = ulong[<1>];
def V1i64 = ulong[<1>];
fn V1i64 f34(V1i64 arg) { return arg; }
typedef V1i64_2 = uint[<2>];
def V1i64_2 = uint[<2>];
fn V1i64_2 f35(V1i64_2 arg) { return arg+arg; }
typedef V2i32 = float[<2>];
def V2i32 = float[<2>];
fn V2i32 f36(V2i32 arg) { return arg; }

View File

@@ -5,7 +5,7 @@ struct Large {
long a, b, c, d;
}
typedef V32i8 = char[<32>];
def V32i8 = char[<32>];
fn int f_scalar_stack_1(int a, int128 b, float c, float128 d, V32i8 e,
char f, char g, char h) {

View File

@@ -1,6 +1,6 @@
module abc;
define @Foo = { @inline };
def @Foo = { @inline };
module bar;

View File

@@ -1,7 +1,7 @@
// #target: macos-x64
module test;
const int FOO @private = 4;
define @Align(x) = { @align(x * FOO) };
def @Align(x) = { @align(x * FOO) };
module test2;
import test;

View File

@@ -2,12 +2,12 @@
module test;
define @Foo = { @noreturn @weak };
def @Foo = { @noreturn @weak };
define @Align(y) = { @align(y) };
define @Align16(x) @private = { @Align(8 * x) @align(1024) };
define @Test = { @noinline };
define @TestZero = { };
def @Align(y) = { @align(y) };
def @Align16(x) @private = { @Align(8 * x) @align(1024) };
def @Test = { @noinline };
def @TestZero = { };
struct Foo
{
int z;

View File

@@ -5,8 +5,8 @@ bitstruct Test : int
float a : 1..3; // #error: 'float' is not supported in a bitstruct, only enums, integer and boolean values may be used.
}
typedef Baz = distinct float;
typedef Foo = distinct bool;
def Baz = distinct float;
def Foo = distinct bool;
enum Boo
{
BAR

View File

@@ -22,8 +22,8 @@ fn void test1()
$endswitch
}
typedef Foo = int;
typedef Bar = double;
def Foo = int;
def Bar = double;
fn void test2()
{
$switch (int.typeid)

View File

@@ -1,13 +1,13 @@
module foo;
// define <name> = <name>
// def <name> = <name>
def standard_foo = __stdin;
def someFunctionIntBool = someFunction<int, bool>;
def FooInt = Foo<int>;
def A_CONST_INT = A_CONST<int>;
def standard_foo<int> = ofke; // #error: Expected '='
def fn foo = fef; // #error: A variable, constant or attribute name was expected here.
def fn foo = fef; // #error: A type, variable, constant or attribute name was expected here
def feokfe = fn void(int); // #error: Expected a function or variable name here
def AOFKE = ofek; // #error: Expected a constant name here
def okfoe = OFKEOK; // #error: Expected a function or variable name here

View File

@@ -1,9 +1,9 @@
typedef int = int; // #error: 'int' is the name of a built-in type and can't be used as an alias.
def int = int; // #error: 'int' is a reserved keyword, try another name
def main = foo; // #error: 'main' is reserved and cannot be used as an alias.
typedef hello = int; // #error: uppercase letter
typedef hello = Foo; // #error: uppercase letter
def hello = int; // #error: uppercase letter
def hello = Foo; // #error: uppercase letter
typedef HELLO = int; // #error: uppercase letter
typedef HELLO = Foo; // #error: uppercase letter
def HELLO = int; // #error: uppercase letter
def HELLO = Foo; // #error: uppercase letter

View File

@@ -1,3 +1,3 @@
typedef Abc = int[*]; // #error: Inferred array types can only
typedef Bcd = anyfault; // #error: 'anyfault' may not be aliased.
typedef Efd = any; // #error: 'any' may not be aliased.
def Abc = int[*]; // #error: Inferred array types can only
def Bcd = anyfault; // #error: 'anyfault' may not be aliased.
def Efd = any; // #error: 'any' may not be aliased.

View File

@@ -3,8 +3,8 @@ fault Error
ABC
}
typedef Foo1 = distinct Error; // #error: You cannot create a distinct type
def Foo1 = distinct Error; // #error: You cannot create a distinct type
typedef Foo3 = distinct void; // #error: create a distinct type from 'void'
def Foo3 = distinct void; // #error: create a distinct type from 'void'
typedef Foo4 = distinct typeid; // #error: create a distinct type from 'typeid'
def Foo4 = distinct typeid; // #error: create a distinct type from 'typeid'

View File

@@ -1,4 +1,4 @@
typedef Foo = distinct double[];
def Foo = distinct double[];
fn void main()
{

View File

@@ -5,7 +5,7 @@ struct Struct
double y;
}
typedef Foo = distinct Struct;
def Foo = distinct Struct;
struct Struct2
{

View File

@@ -1,6 +1,6 @@
module test;
typedef Foo = distinct int;
def Foo = distinct int;
struct Struct
{
@@ -8,8 +8,8 @@ struct Struct
int y;
}
typedef Struct2 = distinct Struct;
typedef StructArr = distinct Struct2[3];
def Struct2 = distinct Struct;
def StructArr = distinct Struct2[3];
fn void test(int x)
{

View File

@@ -6,7 +6,7 @@ union Union
double y;
}
typedef Foo = distinct Union;
def Foo = distinct Union;
union Union2
{
@@ -19,9 +19,9 @@ union Union2
}
Foo f = { .x = 1 };
typedef Union3 = distinct Union2;
def Union3 = distinct Union2;
typedef UnionArr = distinct Union3[3];
def UnionArr = distinct Union3[3];
fn void test(int x)
{

View File

@@ -1,6 +1,6 @@
module test;
typedef Int2 = distinct int;
def Int2 = distinct int;
fn void test()
{

View File

@@ -1,6 +1,6 @@
module test;
typedef Foo = distinct int;
def Foo = distinct int;
fn int test1()
{

View File

@@ -6,7 +6,7 @@ struct Struct
double y;
}
typedef Foo = distinct Struct;
def Foo = distinct Struct;
struct Struct2
{

View File

@@ -0,0 +1,21 @@
fn int any.test(void* a, int ag) @interface;
struct Foo { int a; }
fn int! Foo.test(Foo* f) @dynamic { return 1; } // #error: The prototype method has a return type 'int'
struct Foo1 { int a; }
fn int Foo1.test(Foo1* f, int a) @dynamic { return 1; }
struct Foo2 { int a; }
fn int Foo2.test(Foo2* f) @dynamic { return 1; } // #error: This function is missing parameters, 2
struct Foo3 { int a; }
fn int Foo3.test(Foo3* f, double a) @dynamic { return 1; } // #error: The prototype argument has type 'int'
struct Foo4 { int a; }
fn int Foo4.test(Foo4* f, double a, int x) @dynamic { return 1; } // #error: This function has too many parameters

View File

@@ -60,8 +60,8 @@ fn void test6()
int[]* e = &arr[1..2]; // #error: To take the address of a temporary value, use '&&' instead of '&'
}
typedef Baz = Foo;
typedef Bar = distinct int;
def Baz = Foo;
def Bar = distinct int;
fault Err { FOO }
union Un { int x; }
enum MyEnum { BAR }

View File

@@ -1,4 +1,4 @@
typedef Number = int;
def Number = int;
fn void test1()
{

View File

@@ -2,7 +2,7 @@ enum Foo
{
ABC
}
typedef Abc = distinct int;
def Abc = distinct int;
fn void main()
{
Abc d = Foo.ABC; // #error: Implicitly casting

View File

@@ -13,7 +13,7 @@ enum EnumB : char
C, D
}
typedef Func = fn void(Enum);
def Func = fn void(Enum);
fn void test1(Enum e)
{

View File

@@ -8,9 +8,9 @@ enum Enum : uptr
A, B
}
typedef Func = fn void(int);
typedef FuncOther = fn bool(char*);
typedef FuncSame = fn void(int);
def Func = fn void(int);
def FuncOther = fn bool(char*);
def FuncSame = fn void(int);
fn void test1(Func arg)

View File

@@ -1,4 +1,4 @@
typedef Number = int;
def Number = int;
fn void test1()
{

View File

@@ -1,6 +1,6 @@
typedef Number8 = char;
typedef Number32 = int;
typedef DNumber32 = distinct int;
def Number8 = char;
def Number32 = int;
def DNumber32 = distinct int;
fn void test1()
{
int a = (ichar)(10);

View File

@@ -1,5 +1,5 @@
typedef Foo = distinct double;
typedef Bar = distinct void*;
def Foo = distinct double;
def Bar = distinct void*;
fn int main()
{
float f = 1;

View File

@@ -1,6 +1,6 @@
module test;
typedef Foo = distinct int;
def Foo = distinct int;
fn void test1()
{

View File

@@ -1,4 +1,4 @@
typedef Callback = fn int(char c);
def Callback = fn int(char c);
struct Person { int i; }
struct Company { int j; }
enum Status : int

View File

@@ -65,8 +65,8 @@ fn int Foo2.mutate(Foo2 *foo)
return ++foo.x;
}
define oopsInt = test2::argh<int>;
define oopsDouble = test2::argh<int>;
def oopsInt = test2::argh<int>;
def oopsDouble = test2::argh<int>;
typedef Argh = fn int(double, Bobo);
typedef Argh2 = fn int(double, Bobo);
@@ -95,12 +95,12 @@ struct Foo
int b;
}
define getValueInt = test2::getValue<int>;
define getValueDouble = test2::getValue<double>;
def getValueInt = test2::getValue<int>;
def getValueDouble = test2::getValue<double>;
typedef IntBlob = test2::Blob<int>;
typedef DoubleBlob = Blob<double>;
define getMultInt = test2::getMult<int>;
define getMultDouble = test2::getMult<double>;
def getMultInt = test2::getMult<int>;
def getMultDouble = test2::getMult<double>;
typedef IntArray = List<int>;
typedef IntList = LinkedList<int>;
@@ -173,7 +173,7 @@ module hello_world;
import foo;
extern fn int printf(char *, ...);
define doubleMult = foo::check<double>;
def doubleMult = foo::check<double>;
fn void hello()
{
@@ -219,8 +219,8 @@ macro Hello wut()
}
typedef Bye = Hello;
define wat = wut;
define byebye = hello;
def wat = wut;
def byebye = hello;
fn int hello()
{

View File

@@ -67,8 +67,8 @@ fn int Foo2.mutate(Foo2 *foo)
define oopsInt = test2::argh<int>;
define oopsDouble = test2::argh<int>;
def oopsInt = test2::argh<int>;
def oopsDouble = test2::argh<int>;
typedef Argh = fn int(double, Bobo);
typedef Argh2 = fn int(double, Bobo);
@@ -97,12 +97,12 @@ struct Foo
int b;
}
define getValueInt = test2::getValue<int>;
define getValueDouble = test2::getValue<double>;
def getValueInt = test2::getValue<int>;
def getValueDouble = test2::getValue<double>;
typedef IntBlob = test2::Blob<int>;
typedef DoubleBlob = Blob<double>;
define getMultInt = test2::getMult<int>;
define getMultDouble = test2::getMult<double>;
def getMultInt = test2::getMult<int>;
def getMultDouble = test2::getMult<double>;
typedef IntArray = List<int>;
typedef IntList = LinkedList<int>;
@@ -175,7 +175,7 @@ module hello_world;
import foo;
extern fn int printf(char *, ...);
define doubleMult = foo::check<double>;
def doubleMult = foo::check<double>;
fn void hello()
{
@@ -221,8 +221,8 @@ macro Hello wut()
}
typedef Bye = Hello;
define wat = wut;
define byebye = hello;
def wat = wut;
def byebye = hello;
fn int hello()
{

View File

@@ -1,5 +1,5 @@
import std::io;
typedef Tester = fn int(int x, int y, int z);
def Tester = fn int(int x, int y, int z);
fn int test1(
int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // 20

View File

@@ -9,4 +9,4 @@ fn void abc()
module tester;
import foo;
define abc_my = foo::abc<int>;
def abc_my = foo::abc<int>;

View File

@@ -2,7 +2,7 @@
module test;
import bar;
typedef BazTest = Baz<Test>;
def BazTest = Baz<Test>;
struct Test // #error: Recursive definition of 'Test'
{

View File

@@ -13,8 +13,8 @@ fn Type addMult(Type x, Type a, Type b)
module test;
import gen;
define intMult = gen::mult<int>;
define doubleAddMult = gen::addMult<double>;
def intMult = gen::mult<int>;
def doubleAddMult = gen::addMult<double>;
fn int getIt(int i)
{

View File

@@ -8,7 +8,7 @@ fn Type x(Type t)
module test;
import hello;
define xint = hello::x<int, -123>;
def xint = hello::x<int, -123>;
import std::io;

View File

@@ -10,7 +10,7 @@ struct An3
An2 y;
}
typedef AnCall = fn void();
def AnCall = fn void();
struct An2
{

View File

@@ -1,4 +1,4 @@
typedef NodeNotifyHandler = fn void(TreeView* this, TreeNode* node, String prop, void* data);
def NodeNotifyHandler = fn void(TreeView* this, TreeNode* node, String prop, void* data);
fn void TreeView.nodeNotifyHandler(TreeView* this, TreeNode* node, String prop, void* data) @private {}
struct TreeNode { int abc; NodeNotifyHandler notifyHandler; }

View File

@@ -1,7 +1,7 @@
module compiler_c3;
import std::collections::list;
typedef IntArray = List<int>;
def IntArray = List<int>;
extern fn void printf(char*, ...);

View File

@@ -1,4 +1,4 @@
typedef NodeNotifyHandler = fn void(TreeView* this, TreeNode* node, String prop, void* data);
def NodeNotifyHandler = fn void(TreeView* this, TreeNode* node, String prop, void* data);
fn void TreeView.nodeNotifyHandler(TreeView* this, TreeNode* node, String prop, void* data) @private {}
struct TreeNode { int abc; NodeNotifyHandler notifyHandler; }

View File

@@ -1,4 +1,4 @@
typedef Foo = fn void(int a = 10);
def Foo = fn void(int a = 10);
fn int abc() { return 1; }
typedef Foo2 = fn void(int a = abc());
def Foo2 = fn void(int a = abc());

View File

@@ -4,7 +4,7 @@ fn void test1()
foreach (a : x) { }; // #error: It's not possible to enumerate an expression of type 'int'
}
typedef Test1 = distinct int;
def Test1 = distinct int;
fn void test2()
{

View File

@@ -4,7 +4,7 @@ fn void test1()
foreach_r (a : x) { }; // #error: It's not possible to enumerate an expression of type 'int'
}
typedef Test1 = distinct int;
def Test1 = distinct int;
fn void test2()
{

View File

@@ -1,7 +1,7 @@
typedef Func = fn int(int);
def Func = fn int(int);
typedef Func2 = fn int(Foo*, int);
def Func2 = fn int(Foo*, int);
struct Foo
{

View File

@@ -1,4 +1,4 @@
typedef Foo = int[0]; // #error: An array may not have zero
def Foo = int[0]; // #error: An array may not have zero
struct Bar
{

View File

@@ -4,7 +4,7 @@ struct Foo
int y;
}
typedef Foo = float; // #error: shadow a previous declaration
def Foo = float; // #error: shadow a previous declaration
enum Bar
{
@@ -12,4 +12,4 @@ enum Bar
TEST2
}
typedef Bar = float; // #error: shadow a previous declaration
def Bar = float; // #error: shadow a previous declaration

View File

@@ -49,7 +49,7 @@ fn void test7()
int v = array[1];
}
typedef Number = int;
def Number = int;
fn void test8()
{

View File

@@ -13,7 +13,7 @@ enum Inf2 : char
C,
}
typedef BooInf = Inf;
def BooInf = Inf;
fn void enumInferenceTest()

View File

@@ -4,7 +4,7 @@ enum EnumTest : long
VALUE2
}
typedef Frob = long;
def Frob = long;
enum EnumTestAlias : Frob
{

View File

@@ -1,9 +1,9 @@
typedef Number2 = Number1; // #error: Recursive definition of 'Number2'
typedef Number1 = Number2;
def Number2 = Number1; // #error: Recursive definition of 'Number2'
def Number1 = Number2;
typedef Number = Number; // #error: Recursive definition of 'Number'
def Number = Number; // #error: Recursive definition of 'Number'
typedef Loop2 = Loop; // #error: Recursive definition of 'Loop2'
typedef Loop3 = Loop2;
typedef Loop = Loop3;
def Loop2 = Loop; // #error: Recursive definition of 'Loop2'
def Loop3 = Loop2;
def Loop = Loop3;

View File

@@ -1,2 +1,2 @@
typedef Number = int;
typedef Number = uint; // #error: 'Number' would shadow a previous declaration.
def Number = int;
def Number = uint; // #error: 'Number' would shadow a previous declaration.

View File

@@ -1,4 +1,4 @@
typedef Arr = int[4];
def Arr = int[4];
Arr a = { 3, 4, 5, 6 };

View File

@@ -8,7 +8,7 @@ enum FooEnum
THREE,
}
typedef FooEnumMap = EnumMap<FooEnum, uint>;
def FooEnumMap = EnumMap<FooEnum, uint>;
fn void! enums()
{

View File

@@ -1,7 +1,7 @@
module linkedlist_test @test;
import std::collections::linkedlist;
typedef IntList = LinkedList<int>;
def IntList = LinkedList<int>;
fn void! test_push()
{

View File

@@ -12,14 +12,14 @@ fn void test_ipv4()
fn void! test_ipv4_to_string()
{
InetAddress a = net::ipv4_from_str("127.0.0.1")!;
assert(a.to_string()! == "127.0.0.1");
assert(a.to_string() == "127.0.0.1");
}
fn void! test_ipv6_to_string()
{
InetAddress a = net::ipv6_from_str("2001:db8::2:1")!;
a.to_string()!;
assert(a.to_string()! == "2001:0db8:0000:0000:0000:0000:0002:0001");
a.to_string();
assert(a.to_string() == "2001:0db8:0000:0000:0000:0000:0002:0001");
assert(net::ipv6_from_str("2001:db8::1").to_string()! == "2001:0db8:0000:0000:0000:0000:0000:0001");
assert(net::ipv6_from_str("::1").to_string()! == "0000:0000:0000:0000:0000:0000:0000:0001");
assert(net::ipv6_from_str("2001::1").to_string()! == "2001:0000:0000:0000:0000:0000:0000:0001");