Merge remote-tracking branch 'origin/master' into llvm7
This commit is contained in:
commit
4b2719b51d
@ -600,7 +600,6 @@ set(ZIG_STD_FILES
|
|||||||
"sort.zig"
|
"sort.zig"
|
||||||
"special/bootstrap.zig"
|
"special/bootstrap.zig"
|
||||||
"special/bootstrap_lib.zig"
|
"special/bootstrap_lib.zig"
|
||||||
"special/build_file_template.zig"
|
|
||||||
"special/build_runner.zig"
|
"special/build_runner.zig"
|
||||||
"special/builtin.zig"
|
"special/builtin.zig"
|
||||||
"special/compiler_rt/aulldiv.zig"
|
"special/compiler_rt/aulldiv.zig"
|
||||||
@ -618,22 +617,26 @@ set(ZIG_STD_FILES
|
|||||||
"special/compiler_rt/fixunstfdi.zig"
|
"special/compiler_rt/fixunstfdi.zig"
|
||||||
"special/compiler_rt/fixunstfsi.zig"
|
"special/compiler_rt/fixunstfsi.zig"
|
||||||
"special/compiler_rt/fixunstfti.zig"
|
"special/compiler_rt/fixunstfti.zig"
|
||||||
|
"special/compiler_rt/floattidf.zig"
|
||||||
|
"special/compiler_rt/floattisf.zig"
|
||||||
|
"special/compiler_rt/floattitf.zig"
|
||||||
"special/compiler_rt/floatunditf.zig"
|
"special/compiler_rt/floatunditf.zig"
|
||||||
"special/compiler_rt/floatunsitf.zig"
|
"special/compiler_rt/floatunsitf.zig"
|
||||||
"special/compiler_rt/floatuntidf.zig"
|
"special/compiler_rt/floatuntidf.zig"
|
||||||
"special/compiler_rt/floatuntisf.zig"
|
"special/compiler_rt/floatuntisf.zig"
|
||||||
"special/compiler_rt/floatuntitf.zig"
|
"special/compiler_rt/floatuntitf.zig"
|
||||||
"special/compiler_rt/floattidf.zig"
|
|
||||||
"special/compiler_rt/floattisf.zig"
|
|
||||||
"special/compiler_rt/floattitf.zig"
|
|
||||||
"special/compiler_rt/muloti4.zig"
|
|
||||||
"special/compiler_rt/index.zig"
|
"special/compiler_rt/index.zig"
|
||||||
|
"special/compiler_rt/muloti4.zig"
|
||||||
"special/compiler_rt/truncXfYf2.zig"
|
"special/compiler_rt/truncXfYf2.zig"
|
||||||
"special/compiler_rt/udivmod.zig"
|
"special/compiler_rt/udivmod.zig"
|
||||||
"special/compiler_rt/udivmoddi4.zig"
|
"special/compiler_rt/udivmoddi4.zig"
|
||||||
"special/compiler_rt/udivmodti4.zig"
|
"special/compiler_rt/udivmodti4.zig"
|
||||||
"special/compiler_rt/udivti3.zig"
|
"special/compiler_rt/udivti3.zig"
|
||||||
"special/compiler_rt/umodti3.zig"
|
"special/compiler_rt/umodti3.zig"
|
||||||
|
"special/init-exe/build.zig"
|
||||||
|
"special/init-exe/src/main.zig"
|
||||||
|
"special/init-lib/build.zig"
|
||||||
|
"special/init-lib/src/main.zig"
|
||||||
"special/panic.zig"
|
"special/panic.zig"
|
||||||
"special/test_runner.zig"
|
"special/test_runner.zig"
|
||||||
"unicode.zig"
|
"unicode.zig"
|
||||||
@ -796,6 +799,9 @@ if(MSVC)
|
|||||||
set(EXE_CFLAGS "${EXE_CFLAGS}")
|
set(EXE_CFLAGS "${EXE_CFLAGS}")
|
||||||
else()
|
else()
|
||||||
set(EXE_CFLAGS "${EXE_CFLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fno-exceptions -fno-rtti -Werror=strict-prototypes -Werror=old-style-definition -Werror=type-limits -Wno-missing-braces")
|
set(EXE_CFLAGS "${EXE_CFLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fno-exceptions -fno-rtti -Werror=strict-prototypes -Werror=old-style-definition -Werror=type-limits -Wno-missing-braces")
|
||||||
|
if(MINGW)
|
||||||
|
set(EXE_CFLAGS "${EXE_CFLAGS} -D__USE_MINGW_ANSI_STDIO -Wno-pedantic-ms-format")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(BLAKE_CFLAGS "-std=c99")
|
set(BLAKE_CFLAGS "-std=c99")
|
||||||
|
@ -112,6 +112,7 @@ pub fn build(b: *Builder) !void {
|
|||||||
|
|
||||||
test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes));
|
test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes));
|
||||||
test_step.dependOn(tests.addBuildExampleTests(b, test_filter, modes));
|
test_step.dependOn(tests.addBuildExampleTests(b, test_filter, modes));
|
||||||
|
test_step.dependOn(tests.addCliTests(b, test_filter, modes));
|
||||||
test_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes));
|
test_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes));
|
||||||
test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes));
|
test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes));
|
||||||
test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes));
|
test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes));
|
||||||
|
@ -5877,7 +5877,7 @@ fn add(a: i32, b: i32) i32 {
|
|||||||
{#header_open|@OpaqueType#}
|
{#header_open|@OpaqueType#}
|
||||||
<pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>
|
<pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
Creates a new type with an unknown size and alignment.
|
Creates a new type with an unknown (but non-zero) size and alignment.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
This is typically used for type safety when interacting with C code that does not expose struct details.
|
This is typically used for type safety when interacting with C code that does not expose struct details.
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use @import("std").os.windows;
|
use @import("std").os.windows;
|
||||||
|
|
||||||
|
extern "user32" stdcallcc fn MessageBoxA(hWnd: ?HANDLE, lpText: ?LPCTSTR, lpCaption: ?LPCTSTR, uType: UINT) c_int;
|
||||||
|
|
||||||
export fn WinMain(hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: PWSTR, nCmdShow: INT) INT {
|
export fn WinMain(hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: PWSTR, nCmdShow: INT) INT {
|
||||||
_ = MessageBoxA(null, c"hello", c"title", 0);
|
_ = MessageBoxA(null, c"hello", c"title", 0);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1470,7 +1470,8 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
|
|||||||
case ZigTypeIdArray:
|
case ZigTypeIdArray:
|
||||||
return type_allowed_in_extern(g, type_entry->data.array.child_type);
|
return type_allowed_in_extern(g, type_entry->data.array.child_type);
|
||||||
case ZigTypeIdFn:
|
case ZigTypeIdFn:
|
||||||
return type_entry->data.fn.fn_type_id.cc == CallingConventionC;
|
return type_entry->data.fn.fn_type_id.cc == CallingConventionC ||
|
||||||
|
type_entry->data.fn.fn_type_id.cc == CallingConventionStdcall;
|
||||||
case ZigTypeIdPointer:
|
case ZigTypeIdPointer:
|
||||||
if (type_size(g, type_entry) == 0)
|
if (type_size(g, type_entry) == 0)
|
||||||
return false;
|
return false;
|
||||||
@ -3992,9 +3993,10 @@ uint32_t get_ptr_align(CodeGen *g, ZigType *type) {
|
|||||||
return (ptr_type->data.pointer.explicit_alignment == 0) ?
|
return (ptr_type->data.pointer.explicit_alignment == 0) ?
|
||||||
get_abi_alignment(g, ptr_type->data.pointer.child_type) : ptr_type->data.pointer.explicit_alignment;
|
get_abi_alignment(g, ptr_type->data.pointer.child_type) : ptr_type->data.pointer.explicit_alignment;
|
||||||
} else if (ptr_type->id == ZigTypeIdFn) {
|
} else if (ptr_type->id == ZigTypeIdFn) {
|
||||||
return (ptr_type->data.fn.fn_type_id.alignment == 0) ?
|
// I tried making this use LLVMABIAlignmentOfType but it trips this assertion in LLVM:
|
||||||
LLVMABIAlignmentOfType(g->target_data_ref, ptr_type->data.fn.raw_type_ref) :
|
// "Cannot getTypeInfo() on a type that is unsized!"
|
||||||
ptr_type->data.fn.fn_type_id.alignment;
|
// when getting the alignment of `?extern fn() void`.
|
||||||
|
return (ptr_type->data.fn.fn_type_id.alignment == 0) ? 1 : ptr_type->data.fn.fn_type_id.alignment;
|
||||||
} else if (ptr_type->id == ZigTypeIdPromise) {
|
} else if (ptr_type->id == ZigTypeIdPromise) {
|
||||||
return get_coro_frame_align_bytes(g);
|
return get_coro_frame_align_bytes(g);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1662,6 +1662,22 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z
|
|||||||
if (actual_type->id == ZigTypeIdFloat) {
|
if (actual_type->id == ZigTypeIdFloat) {
|
||||||
return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, "");
|
return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, "");
|
||||||
} else if (actual_type->id == ZigTypeIdInt) {
|
} else if (actual_type->id == ZigTypeIdInt) {
|
||||||
|
if (wanted_bits == 0) {
|
||||||
|
if (!want_runtime_safety)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
LLVMValueRef zero = LLVMConstNull(actual_type->type_ref);
|
||||||
|
LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, expr_val, zero, "");
|
||||||
|
LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenOk");
|
||||||
|
LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenFail");
|
||||||
|
LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
|
||||||
|
|
||||||
|
LLVMPositionBuilderAtEnd(g->builder, fail_block);
|
||||||
|
gen_safety_crash(g, PanicMsgIdCastTruncatedData);
|
||||||
|
|
||||||
|
LLVMPositionBuilderAtEnd(g->builder, ok_block);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");
|
LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");
|
||||||
if (!want_runtime_safety) {
|
if (!want_runtime_safety) {
|
||||||
return trunc_val;
|
return trunc_val;
|
||||||
|
101
src/compiler.cpp
101
src/compiler.cpp
@ -5,6 +5,9 @@
|
|||||||
static Buf saved_compiler_id = BUF_INIT;
|
static Buf saved_compiler_id = BUF_INIT;
|
||||||
static Buf saved_app_data_dir = BUF_INIT;
|
static Buf saved_app_data_dir = BUF_INIT;
|
||||||
static Buf saved_stage1_path = BUF_INIT;
|
static Buf saved_stage1_path = BUF_INIT;
|
||||||
|
static Buf saved_lib_dir = BUF_INIT;
|
||||||
|
static Buf saved_special_dir = BUF_INIT;
|
||||||
|
static Buf saved_std_dir = BUF_INIT;
|
||||||
|
|
||||||
Buf *get_stage1_cache_path() {
|
Buf *get_stage1_cache_path() {
|
||||||
if (saved_stage1_path.list.length != 0) {
|
if (saved_stage1_path.list.length != 0) {
|
||||||
@ -64,3 +67,101 @@ Error get_compiler_id(Buf **result) {
|
|||||||
return ErrorNone;
|
return ErrorNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool test_zig_install_prefix(Buf *test_path, Buf *out_zig_lib_dir) {
|
||||||
|
Buf lib_buf = BUF_INIT;
|
||||||
|
buf_init_from_str(&lib_buf, "lib");
|
||||||
|
|
||||||
|
Buf zig_buf = BUF_INIT;
|
||||||
|
buf_init_from_str(&zig_buf, "zig");
|
||||||
|
|
||||||
|
Buf std_buf = BUF_INIT;
|
||||||
|
buf_init_from_str(&std_buf, "std");
|
||||||
|
|
||||||
|
Buf index_zig_buf = BUF_INIT;
|
||||||
|
buf_init_from_str(&index_zig_buf, "index.zig");
|
||||||
|
|
||||||
|
Buf test_lib_dir = BUF_INIT;
|
||||||
|
Buf test_zig_dir = BUF_INIT;
|
||||||
|
Buf test_std_dir = BUF_INIT;
|
||||||
|
Buf test_index_file = BUF_INIT;
|
||||||
|
|
||||||
|
os_path_join(test_path, &lib_buf, &test_lib_dir);
|
||||||
|
os_path_join(&test_lib_dir, &zig_buf, &test_zig_dir);
|
||||||
|
os_path_join(&test_zig_dir, &std_buf, &test_std_dir);
|
||||||
|
os_path_join(&test_std_dir, &index_zig_buf, &test_index_file);
|
||||||
|
|
||||||
|
int err;
|
||||||
|
bool exists;
|
||||||
|
if ((err = os_file_exists(&test_index_file, &exists))) {
|
||||||
|
exists = false;
|
||||||
|
}
|
||||||
|
if (exists) {
|
||||||
|
buf_init_from_buf(out_zig_lib_dir, &test_zig_dir);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int find_zig_lib_dir(Buf *out_path) {
|
||||||
|
int err;
|
||||||
|
|
||||||
|
Buf self_exe_path = BUF_INIT;
|
||||||
|
buf_resize(&self_exe_path, 0);
|
||||||
|
if (!(err = os_self_exe_path(&self_exe_path))) {
|
||||||
|
Buf *cur_path = &self_exe_path;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
Buf *test_dir = buf_alloc();
|
||||||
|
os_path_dirname(cur_path, test_dir);
|
||||||
|
|
||||||
|
if (buf_eql_buf(test_dir, cur_path)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test_zig_install_prefix(test_dir, out_path)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_path = test_dir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorFileNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buf *get_zig_lib_dir(void) {
|
||||||
|
if (saved_lib_dir.list.length != 0) {
|
||||||
|
return &saved_lib_dir;
|
||||||
|
}
|
||||||
|
buf_resize(&saved_lib_dir, 0);
|
||||||
|
|
||||||
|
int err;
|
||||||
|
if ((err = find_zig_lib_dir(&saved_lib_dir))) {
|
||||||
|
fprintf(stderr, "Unable to find zig lib directory\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
return &saved_lib_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buf *get_zig_std_dir() {
|
||||||
|
if (saved_std_dir.list.length != 0) {
|
||||||
|
return &saved_std_dir;
|
||||||
|
}
|
||||||
|
buf_resize(&saved_std_dir, 0);
|
||||||
|
|
||||||
|
os_path_join(get_zig_lib_dir(), buf_create_from_str("std"), &saved_std_dir);
|
||||||
|
|
||||||
|
return &saved_std_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buf *get_zig_special_dir() {
|
||||||
|
if (saved_special_dir.list.length != 0) {
|
||||||
|
return &saved_special_dir;
|
||||||
|
}
|
||||||
|
buf_resize(&saved_special_dir, 0);
|
||||||
|
|
||||||
|
os_path_join(get_zig_std_dir(), buf_sprintf("special"), &saved_special_dir);
|
||||||
|
|
||||||
|
return &saved_special_dir;
|
||||||
|
}
|
||||||
|
@ -14,4 +14,8 @@
|
|||||||
Buf *get_stage1_cache_path();
|
Buf *get_stage1_cache_path();
|
||||||
Error get_compiler_id(Buf **result);
|
Error get_compiler_id(Buf **result);
|
||||||
|
|
||||||
|
Buf *get_zig_lib_dir();
|
||||||
|
Buf *get_zig_special_dir();
|
||||||
|
Buf *get_zig_std_dir();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
65
src/ir.cpp
65
src/ir.cpp
@ -10015,8 +10015,13 @@ static IrInstruction *ir_analyze_cast_ref(IrAnalyze *ira, IrInstruction *source_
|
|||||||
|
|
||||||
if (value->id == IrInstructionIdLoadPtr) {
|
if (value->id == IrInstructionIdLoadPtr) {
|
||||||
IrInstructionLoadPtr *load_ptr_inst = (IrInstructionLoadPtr *)value;
|
IrInstructionLoadPtr *load_ptr_inst = (IrInstructionLoadPtr *)value;
|
||||||
|
ConstCastOnly const_cast_result = types_match_const_cast_only(ira, wanted_type,
|
||||||
|
load_ptr_inst->ptr->value.type, source_instr->source_node, false);
|
||||||
|
if (const_cast_result.id == ConstCastResultIdInvalid)
|
||||||
|
return ira->codegen->invalid_instruction;
|
||||||
|
if (const_cast_result.id == ConstCastResultIdOk)
|
||||||
return load_ptr_inst->ptr;
|
return load_ptr_inst->ptr;
|
||||||
} else {
|
}
|
||||||
IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instr->scope,
|
IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instr->scope,
|
||||||
source_instr->source_node, value, true, false);
|
source_instr->source_node, value, true, false);
|
||||||
new_instruction->value.type = wanted_type;
|
new_instruction->value.type = wanted_type;
|
||||||
@ -10029,7 +10034,6 @@ static IrInstruction *ir_analyze_cast_ref(IrAnalyze *ira, IrInstruction *source_
|
|||||||
}
|
}
|
||||||
ir_add_alloca(ira, new_instruction, child_type);
|
ir_add_alloca(ira, new_instruction, child_type);
|
||||||
return new_instruction;
|
return new_instruction;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, ZigType *wanted_type) {
|
static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, ZigType *wanted_type) {
|
||||||
@ -11057,7 +11061,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// enum to &const union which has the enum as the tag type
|
// enum to *const union which has the enum as the tag type
|
||||||
if (actual_type->id == ZigTypeIdEnum && wanted_type->id == ZigTypeIdPointer) {
|
if (actual_type->id == ZigTypeIdEnum && wanted_type->id == ZigTypeIdPointer) {
|
||||||
ZigType *union_type = wanted_type->data.pointer.child_type;
|
ZigType *union_type = wanted_type->data.pointer.child_type;
|
||||||
if (union_type->data.unionation.decl_node->data.container_decl.auto_enum ||
|
if (union_type->data.unionation.decl_node->data.container_decl.auto_enum ||
|
||||||
@ -11187,6 +11191,13 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// dereferencing a *u0 is comptime known to be 0
|
||||||
|
if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) {
|
||||||
|
IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,
|
||||||
|
source_instruction->source_node, child_type);
|
||||||
|
init_const_unsigned_negative(&result->value, child_type, 0, false);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
// TODO if the instruction is a const ref instruction we can skip it
|
// TODO if the instruction is a const ref instruction we can skip it
|
||||||
IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,
|
IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,
|
||||||
source_instruction->source_node, ptr);
|
source_instruction->source_node, ptr);
|
||||||
@ -11521,7 +11532,13 @@ static bool optional_value_is_null(ConstExprValue *val) {
|
|||||||
static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
|
static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
|
||||||
Error err;
|
Error err;
|
||||||
IrInstruction *op1 = bin_op_instruction->op1->other;
|
IrInstruction *op1 = bin_op_instruction->op1->other;
|
||||||
|
if (type_is_invalid(op1->value.type))
|
||||||
|
return ira->codegen->builtin_types.entry_invalid;
|
||||||
|
|
||||||
IrInstruction *op2 = bin_op_instruction->op2->other;
|
IrInstruction *op2 = bin_op_instruction->op2->other;
|
||||||
|
if (type_is_invalid(op2->value.type))
|
||||||
|
return ira->codegen->builtin_types.entry_invalid;
|
||||||
|
|
||||||
AstNode *source_node = bin_op_instruction->base.source_node;
|
AstNode *source_node = bin_op_instruction->base.source_node;
|
||||||
|
|
||||||
IrBinOp op_id = bin_op_instruction->op_id;
|
IrBinOp op_id = bin_op_instruction->op_id;
|
||||||
@ -11564,6 +11581,9 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
|
|||||||
ir_link_new_instruction(is_non_null, &bin_op_instruction->base);
|
ir_link_new_instruction(is_non_null, &bin_op_instruction->base);
|
||||||
}
|
}
|
||||||
return ira->codegen->builtin_types.entry_bool;
|
return ira->codegen->builtin_types.entry_bool;
|
||||||
|
} else if (op1->value.type->id == ZigTypeIdNull || op2->value.type->id == ZigTypeIdNull) {
|
||||||
|
ir_add_error_node(ira, source_node, buf_sprintf("comparison against null can only be done with optionals"));
|
||||||
|
return ira->codegen->builtin_types.entry_invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) {
|
if (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) {
|
||||||
@ -12063,6 +12083,12 @@ static ZigType *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *bin_op_
|
|||||||
ir_add_error(ira, &bin_op_instruction->base,
|
ir_add_error(ira, &bin_op_instruction->base,
|
||||||
buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known"));
|
buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known"));
|
||||||
return ira->codegen->builtin_types.entry_invalid;
|
return ira->codegen->builtin_types.entry_invalid;
|
||||||
|
} else if (instr_is_comptime(casted_op2) && bigint_cmp_zero(&casted_op2->value.data.x_bigint) == CmpEQ) {
|
||||||
|
IrInstruction *result = ir_build_cast(&ira->new_irb, bin_op_instruction->base.scope,
|
||||||
|
bin_op_instruction->base.source_node, op1->value.type, op1, CastOpNoop);
|
||||||
|
result->value.type = op1->value.type;
|
||||||
|
ir_link_new_instruction(result, &bin_op_instruction->base);
|
||||||
|
return result->value.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id,
|
ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id,
|
||||||
@ -18165,17 +18191,18 @@ static ZigType *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstructionE
|
|||||||
&source_dir_path,
|
&source_dir_path,
|
||||||
rel_file_path,
|
rel_file_path,
|
||||||
};
|
};
|
||||||
Buf file_path = os_path_resolve(resolve_paths, 2);
|
Buf *file_path = buf_alloc();
|
||||||
|
*file_path = os_path_resolve(resolve_paths, 2);
|
||||||
|
|
||||||
// load from file system into const expr
|
// load from file system into const expr
|
||||||
Buf *file_contents = buf_alloc();
|
Buf *file_contents = buf_alloc();
|
||||||
int err;
|
int err;
|
||||||
if ((err = file_fetch(ira->codegen, &file_path, file_contents))) {
|
if ((err = file_fetch(ira->codegen, file_path, file_contents))) {
|
||||||
if (err == ErrorFileNotFound) {
|
if (err == ErrorFileNotFound) {
|
||||||
ir_add_error(ira, instruction->name, buf_sprintf("unable to find '%s'", buf_ptr(&file_path)));
|
ir_add_error(ira, instruction->name, buf_sprintf("unable to find '%s'", buf_ptr(file_path)));
|
||||||
return ira->codegen->builtin_types.entry_invalid;
|
return ira->codegen->builtin_types.entry_invalid;
|
||||||
} else {
|
} else {
|
||||||
ir_add_error(ira, instruction->name, buf_sprintf("unable to open '%s': %s", buf_ptr(&file_path), err_str(err)));
|
ir_add_error(ira, instruction->name, buf_sprintf("unable to open '%s': %s", buf_ptr(file_path), err_str(err)));
|
||||||
return ira->codegen->builtin_types.entry_invalid;
|
return ira->codegen->builtin_types.entry_invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -18494,6 +18521,9 @@ static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionF
|
|||||||
src_ptr_align = get_abi_alignment(ira->codegen, target->value.type);
|
src_ptr_align = get_abi_alignment(ira->codegen, target->value.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((err = type_resolve(ira->codegen, dest_child_type, ResolveStatusSizeKnown)))
|
||||||
|
return ira->codegen->builtin_types.entry_invalid;
|
||||||
|
|
||||||
ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_child_type,
|
ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_child_type,
|
||||||
src_ptr_const, src_ptr_volatile, PtrLenUnknown,
|
src_ptr_const, src_ptr_volatile, PtrLenUnknown,
|
||||||
src_ptr_align, 0, 0);
|
src_ptr_align, 0, 0);
|
||||||
@ -20174,11 +20204,19 @@ static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtr
|
|||||||
instruction->base.source_node, nullptr, ptr);
|
instruction->base.source_node, nullptr, ptr);
|
||||||
casted_ptr->value.type = dest_type;
|
casted_ptr->value.type = dest_type;
|
||||||
|
|
||||||
|
if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
|
||||||
|
ErrorMsg *msg = ir_add_error(ira, &instruction->base,
|
||||||
|
buf_sprintf("'%s' and '%s' do not have the same in-memory representation",
|
||||||
|
buf_ptr(&src_type->name), buf_ptr(&dest_type->name)));
|
||||||
|
add_error_note(ira->codegen, msg, ptr->source_node,
|
||||||
|
buf_sprintf("'%s' has no in-memory bits", buf_ptr(&src_type->name)));
|
||||||
|
add_error_note(ira->codegen, msg, dest_type_value->source_node,
|
||||||
|
buf_sprintf("'%s' has in-memory bits", buf_ptr(&dest_type->name)));
|
||||||
|
return ira->codegen->builtin_types.entry_invalid;
|
||||||
|
}
|
||||||
|
|
||||||
// Keep the bigger alignment, it can only help-
|
// Keep the bigger alignment, it can only help-
|
||||||
// unless the target is zero bits.
|
// unless the target is zero bits.
|
||||||
if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
|
|
||||||
return ira->codegen->builtin_types.entry_invalid;
|
|
||||||
|
|
||||||
IrInstruction *result;
|
IrInstruction *result;
|
||||||
if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) {
|
if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) {
|
||||||
result = ir_align_cast(ira, casted_ptr, src_align_bytes, false);
|
result = ir_align_cast(ira, casted_ptr, src_align_bytes, false);
|
||||||
@ -20216,6 +20254,11 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
|
|||||||
bigint_write_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count,
|
bigint_write_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count,
|
||||||
codegen->is_big_endian);
|
codegen->is_big_endian);
|
||||||
return;
|
return;
|
||||||
|
case ZigTypeIdEnum:
|
||||||
|
bigint_write_twos_complement(&val->data.x_enum_tag, buf,
|
||||||
|
val->type->data.enumeration.tag_int_type->data.integral.bit_count,
|
||||||
|
codegen->is_big_endian);
|
||||||
|
return;
|
||||||
case ZigTypeIdFloat:
|
case ZigTypeIdFloat:
|
||||||
float_write_ieee597(val, buf, codegen->is_big_endian);
|
float_write_ieee597(val, buf, codegen->is_big_endian);
|
||||||
return;
|
return;
|
||||||
@ -20247,8 +20290,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
|
|||||||
zig_panic("TODO buf_write_value_bytes error union");
|
zig_panic("TODO buf_write_value_bytes error union");
|
||||||
case ZigTypeIdErrorSet:
|
case ZigTypeIdErrorSet:
|
||||||
zig_panic("TODO buf_write_value_bytes pure error type");
|
zig_panic("TODO buf_write_value_bytes pure error type");
|
||||||
case ZigTypeIdEnum:
|
|
||||||
zig_panic("TODO buf_write_value_bytes enum type");
|
|
||||||
case ZigTypeIdFn:
|
case ZigTypeIdFn:
|
||||||
zig_panic("TODO buf_write_value_bytes fn type");
|
zig_panic("TODO buf_write_value_bytes fn type");
|
||||||
case ZigTypeIdUnion:
|
case ZigTypeIdUnion:
|
||||||
|
230
src/main.cpp
230
src/main.cpp
@ -25,6 +25,8 @@ static int usage(const char *arg0) {
|
|||||||
" build-obj [source] create object from source or assembly\n"
|
" build-obj [source] create object from source or assembly\n"
|
||||||
" builtin show the source code of that @import(\"builtin\")\n"
|
" builtin show the source code of that @import(\"builtin\")\n"
|
||||||
" id print the base64-encoded compiler id\n"
|
" id print the base64-encoded compiler id\n"
|
||||||
|
" init-exe initialize a `zig build` application in the cwd\n"
|
||||||
|
" init-lib initialize a `zig build` library in the cwd\n"
|
||||||
" run [source] create executable and run immediately\n"
|
" run [source] create executable and run immediately\n"
|
||||||
" translate-c [source] convert c code to zig code\n"
|
" translate-c [source] convert c code to zig code\n"
|
||||||
" targets list available compilation targets\n"
|
" targets list available compilation targets\n"
|
||||||
@ -34,7 +36,7 @@ static int usage(const char *arg0) {
|
|||||||
"Compile Options:\n"
|
"Compile Options:\n"
|
||||||
" --assembly [source] add assembly file to build\n"
|
" --assembly [source] add assembly file to build\n"
|
||||||
" --cache-dir [path] override the cache directory\n"
|
" --cache-dir [path] override the cache directory\n"
|
||||||
" --cache [auto|off|on] build to the global cache and print output path to stdout\n"
|
" --cache [auto|off|on] build in global cache, print out paths to stdout\n"
|
||||||
" --color [auto|off|on] enable or disable colored error messages\n"
|
" --color [auto|off|on] enable or disable colored error messages\n"
|
||||||
" --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"
|
" --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"
|
||||||
" -ftime-report print timing diagnostics\n"
|
" -ftime-report print timing diagnostics\n"
|
||||||
@ -42,7 +44,7 @@ static int usage(const char *arg0) {
|
|||||||
" --name [name] override output name\n"
|
" --name [name] override output name\n"
|
||||||
" --output [file] override destination path\n"
|
" --output [file] override destination path\n"
|
||||||
" --output-h [file] override generated header file path\n"
|
" --output-h [file] override generated header file path\n"
|
||||||
" --pkg-begin [name] [path] make package available to import and push current pkg\n"
|
" --pkg-begin [name] [path] make pkg available to import and push current pkg\n"
|
||||||
" --pkg-end pop current pkg\n"
|
" --pkg-end pop current pkg\n"
|
||||||
" --release-fast build with optimizations on and safety off\n"
|
" --release-fast build with optimizations on and safety off\n"
|
||||||
" --release-safe build with optimizations on and safety on\n"
|
" --release-safe build with optimizations on and safety on\n"
|
||||||
@ -52,17 +54,16 @@ static int usage(const char *arg0) {
|
|||||||
" --target-arch [name] specify target architecture\n"
|
" --target-arch [name] specify target architecture\n"
|
||||||
" --target-environ [name] specify target environment\n"
|
" --target-environ [name] specify target environment\n"
|
||||||
" --target-os [name] specify target operating system\n"
|
" --target-os [name] specify target operating system\n"
|
||||||
" --verbose-tokenize turn on compiler debug output for tokenization\n"
|
" --verbose-tokenize enable compiler debug output for tokenization\n"
|
||||||
" --verbose-ast turn on compiler debug output for parsing into an AST\n"
|
" --verbose-ast enable compiler debug output for AST parsing\n"
|
||||||
" --verbose-link turn on compiler debug output for linking\n"
|
" --verbose-link enable compiler debug output for linking\n"
|
||||||
" --verbose-ir turn on compiler debug output for Zig IR\n"
|
" --verbose-ir enable compiler debug output for Zig IR\n"
|
||||||
" --verbose-llvm-ir turn on compiler debug output for LLVM IR\n"
|
" --verbose-llvm-ir enable compiler debug output for LLVM IR\n"
|
||||||
" --verbose-cimport turn on compiler debug output for C imports\n"
|
" --verbose-cimport enable compiler debug output for C imports\n"
|
||||||
" -dirafter [dir] same as -isystem but do it last\n"
|
" -dirafter [dir] same as -isystem but do it last\n"
|
||||||
" -isystem [dir] add additional search path for other .h files\n"
|
" -isystem [dir] add additional search path for other .h files\n"
|
||||||
" -mllvm [arg] additional arguments to forward to LLVM's option processing\n"
|
" -mllvm [arg] forward an arg to LLVM's option processing\n"
|
||||||
"Link Options:\n"
|
"Link Options:\n"
|
||||||
" --ar-path [path] set the path to ar\n"
|
|
||||||
" --dynamic-linker [path] set the path to ld.so\n"
|
" --dynamic-linker [path] set the path to ld.so\n"
|
||||||
" --each-lib-rpath add rpath for each used dynamic library\n"
|
" --each-lib-rpath add rpath for each used dynamic library\n"
|
||||||
" --libc-lib-dir [path] directory where libc crt1.o resides\n"
|
" --libc-lib-dir [path] directory where libc crt1.o resides\n"
|
||||||
@ -142,78 +143,6 @@ static int print_target_list(FILE *f) {
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool test_zig_install_prefix(Buf *test_path, Buf *out_zig_lib_dir) {
|
|
||||||
Buf lib_buf = BUF_INIT;
|
|
||||||
buf_init_from_str(&lib_buf, "lib");
|
|
||||||
|
|
||||||
Buf zig_buf = BUF_INIT;
|
|
||||||
buf_init_from_str(&zig_buf, "zig");
|
|
||||||
|
|
||||||
Buf std_buf = BUF_INIT;
|
|
||||||
buf_init_from_str(&std_buf, "std");
|
|
||||||
|
|
||||||
Buf index_zig_buf = BUF_INIT;
|
|
||||||
buf_init_from_str(&index_zig_buf, "index.zig");
|
|
||||||
|
|
||||||
Buf test_lib_dir = BUF_INIT;
|
|
||||||
Buf test_zig_dir = BUF_INIT;
|
|
||||||
Buf test_std_dir = BUF_INIT;
|
|
||||||
Buf test_index_file = BUF_INIT;
|
|
||||||
|
|
||||||
os_path_join(test_path, &lib_buf, &test_lib_dir);
|
|
||||||
os_path_join(&test_lib_dir, &zig_buf, &test_zig_dir);
|
|
||||||
os_path_join(&test_zig_dir, &std_buf, &test_std_dir);
|
|
||||||
os_path_join(&test_std_dir, &index_zig_buf, &test_index_file);
|
|
||||||
|
|
||||||
int err;
|
|
||||||
bool exists;
|
|
||||||
if ((err = os_file_exists(&test_index_file, &exists))) {
|
|
||||||
exists = false;
|
|
||||||
}
|
|
||||||
if (exists) {
|
|
||||||
buf_init_from_buf(out_zig_lib_dir, &test_zig_dir);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int find_zig_lib_dir(Buf *out_path) {
|
|
||||||
int err;
|
|
||||||
|
|
||||||
Buf self_exe_path = BUF_INIT;
|
|
||||||
buf_resize(&self_exe_path, 0);
|
|
||||||
if (!(err = os_self_exe_path(&self_exe_path))) {
|
|
||||||
Buf *cur_path = &self_exe_path;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
Buf *test_dir = buf_alloc();
|
|
||||||
os_path_dirname(cur_path, test_dir);
|
|
||||||
|
|
||||||
if (buf_eql_buf(test_dir, cur_path)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (test_zig_install_prefix(test_dir, out_path)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_path = test_dir;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ErrorFileNotFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Buf *resolve_zig_lib_dir(void) {
|
|
||||||
int err;
|
|
||||||
Buf *result = buf_alloc();
|
|
||||||
if ((err = find_zig_lib_dir(result))) {
|
|
||||||
fprintf(stderr, "Unable to find zig lib directory\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Cmd {
|
enum Cmd {
|
||||||
CmdInvalid,
|
CmdInvalid,
|
||||||
CmdBuild,
|
CmdBuild,
|
||||||
@ -277,6 +206,9 @@ static bool get_cache_opt(CacheOpt opt, bool default_value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
char *arg0 = argv[0];
|
||||||
|
Error err;
|
||||||
|
|
||||||
if (argc == 2 && strcmp(argv[1], "BUILD_INFO") == 0) {
|
if (argc == 2 && strcmp(argv[1], "BUILD_INFO") == 0) {
|
||||||
printf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
|
printf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
|
||||||
ZIG_CMAKE_BINARY_DIR,
|
ZIG_CMAKE_BINARY_DIR,
|
||||||
@ -290,8 +222,10 @@ int main(int argc, char **argv) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Must be before all os.hpp function calls.
|
||||||
|
os_init();
|
||||||
|
|
||||||
if (argc == 2 && strcmp(argv[1], "id") == 0) {
|
if (argc == 2 && strcmp(argv[1], "id") == 0) {
|
||||||
Error err;
|
|
||||||
Buf *compiler_id;
|
Buf *compiler_id;
|
||||||
if ((err = get_compiler_id(&compiler_id))) {
|
if ((err = get_compiler_id(&compiler_id))) {
|
||||||
fprintf(stderr, "Unable to determine compiler id: %s\n", err_str(err));
|
fprintf(stderr, "Unable to determine compiler id: %s\n", err_str(err));
|
||||||
@ -301,9 +235,97 @@ int main(int argc, char **argv) {
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
os_init();
|
enum InitKind {
|
||||||
|
InitKindNone,
|
||||||
|
InitKindExe,
|
||||||
|
InitKindLib,
|
||||||
|
};
|
||||||
|
InitKind init_kind = InitKindNone;
|
||||||
|
if (argc >= 2) {
|
||||||
|
const char *init_cmd = argv[1];
|
||||||
|
if (strcmp(init_cmd, "init-exe") == 0) {
|
||||||
|
init_kind = InitKindExe;
|
||||||
|
} else if (strcmp(init_cmd, "init-lib") == 0) {
|
||||||
|
init_kind = InitKindLib;
|
||||||
|
}
|
||||||
|
if (init_kind != InitKindNone) {
|
||||||
|
if (argc >= 3) {
|
||||||
|
fprintf(stderr, "Unexpected extra argument: %s\n", argv[2]);
|
||||||
|
return usage(arg0);
|
||||||
|
}
|
||||||
|
Buf *cmd_template_path = buf_alloc();
|
||||||
|
os_path_join(get_zig_special_dir(), buf_create_from_str(init_cmd), cmd_template_path);
|
||||||
|
Buf *build_zig_path = buf_alloc();
|
||||||
|
os_path_join(cmd_template_path, buf_create_from_str("build.zig"), build_zig_path);
|
||||||
|
Buf *src_dir_path = buf_alloc();
|
||||||
|
os_path_join(cmd_template_path, buf_create_from_str("src"), src_dir_path);
|
||||||
|
Buf *main_zig_path = buf_alloc();
|
||||||
|
os_path_join(src_dir_path, buf_create_from_str("main.zig"), main_zig_path);
|
||||||
|
|
||||||
|
Buf *cwd = buf_alloc();
|
||||||
|
if ((err = os_get_cwd(cwd))) {
|
||||||
|
fprintf(stderr, "Unable to get cwd: %s\n", err_str(err));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
Buf *cwd_basename = buf_alloc();
|
||||||
|
os_path_split(cwd, nullptr, cwd_basename);
|
||||||
|
|
||||||
|
Buf *build_zig_contents = buf_alloc();
|
||||||
|
if ((err = os_fetch_file_path(build_zig_path, build_zig_contents, false))) {
|
||||||
|
fprintf(stderr, "Unable to read %s: %s\n", buf_ptr(build_zig_path), err_str(err));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
Buf *modified_build_zig_contents = buf_alloc();
|
||||||
|
for (size_t i = 0; i < buf_len(build_zig_contents); i += 1) {
|
||||||
|
char c = buf_ptr(build_zig_contents)[i];
|
||||||
|
if (c == '$') {
|
||||||
|
buf_append_buf(modified_build_zig_contents, cwd_basename);
|
||||||
|
} else {
|
||||||
|
buf_append_char(modified_build_zig_contents, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Buf *main_zig_contents = buf_alloc();
|
||||||
|
if ((err = os_fetch_file_path(main_zig_path, main_zig_contents, false))) {
|
||||||
|
fprintf(stderr, "Unable to read %s: %s\n", buf_ptr(main_zig_path), err_str(err));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buf *out_build_zig_path = buf_create_from_str("build.zig");
|
||||||
|
Buf *out_src_dir_path = buf_create_from_str("src");
|
||||||
|
Buf *out_main_zig_path = buf_alloc();
|
||||||
|
os_path_join(out_src_dir_path, buf_create_from_str("main.zig"), out_main_zig_path);
|
||||||
|
|
||||||
|
bool already_exists;
|
||||||
|
if ((err = os_file_exists(out_build_zig_path, &already_exists))) {
|
||||||
|
fprintf(stderr, "Unable test existence of %s: %s\n", buf_ptr(out_build_zig_path), err_str(err));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if (already_exists) {
|
||||||
|
fprintf(stderr, "This file would be overwritten: %s\n", buf_ptr(out_build_zig_path));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = os_make_dir(out_src_dir_path))) {
|
||||||
|
fprintf(stderr, "Unable to make directory: %s: %s\n", buf_ptr(out_src_dir_path), err_str(err));
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
os_write_file(out_build_zig_path, modified_build_zig_contents);
|
||||||
|
os_write_file(out_main_zig_path, main_zig_contents);
|
||||||
|
fprintf(stderr, "Created %s\n", buf_ptr(out_build_zig_path));
|
||||||
|
fprintf(stderr, "Created %s\n", buf_ptr(out_main_zig_path));
|
||||||
|
if (init_kind == InitKindExe) {
|
||||||
|
fprintf(stderr, "\nNext, try `zig build --help` or `zig build run`\n");
|
||||||
|
} else if (init_kind == InitKindLib) {
|
||||||
|
fprintf(stderr, "\nNext, try `zig build --help` or `zig build test`\n");
|
||||||
|
} else {
|
||||||
|
zig_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char *arg0 = argv[0];
|
|
||||||
Cmd cmd = CmdInvalid;
|
Cmd cmd = CmdInvalid;
|
||||||
EmitFileType emit_file_type = EmitFileTypeBinary;
|
EmitFileType emit_file_type = EmitFileTypeBinary;
|
||||||
const char *in_file = nullptr;
|
const char *in_file = nullptr;
|
||||||
@ -333,7 +355,6 @@ int main(int argc, char **argv) {
|
|||||||
ZigList<const char *> link_libs = {0};
|
ZigList<const char *> link_libs = {0};
|
||||||
ZigList<const char *> forbidden_link_libs = {0};
|
ZigList<const char *> forbidden_link_libs = {0};
|
||||||
ZigList<const char *> frameworks = {0};
|
ZigList<const char *> frameworks = {0};
|
||||||
int err;
|
|
||||||
const char *target_arch = nullptr;
|
const char *target_arch = nullptr;
|
||||||
const char *target_os = nullptr;
|
const char *target_os = nullptr;
|
||||||
const char *target_environ = nullptr;
|
const char *target_environ = nullptr;
|
||||||
@ -364,7 +385,6 @@ int main(int argc, char **argv) {
|
|||||||
const char *zig_exe_path = arg0;
|
const char *zig_exe_path = arg0;
|
||||||
const char *build_file = "build.zig";
|
const char *build_file = "build.zig";
|
||||||
bool asked_for_help = false;
|
bool asked_for_help = false;
|
||||||
bool asked_to_init = false;
|
|
||||||
|
|
||||||
init_all_targets();
|
init_all_targets();
|
||||||
|
|
||||||
@ -376,9 +396,6 @@ int main(int argc, char **argv) {
|
|||||||
if (strcmp(argv[i], "--help") == 0) {
|
if (strcmp(argv[i], "--help") == 0) {
|
||||||
asked_for_help = true;
|
asked_for_help = true;
|
||||||
args.append(argv[i]);
|
args.append(argv[i]);
|
||||||
} else if (strcmp(argv[i], "--init") == 0) {
|
|
||||||
asked_to_init = true;
|
|
||||||
args.append(argv[i]);
|
|
||||||
} else if (i + 1 < argc && strcmp(argv[i], "--build-file") == 0) {
|
} else if (i + 1 < argc && strcmp(argv[i], "--build-file") == 0) {
|
||||||
build_file = argv[i + 1];
|
build_file = argv[i + 1];
|
||||||
i += 1;
|
i += 1;
|
||||||
@ -390,18 +407,10 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Buf *zig_lib_dir_buf = resolve_zig_lib_dir();
|
|
||||||
|
|
||||||
Buf *zig_std_dir = buf_alloc();
|
|
||||||
os_path_join(zig_lib_dir_buf, buf_create_from_str("std"), zig_std_dir);
|
|
||||||
|
|
||||||
Buf *special_dir = buf_alloc();
|
|
||||||
os_path_join(zig_std_dir, buf_sprintf("special"), special_dir);
|
|
||||||
|
|
||||||
Buf *build_runner_path = buf_alloc();
|
Buf *build_runner_path = buf_alloc();
|
||||||
os_path_join(special_dir, buf_create_from_str("build_runner.zig"), build_runner_path);
|
os_path_join(get_zig_special_dir(), buf_create_from_str("build_runner.zig"), build_runner_path);
|
||||||
|
|
||||||
CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, zig_lib_dir_buf);
|
CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir());
|
||||||
g->enable_time_report = timing_info;
|
g->enable_time_report = timing_info;
|
||||||
buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
|
buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
|
||||||
codegen_set_out_name(g, buf_create_from_str("build"));
|
codegen_set_out_name(g, buf_create_from_str("build"));
|
||||||
@ -437,7 +446,6 @@ int main(int argc, char **argv) {
|
|||||||
"\n"
|
"\n"
|
||||||
"General Options:\n"
|
"General Options:\n"
|
||||||
" --help Print this help and exit\n"
|
" --help Print this help and exit\n"
|
||||||
" --init Generate a build.zig template\n"
|
|
||||||
" --build-file [file] Override path to build.zig\n"
|
" --build-file [file] Override path to build.zig\n"
|
||||||
" --cache-dir [path] Override path to cache directory\n"
|
" --cache-dir [path] Override path to cache directory\n"
|
||||||
" --verbose Print commands before executing them\n"
|
" --verbose Print commands before executing them\n"
|
||||||
@ -463,22 +471,11 @@ int main(int argc, char **argv) {
|
|||||||
"\n"
|
"\n"
|
||||||
, zig_exe_path);
|
, zig_exe_path);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
} else if (asked_to_init) {
|
|
||||||
Buf *build_template_path = buf_alloc();
|
|
||||||
os_path_join(special_dir, buf_create_from_str("build_file_template.zig"), build_template_path);
|
|
||||||
|
|
||||||
if ((err = os_copy_file(build_template_path, &build_file_abs))) {
|
|
||||||
fprintf(stderr, "Unable to write build.zig template: %s\n", err_str(err));
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Wrote build.zig template\n");
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"No 'build.zig' file found.\n"
|
"No 'build.zig' file found.\n"
|
||||||
"Initialize a 'build.zig' template file with `zig build --init`,\n"
|
"Initialize a 'build.zig' template file with `zig init-lib` or `zig init-exe`,\n"
|
||||||
"or build an executable directly with `zig build-exe $FILENAME.zig`.\n"
|
"or build an executable directly with `zig build-exe $FILENAME.zig`.\n"
|
||||||
"See: `zig build --help` or `zig help` for more options.\n"
|
"See: `zig build --help` or `zig help` for more options.\n"
|
||||||
);
|
);
|
||||||
@ -773,8 +770,7 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case CmdBuiltin: {
|
case CmdBuiltin: {
|
||||||
Buf *zig_lib_dir_buf = resolve_zig_lib_dir();
|
CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, get_zig_lib_dir());
|
||||||
CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, zig_lib_dir_buf);
|
|
||||||
Buf *builtin_source = codegen_generate_builtin_source(g);
|
Buf *builtin_source = codegen_generate_builtin_source(g);
|
||||||
if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {
|
if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {
|
||||||
fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout)));
|
fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout)));
|
||||||
@ -832,9 +828,7 @@ int main(int argc, char **argv) {
|
|||||||
if (cmd == CmdRun && buf_out_name == nullptr) {
|
if (cmd == CmdRun && buf_out_name == nullptr) {
|
||||||
buf_out_name = buf_create_from_str("run");
|
buf_out_name = buf_create_from_str("run");
|
||||||
}
|
}
|
||||||
Buf *zig_lib_dir_buf = resolve_zig_lib_dir();
|
CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir());
|
||||||
|
|
||||||
CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, zig_lib_dir_buf);
|
|
||||||
g->enable_time_report = timing_info;
|
g->enable_time_report = timing_info;
|
||||||
buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
|
buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
|
||||||
codegen_set_out_name(g, buf_out_name);
|
codegen_set_out_name(g, buf_out_name);
|
||||||
|
26
src/os.cpp
26
src/os.cpp
@ -23,6 +23,14 @@
|
|||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(_WIN32_WINNT)
|
||||||
|
#define _WIN32_WINNT 0x600
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(NTDDI_VERSION)
|
||||||
|
#define NTDDI_VERSION 0x06000000
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
@ -1091,14 +1099,14 @@ Error os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int os_get_cwd(Buf *out_cwd) {
|
Error os_get_cwd(Buf *out_cwd) {
|
||||||
#if defined(ZIG_OS_WINDOWS)
|
#if defined(ZIG_OS_WINDOWS)
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
if (GetCurrentDirectory(4096, buf) == 0) {
|
if (GetCurrentDirectory(4096, buf) == 0) {
|
||||||
zig_panic("GetCurrentDirectory failed");
|
zig_panic("GetCurrentDirectory failed");
|
||||||
}
|
}
|
||||||
buf_init_from_str(out_cwd, buf);
|
buf_init_from_str(out_cwd, buf);
|
||||||
return 0;
|
return ErrorNone;
|
||||||
#elif defined(ZIG_OS_POSIX)
|
#elif defined(ZIG_OS_POSIX)
|
||||||
char buf[PATH_MAX];
|
char buf[PATH_MAX];
|
||||||
char *res = getcwd(buf, PATH_MAX);
|
char *res = getcwd(buf, PATH_MAX);
|
||||||
@ -1106,7 +1114,7 @@ int os_get_cwd(Buf *out_cwd) {
|
|||||||
zig_panic("unable to get cwd: %s", strerror(errno));
|
zig_panic("unable to get cwd: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
buf_init_from_str(out_cwd, res);
|
buf_init_from_str(out_cwd, res);
|
||||||
return 0;
|
return ErrorNone;
|
||||||
#else
|
#else
|
||||||
#error "missing os_get_cwd implementation"
|
#error "missing os_get_cwd implementation"
|
||||||
#endif
|
#endif
|
||||||
@ -1634,16 +1642,16 @@ static Optional<uint32_t> Utf16LeIterator_nextCodepoint(Utf16LeIterator *it) {
|
|||||||
if (it->bytes[it->i] == 0 && it->bytes[it->i + 1] == 0)
|
if (it->bytes[it->i] == 0 && it->bytes[it->i + 1] == 0)
|
||||||
return {};
|
return {};
|
||||||
uint32_t c0 = ((uint32_t)it->bytes[it->i]) | (((uint32_t)it->bytes[it->i + 1]) << 8);
|
uint32_t c0 = ((uint32_t)it->bytes[it->i]) | (((uint32_t)it->bytes[it->i + 1]) << 8);
|
||||||
if (c0 & ~((uint32_t)0x03ff) == 0xd800) {
|
if ((c0 & ~((uint32_t)0x03ff)) == 0xd800) {
|
||||||
// surrogate pair
|
// surrogate pair
|
||||||
it->i += 2;
|
it->i += 2;
|
||||||
assert(it->bytes[it->i] != 0 || it->bytes[it->i + 1] != 0);
|
assert(it->bytes[it->i] != 0 || it->bytes[it->i + 1] != 0);
|
||||||
uint32_t c1 = ((uint32_t)it->bytes[it->i]) | (((uint32_t)it->bytes[it->i + 1]) << 8);
|
uint32_t c1 = ((uint32_t)it->bytes[it->i]) | (((uint32_t)it->bytes[it->i + 1]) << 8);
|
||||||
assert(c1 & ~((uint32_t)0x03ff) == 0xdc00);
|
assert((c1 & ~((uint32_t)0x03ff)) == 0xdc00);
|
||||||
it->i += 2;
|
it->i += 2;
|
||||||
return Optional<uint32_t>::some(0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff)));
|
return Optional<uint32_t>::some(0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff)));
|
||||||
} else {
|
} else {
|
||||||
assert(c0 & ~((uint32_t)0x03ff) != 0xdc00);
|
assert((c0 & ~((uint32_t)0x03ff)) != 0xdc00);
|
||||||
it->i += 2;
|
it->i += 2;
|
||||||
return Optional<uint32_t>::some(c0);
|
return Optional<uint32_t>::some(c0);
|
||||||
}
|
}
|
||||||
@ -1714,7 +1722,6 @@ static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le) {
|
|||||||
// Ported from std.os.getAppDataDir
|
// Ported from std.os.getAppDataDir
|
||||||
Error os_get_app_data_dir(Buf *out_path, const char *appname) {
|
Error os_get_app_data_dir(Buf *out_path, const char *appname) {
|
||||||
#if defined(ZIG_OS_WINDOWS)
|
#if defined(ZIG_OS_WINDOWS)
|
||||||
Error err;
|
|
||||||
WCHAR *dir_path_ptr;
|
WCHAR *dir_path_ptr;
|
||||||
switch (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &dir_path_ptr)) {
|
switch (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &dir_path_ptr)) {
|
||||||
case S_OK:
|
case S_OK:
|
||||||
@ -1928,7 +1935,7 @@ Error os_file_mtime(OsFile file, OsTimeStamp *mtime) {
|
|||||||
FILETIME last_write_time;
|
FILETIME last_write_time;
|
||||||
if (!GetFileTime(file, nullptr, nullptr, &last_write_time))
|
if (!GetFileTime(file, nullptr, nullptr, &last_write_time))
|
||||||
return ErrorUnexpected;
|
return ErrorUnexpected;
|
||||||
mtime->sec = last_write_time.dwLowDateTime | (last_write_time.dwHighDateTime << 32);
|
mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime;
|
||||||
mtime->nsec = 0;
|
mtime->nsec = 0;
|
||||||
return ErrorNone;
|
return ErrorNone;
|
||||||
#elif defined(ZIG_OS_LINUX)
|
#elif defined(ZIG_OS_LINUX)
|
||||||
@ -2011,7 +2018,8 @@ Error os_file_overwrite(OsFile file, Buf *contents) {
|
|||||||
return ErrorFileSystem;
|
return ErrorFileSystem;
|
||||||
if (!SetEndOfFile(file))
|
if (!SetEndOfFile(file))
|
||||||
return ErrorFileSystem;
|
return ErrorFileSystem;
|
||||||
if (!WriteFile(file, buf_ptr(contents), buf_len(contents), nullptr, nullptr))
|
DWORD bytes_written;
|
||||||
|
if (!WriteFile(file, buf_ptr(contents), buf_len(contents), &bytes_written, nullptr))
|
||||||
return ErrorFileSystem;
|
return ErrorFileSystem;
|
||||||
return ErrorNone;
|
return ErrorNone;
|
||||||
#else
|
#else
|
||||||
|
@ -114,7 +114,7 @@ int os_copy_file(Buf *src_path, Buf *dest_path);
|
|||||||
Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents, bool skip_shebang);
|
Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents, bool skip_shebang);
|
||||||
Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang);
|
Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang);
|
||||||
|
|
||||||
int os_get_cwd(Buf *out_cwd);
|
Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd);
|
||||||
|
|
||||||
bool os_stderr_tty(void);
|
bool os_stderr_tty(void);
|
||||||
void os_stderr_set_color(TermColor color);
|
void os_stderr_set_color(TermColor color);
|
||||||
|
@ -28,6 +28,9 @@
|
|||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
|
|
||||||
|
// Standard headers
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
// COM support header files
|
// COM support header files
|
||||||
#include <comdef.h>
|
#include <comdef.h>
|
||||||
|
|
||||||
|
@ -11,18 +11,6 @@ pub const HKEY__ = extern struct {
|
|||||||
};
|
};
|
||||||
pub const LSTATUS = LONG;
|
pub const LSTATUS = LONG;
|
||||||
|
|
||||||
pub extern "advapi32" stdcallcc fn CryptAcquireContextA(
|
|
||||||
phProv: *HCRYPTPROV,
|
|
||||||
pszContainer: ?LPCSTR,
|
|
||||||
pszProvider: ?LPCSTR,
|
|
||||||
dwProvType: DWORD,
|
|
||||||
dwFlags: DWORD,
|
|
||||||
) BOOL;
|
|
||||||
|
|
||||||
pub extern "advapi32" stdcallcc fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) BOOL;
|
|
||||||
|
|
||||||
pub extern "advapi32" stdcallcc fn CryptGenRandom(hProv: HCRYPTPROV, dwLen: DWORD, pbBuffer: [*]BYTE) BOOL;
|
|
||||||
|
|
||||||
pub extern "advapi32" stdcallcc fn RegOpenKeyExW(
|
pub extern "advapi32" stdcallcc fn RegOpenKeyExW(
|
||||||
hKey: HKEY,
|
hKey: HKEY,
|
||||||
lpSubKey: LPCWSTR,
|
lpSubKey: LPCWSTR,
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
const Builder = @import("std").build.Builder;
|
|
||||||
|
|
||||||
pub fn build(b: *Builder) void {
|
|
||||||
const mode = b.standardReleaseOptions();
|
|
||||||
const exe = b.addExecutable("YOUR_NAME_HERE", "src/main.zig");
|
|
||||||
exe.setBuildMode(mode);
|
|
||||||
|
|
||||||
b.default_step.dependOn(&exe.step);
|
|
||||||
b.installArtifact(exe);
|
|
||||||
}
|
|
15
std/special/init-exe/build.zig
Normal file
15
std/special/init-exe/build.zig
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
const Builder = @import("std").build.Builder;
|
||||||
|
|
||||||
|
pub fn build(b: *Builder) void {
|
||||||
|
const mode = b.standardReleaseOptions();
|
||||||
|
const exe = b.addExecutable("$", "src/main.zig");
|
||||||
|
exe.setBuildMode(mode);
|
||||||
|
|
||||||
|
const run_step = b.step("run", "Run the app");
|
||||||
|
const run_cmd = b.addCommand(".", b.env_map, [][]const u8{exe.getOutputPath()});
|
||||||
|
run_step.dependOn(&run_cmd.step);
|
||||||
|
run_cmd.step.dependOn(&exe.step);
|
||||||
|
|
||||||
|
b.default_step.dependOn(&exe.step);
|
||||||
|
b.installArtifact(exe);
|
||||||
|
}
|
5
std/special/init-exe/src/main.zig
Normal file
5
std/special/init-exe/src/main.zig
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn main() error!void {
|
||||||
|
std.debug.warn("All your base are belong to us.\n");
|
||||||
|
}
|
16
std/special/init-lib/build.zig
Normal file
16
std/special/init-lib/build.zig
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
const Builder = @import("std").build.Builder;
|
||||||
|
|
||||||
|
pub fn build(b: *Builder) void {
|
||||||
|
const mode = b.standardReleaseOptions();
|
||||||
|
const lib = b.addStaticLibrary("$", "src/main.zig");
|
||||||
|
lib.setBuildMode(mode);
|
||||||
|
|
||||||
|
var main_tests = b.addTest("src/main.zig");
|
||||||
|
main_tests.setBuildMode(mode);
|
||||||
|
|
||||||
|
const test_step = b.step("test", "Run library tests");
|
||||||
|
test_step.dependOn(&main_tests.step);
|
||||||
|
|
||||||
|
b.default_step.dependOn(&lib.step);
|
||||||
|
b.installArtifact(lib);
|
||||||
|
}
|
10
std/special/init-lib/src/main.zig
Normal file
10
std/special/init-lib/src/main.zig
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const assertOrPanic = std.debug.assertOrPanic;
|
||||||
|
|
||||||
|
export fn add(a: i32, b: i32) i32 {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
test "basic add functionality" {
|
||||||
|
assertOrPanic(add(3, 7) == 10);
|
||||||
|
}
|
@ -71,4 +71,5 @@ comptime {
|
|||||||
_ = @import("cases/void.zig");
|
_ = @import("cases/void.zig");
|
||||||
_ = @import("cases/while.zig");
|
_ = @import("cases/while.zig");
|
||||||
_ = @import("cases/widening.zig");
|
_ = @import("cases/widening.zig");
|
||||||
|
_ = @import("cases/bit_shifting.zig");
|
||||||
}
|
}
|
||||||
|
@ -219,3 +219,12 @@ test "alignment of structs" {
|
|||||||
b: *i32,
|
b: *i32,
|
||||||
}) == @alignOf(usize));
|
}) == @alignOf(usize));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "alignment of extern() void" {
|
||||||
|
var runtime_nothing = nothing;
|
||||||
|
const casted1 = @ptrCast(*const u8, runtime_nothing);
|
||||||
|
const casted2 = @ptrCast(extern fn () void, casted1);
|
||||||
|
casted2();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern fn nothing() void {}
|
||||||
|
88
test/cases/bit_shifting.zig
Normal file
88
test/cases/bit_shifting.zig
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
|
fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type {
|
||||||
|
assert(Key == @IntType(false, Key.bit_count));
|
||||||
|
assert(Key.bit_count >= mask_bit_count);
|
||||||
|
const ShardKey = @IntType(false, mask_bit_count);
|
||||||
|
const shift_amount = Key.bit_count - ShardKey.bit_count;
|
||||||
|
return struct {
|
||||||
|
const Self = @This();
|
||||||
|
shards: [1 << ShardKey.bit_count]?*Node,
|
||||||
|
|
||||||
|
pub fn create() Self {
|
||||||
|
return Self{ .shards = []?*Node{null} ** (1 << ShardKey.bit_count) };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getShardKey(key: Key) ShardKey {
|
||||||
|
// https://github.com/ziglang/zig/issues/1544
|
||||||
|
// this special case is needed because you can't u32 >> 32.
|
||||||
|
if (ShardKey == u0) return 0;
|
||||||
|
|
||||||
|
// this can be u1 >> u0
|
||||||
|
const shard_key = key >> shift_amount;
|
||||||
|
|
||||||
|
// TODO: https://github.com/ziglang/zig/issues/1544
|
||||||
|
// This cast could be implicit if we teach the compiler that
|
||||||
|
// u32 >> 30 -> u2
|
||||||
|
return @intCast(ShardKey, shard_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn put(self: *Self, node: *Node) void {
|
||||||
|
const shard_key = Self.getShardKey(node.key);
|
||||||
|
node.next = self.shards[shard_key];
|
||||||
|
self.shards[shard_key] = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(self: *Self, key: Key) ?*Node {
|
||||||
|
const shard_key = Self.getShardKey(key);
|
||||||
|
var maybe_node = self.shards[shard_key];
|
||||||
|
while (maybe_node) |node| : (maybe_node = node.next) {
|
||||||
|
if (node.key == key) return node;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const Node = struct {
|
||||||
|
key: Key,
|
||||||
|
value: V,
|
||||||
|
next: ?*Node,
|
||||||
|
|
||||||
|
pub fn init(self: *Node, key: Key, value: V) void {
|
||||||
|
self.key = key;
|
||||||
|
self.value = value;
|
||||||
|
self.next = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
test "sharded table" {
|
||||||
|
// realistic 16-way sharding
|
||||||
|
testShardedTable(u32, 4, 8);
|
||||||
|
|
||||||
|
testShardedTable(u5, 0, 32); // ShardKey == u0
|
||||||
|
testShardedTable(u5, 2, 32);
|
||||||
|
testShardedTable(u5, 5, 32);
|
||||||
|
|
||||||
|
testShardedTable(u1, 0, 2);
|
||||||
|
testShardedTable(u1, 1, 2); // this does u1 >> u0
|
||||||
|
|
||||||
|
testShardedTable(u0, 0, 1);
|
||||||
|
}
|
||||||
|
fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime node_count: comptime_int) void {
|
||||||
|
const Table = ShardedTable(Key, mask_bit_count, void);
|
||||||
|
|
||||||
|
var table = Table.create();
|
||||||
|
var node_buffer: [node_count]Table.Node = undefined;
|
||||||
|
for (node_buffer) |*node, i| {
|
||||||
|
const key = @intCast(Key, i);
|
||||||
|
assert(table.get(key) == null);
|
||||||
|
node.init(key, {});
|
||||||
|
table.put(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (node_buffer) |*node, i| {
|
||||||
|
assert(table.get(@intCast(Key, i)) == node);
|
||||||
|
}
|
||||||
|
}
|
@ -16,3 +16,20 @@ fn conv(x: i32) u32 {
|
|||||||
fn conv2(x: u32) i32 {
|
fn conv2(x: u32) i32 {
|
||||||
return @bitCast(i32, x);
|
return @bitCast(i32, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "@bitCast extern enum to its integer type" {
|
||||||
|
const SOCK = extern enum {
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
|
||||||
|
fn testBitCastExternEnum() void {
|
||||||
|
var SOCK_DGRAM = @This().B;
|
||||||
|
var sock_dgram = @bitCast(c_int, SOCK_DGRAM);
|
||||||
|
assert(sock_dgram == 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SOCK.testBitCastExternEnum();
|
||||||
|
comptime SOCK.testBitCastExternEnum();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -682,3 +682,31 @@ test "refer to the type of a generic function" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn doNothingWithType(comptime T: type) void {}
|
fn doNothingWithType(comptime T: type) void {}
|
||||||
|
|
||||||
|
test "zero extend from u0 to u1" {
|
||||||
|
var zero_u0: u0 = 0;
|
||||||
|
var zero_u1: u1 = zero_u0;
|
||||||
|
assert(zero_u1 == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "bit shift a u1" {
|
||||||
|
var x: u1 = 1;
|
||||||
|
var y = x << 0;
|
||||||
|
assert(y == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "@intCast to a u0" {
|
||||||
|
var x: u8 = 0;
|
||||||
|
var y: u0 = @intCast(u0, x);
|
||||||
|
assert(y == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "@bytesToslice on a packed struct" {
|
||||||
|
const F = packed struct {
|
||||||
|
a: u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
var b = [1]u8{9};
|
||||||
|
var f = @bytesToSlice(F, b);
|
||||||
|
assert(f[0].a == 9);
|
||||||
|
}
|
||||||
|
@ -191,3 +191,17 @@ test "return inner function which references comptime variable of outer function
|
|||||||
var func = outer(10);
|
var func = outer(10);
|
||||||
assert(func(3) == 7);
|
assert(func(3) == 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "extern struct with stdcallcc fn pointer" {
|
||||||
|
const S = extern struct {
|
||||||
|
ptr: stdcallcc fn () i32,
|
||||||
|
|
||||||
|
stdcallcc fn foo() i32 {
|
||||||
|
return 1234;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var s: S = undefined;
|
||||||
|
s.ptr = S.foo;
|
||||||
|
assert(s.ptr() == 1234);
|
||||||
|
}
|
||||||
|
@ -437,3 +437,19 @@ test "call method with mutable reference to struct with no fields" {
|
|||||||
assert(S.do(&s));
|
assert(S.do(&s));
|
||||||
assert(s.do());
|
assert(s.do());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "implicit cast packed struct field to const ptr" {
|
||||||
|
const LevelUpMove = packed struct {
|
||||||
|
move_id: u9,
|
||||||
|
level: u7,
|
||||||
|
|
||||||
|
fn toInt(value: *const u7) u7 {
|
||||||
|
return value.*;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var lup: LevelUpMove = undefined;
|
||||||
|
lup.level = 12;
|
||||||
|
const res = LevelUpMove.toInt(lup.level);
|
||||||
|
assert(res == 12);
|
||||||
|
}
|
||||||
|
92
test/cli.zig
Normal file
92
test/cli.zig
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const os = std.os;
|
||||||
|
const assertOrPanic = std.debug.assertOrPanic;
|
||||||
|
|
||||||
|
var a: *std.mem.Allocator = undefined;
|
||||||
|
|
||||||
|
pub fn main() !void {
|
||||||
|
var direct_allocator = std.heap.DirectAllocator.init();
|
||||||
|
defer direct_allocator.deinit();
|
||||||
|
|
||||||
|
var arena = std.heap.ArenaAllocator.init(&direct_allocator.allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
|
||||||
|
var arg_it = os.args();
|
||||||
|
|
||||||
|
// skip my own exe name
|
||||||
|
_ = arg_it.skip();
|
||||||
|
|
||||||
|
a = &arena.allocator;
|
||||||
|
|
||||||
|
const zig_exe_rel = try (arg_it.next(a) orelse {
|
||||||
|
std.debug.warn("Expected first argument to be path to zig compiler\n");
|
||||||
|
return error.InvalidArgs;
|
||||||
|
});
|
||||||
|
const cache_root = try (arg_it.next(a) orelse {
|
||||||
|
std.debug.warn("Expected second argument to be cache root directory path\n");
|
||||||
|
return error.InvalidArgs;
|
||||||
|
});
|
||||||
|
const zig_exe = try os.path.resolve(a, zig_exe_rel);
|
||||||
|
|
||||||
|
try testZigInitLib(zig_exe, cache_root);
|
||||||
|
try testZigInitExe(zig_exe, cache_root);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unwrapArg(arg: UnwrapArgError![]u8) UnwrapArgError![]u8 {
|
||||||
|
return arg catch |err| {
|
||||||
|
warn("Unable to parse command line: {}\n", err);
|
||||||
|
return err;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn printCmd(cwd: []const u8, argv: []const []const u8) void {
|
||||||
|
std.debug.warn("cd {} && ", cwd);
|
||||||
|
for (argv) |arg| {
|
||||||
|
std.debug.warn("{} ", arg);
|
||||||
|
}
|
||||||
|
std.debug.warn("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exec(cwd: []const u8, argv: []const []const u8) !os.ChildProcess.ExecResult {
|
||||||
|
const max_output_size = 100 * 1024;
|
||||||
|
const result = os.ChildProcess.exec(a, argv, cwd, null, max_output_size) catch |err| {
|
||||||
|
std.debug.warn("The following command failed:\n");
|
||||||
|
printCmd(cwd, argv);
|
||||||
|
return err;
|
||||||
|
};
|
||||||
|
switch (result.term) {
|
||||||
|
os.ChildProcess.Term.Exited => |code| {
|
||||||
|
if (code != 0) {
|
||||||
|
std.debug.warn("The following command exited with error code {}:\n", code);
|
||||||
|
printCmd(cwd, argv);
|
||||||
|
std.debug.warn("stderr:\n{}\n", result.stderr);
|
||||||
|
return error.CommandFailed;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
std.debug.warn("The following command terminated unexpectedly:\n");
|
||||||
|
printCmd(cwd, argv);
|
||||||
|
std.debug.warn("stderr:\n{}\n", result.stderr);
|
||||||
|
return error.CommandFailed;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn testZigInitLib(zig_exe: []const u8, cache_root: []const u8) !void {
|
||||||
|
const dir_path = try os.path.join(a, cache_root, "clitest");
|
||||||
|
try os.deleteTree(a, dir_path);
|
||||||
|
try os.makeDir(dir_path);
|
||||||
|
_ = try exec(dir_path, [][]const u8{ zig_exe, "init-lib" });
|
||||||
|
const test_result = try exec(dir_path, [][]const u8{ zig_exe, "build", "test" });
|
||||||
|
assertOrPanic(std.mem.endsWith(u8, test_result.stderr, "All tests passed.\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn testZigInitExe(zig_exe: []const u8, cache_root: []const u8) !void {
|
||||||
|
const dir_path = try os.path.join(a, cache_root, "clitest");
|
||||||
|
try os.deleteTree(a, dir_path);
|
||||||
|
try os.makeDir(dir_path);
|
||||||
|
_ = try exec(dir_path, [][]const u8{ zig_exe, "init-exe" });
|
||||||
|
const run_result = try exec(dir_path, [][]const u8{ zig_exe, "build", "run" });
|
||||||
|
assertOrPanic(std.mem.eql(u8, run_result.stderr, "All your base are belong to us.\n"));
|
||||||
|
}
|
@ -1,6 +1,29 @@
|
|||||||
const tests = @import("tests.zig");
|
const tests = @import("tests.zig");
|
||||||
|
|
||||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||||
|
cases.add(
|
||||||
|
"@ptrCast a 0 bit type to a non- 0 bit type",
|
||||||
|
\\export fn entry() bool {
|
||||||
|
\\ var x: u0 = 0;
|
||||||
|
\\ const p = @ptrCast(?*u0, &x);
|
||||||
|
\\ return p == null;
|
||||||
|
\\}
|
||||||
|
,
|
||||||
|
".tmp_source.zig:3:15: error: '*u0' and '?*u0' do not have the same in-memory representation",
|
||||||
|
".tmp_source.zig:3:31: note: '*u0' has no in-memory bits",
|
||||||
|
".tmp_source.zig:3:24: note: '?*u0' has in-memory bits",
|
||||||
|
);
|
||||||
|
|
||||||
|
cases.add(
|
||||||
|
"comparing a non-optional pointer against null",
|
||||||
|
\\export fn entry() void {
|
||||||
|
\\ var x: i32 = 1;
|
||||||
|
\\ _ = &x == null;
|
||||||
|
\\}
|
||||||
|
,
|
||||||
|
".tmp_source.zig:3:12: error: comparison against null can only be done with optionals",
|
||||||
|
);
|
||||||
|
|
||||||
cases.add(
|
cases.add(
|
||||||
"non error sets used in merge error sets operator",
|
"non error sets used in merge error sets operator",
|
||||||
\\export fn foo() void {
|
\\export fn foo() void {
|
||||||
|
@ -249,6 +249,19 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
|
|||||||
\\}
|
\\}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
cases.addRuntimeSafety("value does not fit in shortening cast - u0",
|
||||||
|
\\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
|
||||||
|
\\ @import("std").os.exit(126);
|
||||||
|
\\}
|
||||||
|
\\pub fn main() !void {
|
||||||
|
\\ const x = shorten_cast(1);
|
||||||
|
\\ if (x == 0) return error.Whatever;
|
||||||
|
\\}
|
||||||
|
\\fn shorten_cast(x: u8) u0 {
|
||||||
|
\\ return @intCast(u0, x);
|
||||||
|
\\}
|
||||||
|
);
|
||||||
|
|
||||||
cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer",
|
cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer",
|
||||||
\\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
|
\\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
|
||||||
\\ @import("std").os.exit(126);
|
\\ @import("std").os.exit(126);
|
||||||
|
@ -103,6 +103,21 @@ pub fn addBuildExampleTests(b: *build.Builder, test_filter: ?[]const u8, modes:
|
|||||||
return cases.step;
|
return cases.step;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn addCliTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
|
||||||
|
const step = b.step("test-cli", "Test the command line interface");
|
||||||
|
|
||||||
|
const exe = b.addExecutable("test-cli", "test/cli.zig");
|
||||||
|
const run_cmd = b.addCommand(null, b.env_map, [][]const u8{
|
||||||
|
b.pathFromRoot(exe.getOutputPath()),
|
||||||
|
os.path.realAlloc(b.allocator, b.zig_exe) catch unreachable,
|
||||||
|
b.pathFromRoot(b.cache_root),
|
||||||
|
});
|
||||||
|
run_cmd.step.dependOn(&exe.step);
|
||||||
|
|
||||||
|
step.dependOn(&run_cmd.step);
|
||||||
|
return step;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
|
pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
|
||||||
const cases = b.allocator.create(CompareOutputContext{
|
const cases = b.allocator.create(CompareOutputContext{
|
||||||
.b = b,
|
.b = b,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user