first pass at zig build system

* `zig build --export [obj|lib|exe]` changed to `zig build_obj`,
   `zig build_lib` and `zig build_exe` respectively.
 * `--name` parameter is optional when it can be inferred from the
   root source filename. closes #207
 * `zig build` now looks for `build.zig` which interacts with
   `std.build.Builder` to describe the targets, and then the zig
   build system prints TODO: build these targets. See #204
 * add `@bitcast` which is mainly used for pointer reinterpret
   casting and make explicit casting not do pointer reinterpretation.
   Closes #290
 * fix debug info for byval parameters
 * sort command line help options
 * `std.debug.panic` supports format string printing
 * add `std.mem.IncrementingAllocator`
 * fix const ptr to a variable with data changing at runtime.
   closes #289
master
Andrew Kelley 2017-03-31 05:48:15 -04:00
parent 536c35136a
commit 3ca027ca82
27 changed files with 477 additions and 190 deletions

View File

@ -204,6 +204,7 @@ install(TARGETS zig DESTINATION bin)
install(FILES ${C_HEADERS} DESTINATION ${C_HEADERS_DEST})
install(FILES "${CMAKE_SOURCE_DIR}/std/build.zig" DESTINATION "${ZIG_STD_DEST}")
install(FILES "${CMAKE_SOURCE_DIR}/std/c/darwin.zig" DESTINATION "${ZIG_STD_DEST}/c")
install(FILES "${CMAKE_SOURCE_DIR}/std/c/index.zig" DESTINATION "${ZIG_STD_DEST}/c")
install(FILES "${CMAKE_SOURCE_DIR}/std/c/linux.zig" DESTINATION "${ZIG_STD_DEST}/c")
@ -234,6 +235,7 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}")
install(FILES "${CMAKE_SOURCE_DIR}/std/rand_test.zig" DESTINATION "${ZIG_STD_DEST}")
install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}")
install(FILES "${CMAKE_SOURCE_DIR}/std/special/bootstrap.zig" DESTINATION "${ZIG_STD_DEST}/special")
install(FILES "${CMAKE_SOURCE_DIR}/std/special/build_runner.zig" DESTINATION "${ZIG_STD_DEST}/special")
install(FILES "${CMAKE_SOURCE_DIR}/std/special/builtin.zig" DESTINATION "${ZIG_STD_DEST}/special")
install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt.zig" DESTINATION "${ZIG_STD_DEST}/special")
install(FILES "${CMAKE_SOURCE_DIR}/std/special/test_runner.zig" DESTINATION "${ZIG_STD_DEST}/special")

View File

@ -82,13 +82,12 @@ the Zig compiler itself:
* gcc >= 5.0.0 or clang >= 3.6.0
* cmake >= 2.8.5
#### Runtime Dependencies
#### Library Dependencies
These libraries must be installed on your system, with the development files
available. The Zig compiler dynamically links against them.
* LLVM == 4.x
* libclang == 4.x
* LLVM, Clang, and LLD libraries == 4.x
### Debug / Development Build

View File

@ -633,3 +633,10 @@ Invokes the panic handler function. By default the panic handler function
calls the public `panic` function exposed in the root source file, or
if there is not one specified, invokes the one provided in
`std/special/panic.zig`.
### @bitcast(comptime DestType: type, value: var) -> DestType
Transmutes memory from one type to another without changing any bits.
The source and destination types must have the same size. This function
can be used to, for example, reinterpret a pointer, or convert a `f32` to a
`u32`.

View File

@ -1196,6 +1196,7 @@ enum BuiltinFnId {
BuiltinFnIdSetGlobalSection,
BuiltinFnIdSetGlobalLinkage,
BuiltinFnIdPanic,
BuiltinFnIdBitCast,
};
struct BuiltinFnEntry {
@ -1719,7 +1720,7 @@ enum IrInstructionId {
IrInstructionIdFnProto,
IrInstructionIdTestComptime,
IrInstructionIdInitEnum,
IrInstructionIdPointerReinterpret,
IrInstructionIdBitCast,
IrInstructionIdWidenOrShorten,
IrInstructionIdIntToPtr,
IrInstructionIdPtrToInt,
@ -2369,10 +2370,11 @@ struct IrInstructionInitEnum {
LLVMValueRef tmp_ptr;
};
struct IrInstructionPointerReinterpret {
struct IrInstructionBitCast {
IrInstruction base;
IrInstruction *ptr;
IrInstruction *dest_type;
IrInstruction *target;
};
struct IrInstructionWidenOrShorten {

View File

@ -3355,7 +3355,6 @@ bool type_has_bits(TypeTableEntry *type_entry) {
bool type_requires_comptime(TypeTableEntry *type_entry) {
switch (get_underlying_type(type_entry)->id) {
case TypeTableEntryIdInvalid:
case TypeTableEntryIdUnreachable:
case TypeTableEntryIdVar:
case TypeTableEntryIdTypeDecl:
zig_unreachable();
@ -3383,6 +3382,7 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {
case TypeTableEntryIdPointer:
case TypeTableEntryIdEnumTag:
case TypeTableEntryIdVoid:
case TypeTableEntryIdUnreachable:
return false;
}
zig_unreachable();

View File

@ -47,7 +47,7 @@ static void init_darwin_native(CodeGen *g) {
}
}
static PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_path) {
PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_path) {
PackageTableEntry *entry = allocate<PackageTableEntry>(1);
entry->package_table.init(4);
buf_init_from_str(&entry->root_src_dir, root_src_dir);
@ -1345,12 +1345,12 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
zig_unreachable();
}
static LLVMValueRef ir_render_pointer_reinterpret(CodeGen *g, IrExecutable *executable,
IrInstructionPointerReinterpret *instruction)
static LLVMValueRef ir_render_bitcast(CodeGen *g, IrExecutable *executable,
IrInstructionBitCast *instruction)
{
TypeTableEntry *wanted_type = instruction->base.value.type;
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
return LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, "");
LLVMValueRef target = ir_llvm_value(g, instruction->target);
return LLVMBuildBitCast(g->builder, target, wanted_type->type_ref, "");
}
static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executable,
@ -2776,8 +2776,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_init_enum(g, executable, (IrInstructionInitEnum *)instruction);
case IrInstructionIdStructInit:
return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
case IrInstructionIdPointerReinterpret:
return ir_render_pointer_reinterpret(g, executable, (IrInstructionPointerReinterpret *)instruction);
case IrInstructionIdBitCast:
return ir_render_bitcast(g, executable, (IrInstructionBitCast *)instruction);
case IrInstructionIdWidenOrShorten:
return ir_render_widen_or_shorten(g, executable, (IrInstructionWidenOrShorten *)instruction);
case IrInstructionIdPtrToInt:
@ -3638,8 +3638,14 @@ static void do_code_gen(CodeGen *g) {
} else {
assert(var->gen_arg_index != SIZE_MAX);
TypeTableEntry *gen_type;
FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index];
if (handle_is_ptr(var->value->type)) {
gen_type = fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index].type;
if (gen_info->is_byval) {
gen_type = var->value->type;
} else {
gen_type = gen_info->type;
}
var->value_ref = LLVMGetParam(fn, var->gen_arg_index);
} else {
gen_type = var->value->type;
@ -4254,6 +4260,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2);
create_builtin_fn(g, BuiltinFnIdSetGlobalLinkage, "setGlobalLinkage", 2);
create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1);
create_builtin_fn(g, BuiltinFnIdBitCast, "bitcast", 2);
}
static void add_compile_var(CodeGen *g, const char *name, ConstExprValue *value) {

View File

@ -45,6 +45,7 @@ void codegen_set_mios_version_min(CodeGen *g, Buf *mios_version_min);
void codegen_set_linker_script(CodeGen *g, const char *linker_script);
void codegen_set_omit_zigrt(CodeGen *g, bool omit_zigrt);
PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_path);
void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code);
void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code);

View File

@ -480,8 +480,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionInitEnum *) {
return IrInstructionIdInitEnum;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionPointerReinterpret *) {
return IrInstructionIdPointerReinterpret;
static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {
return IrInstructionIdBitCast;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionWidenOrShorten *) {
@ -1940,14 +1940,16 @@ static IrInstruction *ir_build_init_enum_from(IrBuilder *irb, IrInstruction *old
return new_instruction;
}
static IrInstruction *ir_build_pointer_reinterpret(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *ptr)
static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *dest_type, IrInstruction *target)
{
IrInstructionPointerReinterpret *instruction = ir_build_instruction<IrInstructionPointerReinterpret>(
IrInstructionBitCast *instruction = ir_build_instruction<IrInstructionBitCast>(
irb, scope, source_node);
instruction->ptr = ptr;
instruction->dest_type = dest_type;
instruction->target = target;
ir_ref_instruction(ptr, irb->current_basic_block);
if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block);
ir_ref_instruction(target, irb->current_basic_block);
return &instruction->base;
}
@ -2664,11 +2666,12 @@ static IrInstruction *ir_instruction_initenum_get_dep(IrInstructionInitEnum *ins
}
}
static IrInstruction *ir_instruction_pointerreinterpret_get_dep(IrInstructionPointerReinterpret *instruction,
static IrInstruction *ir_instruction_bitcast_get_dep(IrInstructionBitCast *instruction,
size_t index)
{
switch (index) {
case 0: return instruction->ptr;
case 0: return instruction->dest_type;
case 1: return instruction->target;
default: return nullptr;
}
}
@ -2925,8 +2928,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
return ir_instruction_testcomptime_get_dep((IrInstructionTestComptime *) instruction, index);
case IrInstructionIdInitEnum:
return ir_instruction_initenum_get_dep((IrInstructionInitEnum *) instruction, index);
case IrInstructionIdPointerReinterpret:
return ir_instruction_pointerreinterpret_get_dep((IrInstructionPointerReinterpret *) instruction, index);
case IrInstructionIdBitCast:
return ir_instruction_bitcast_get_dep((IrInstructionBitCast *) instruction, index);
case IrInstructionIdWidenOrShorten:
return ir_instruction_widenorshorten_get_dep((IrInstructionWidenOrShorten *) instruction, index);
case IrInstructionIdIntToPtr:
@ -4197,6 +4200,20 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return ir_build_panic(irb, scope, node, arg0_value);
}
case BuiltinFnIdBitCast:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
if (arg0_value == irb->codegen->invalid_instruction)
return arg0_value;
AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
if (arg1_value == irb->codegen->invalid_instruction)
return arg1_value;
return ir_build_bit_cast(irb, scope, node, arg0_value, arg1_value);
}
}
zig_unreachable();
}
@ -6364,34 +6381,6 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc
return result;
}
static IrInstruction *ir_analyze_pointer_reinterpret(IrAnalyze *ira, IrInstruction *source_instr,
IrInstruction *ptr, TypeTableEntry *wanted_type)
{
if (ptr->value.type->id != TypeTableEntryIdPointer &&
ptr->value.type->id != TypeTableEntryIdMaybe)
{
ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&ptr->value.type->name)));
return ira->codegen->invalid_instruction;
}
if (instr_is_comptime(ptr)) {
ConstExprValue *val = ir_resolve_const(ira, ptr, UndefOk);
if (!val)
return ira->codegen->invalid_instruction;
IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
source_instr->scope, source_instr->source_node);
const_instruction->base.value = *val;
const_instruction->base.value.type = wanted_type;
return &const_instruction->base;
}
IrInstruction *result = ir_build_pointer_reinterpret(&ira->new_irb, source_instr->scope,
source_instr->source_node, ptr);
result->value.type = wanted_type;
return result;
}
static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction *source_instr,
IrInstruction *value, TypeTableEntry *wanted_type)
{
@ -6829,24 +6818,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
}
}
// explicit cast from pointer to another pointer
if ((actual_type->id == TypeTableEntryIdPointer || actual_type->id == TypeTableEntryIdFn) &&
(wanted_type->id == TypeTableEntryIdPointer || wanted_type->id == TypeTableEntryIdFn))
{
return ir_analyze_pointer_reinterpret(ira, source_instr, value, wanted_type);
}
// explicit cast from maybe pointer to another maybe pointer
if (actual_type->id == TypeTableEntryIdMaybe &&
(actual_type->data.maybe.child_type->id == TypeTableEntryIdPointer ||
actual_type->data.maybe.child_type->id == TypeTableEntryIdFn) &&
wanted_type->id == TypeTableEntryIdMaybe &&
(wanted_type->data.maybe.child_type->id == TypeTableEntryIdPointer ||
wanted_type->data.maybe.child_type->id == TypeTableEntryIdFn))
{
return ir_analyze_pointer_reinterpret(ira, source_instr, value, wanted_type);
}
// explicit cast from child type of maybe type to maybe type
if (wanted_type->id == TypeTableEntryIdMaybe) {
if (types_match_const_cast_only(wanted_type->data.maybe.child_type, actual_type)) {
@ -8986,6 +8957,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
ConstExprValue *array_ptr_val;
if (array_ptr->value.special != ConstValSpecialRuntime &&
array_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar &&
(array_ptr_val = const_ptr_pointee(&array_ptr->value)) &&
array_ptr_val->special != ConstValSpecialRuntime &&
(array_type->id != TypeTableEntryIdPointer ||
@ -12210,6 +12182,50 @@ static TypeTableEntry *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructio
return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
}
static TypeTableEntry *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
IrInstruction *dest_type_value = instruction->dest_type->other;
TypeTableEntry *dest_type = ir_resolve_type(ira, dest_type_value);
if (type_is_invalid(dest_type))
return ira->codegen->builtin_types.entry_invalid;
IrInstruction *target = instruction->target->other;
TypeTableEntry *src_type = target->value.type;
if (type_is_invalid(src_type))
return ira->codegen->builtin_types.entry_invalid;
ensure_complete_type(ira->codegen, dest_type);
ensure_complete_type(ira->codegen, src_type);
uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);
uint64_t src_size_bytes = type_size(ira->codegen, src_type);
if (dest_size_bytes != src_size_bytes) {
ir_add_error(ira, &instruction->base,
buf_sprintf("destination type '%s' has size %" PRIu64 " but source type '%s' has size %" PRIu64,
buf_ptr(&dest_type->name), dest_size_bytes,
buf_ptr(&src_type->name), src_size_bytes));
return ira->codegen->builtin_types.entry_invalid;
}
if (instr_is_comptime(target) && src_type->id == dest_type->id &&
(src_type->id == TypeTableEntryIdPointer || src_type->id == TypeTableEntryIdMaybe))
{
ConstExprValue *val = ir_resolve_const(ira, target, UndefOk);
if (!val)
return ira->codegen->builtin_types.entry_invalid;
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
*out_val = *val;
out_val->type = dest_type;
return dest_type;
}
IrInstruction *result = ir_build_bit_cast(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, nullptr, target);
ir_link_new_instruction(result, &instruction->base);
result->value.type = dest_type;
return dest_type;
}
static TypeTableEntry *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
IrInstructionDeclRef *instruction)
{
@ -12283,7 +12299,6 @@ static TypeTableEntry *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
switch (instruction->id) {
case IrInstructionIdInvalid:
case IrInstructionIdPointerReinterpret:
case IrInstructionIdWidenOrShorten:
case IrInstructionIdIntToPtr:
case IrInstructionIdPtrToInt:
@ -12449,6 +12464,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction);
case IrInstructionIdPanic:
return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);
case IrInstructionIdBitCast:
return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction);
case IrInstructionIdMaybeWrap:
case IrInstructionIdErrWrapCode:
case IrInstructionIdErrWrapPayload:
@ -12620,7 +12637,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdFnProto:
case IrInstructionIdTestComptime:
case IrInstructionIdInitEnum:
case IrInstructionIdPointerReinterpret:
case IrInstructionIdBitCast:
case IrInstructionIdWidenOrShorten:
case IrInstructionIdPtrToInt:
case IrInstructionIdIntToPtr:

View File

@ -765,9 +765,9 @@ static void ir_print_init_enum(IrPrint *irp, IrInstructionInitEnum *instruction)
fprintf(irp->f, "}");
}
static void ir_print_pointer_reinterpret(IrPrint *irp, IrInstructionPointerReinterpret *instruction) {
fprintf(irp->f, "@pointerReinterpret(");
ir_print_other_instruction(irp, instruction->ptr);
static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
fprintf(irp->f, "@bitcast(");
ir_print_other_instruction(irp, instruction->target);
fprintf(irp->f, ")");
}
@ -1098,8 +1098,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdInitEnum:
ir_print_init_enum(irp, (IrInstructionInitEnum *)instruction);
break;
case IrInstructionIdPointerReinterpret:
ir_print_pointer_reinterpret(irp, (IrInstructionPointerReinterpret *)instruction);
case IrInstructionIdBitCast:
ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);
break;
case IrInstructionIdWidenOrShorten:
ir_print_widen_or_shorten(irp, (IrInstructionWidenOrShorten *)instruction);

View File

@ -19,46 +19,48 @@
static int usage(const char *arg0) {
fprintf(stderr, "Usage: %s [command] [options]\n"
"Commands:\n"
" build [sources] create executable, object, or library from source\n"
" test [sources] create and run a test build\n"
" build build project from build.zig\n"
" build_exe [source] create executable from source\n"
" build_lib [source] create library from source\n"
" build_obj [source] create object from source\n"
" parseh [source] convert a c header file to zig extern declarations\n"
" version print version number and exit\n"
" targets list available compilation targets\n"
" test [source] create and run a test build\n"
" version print version number and exit\n"
"Options:\n"
" --ar-path [path] set the path to ar\n"
" --color [auto|off|on] enable or disable colored error messages\n"
" --dynamic-linker [path] set the path to ld.so\n"
" --each-lib-rpath add rpath for each used dynamic library\n"
" --ld-path [path] set the path to the linker\n"
" --libc-include-dir [path] directory where libc stdlib.h resides\n"
" --libc-lib-dir [path] directory where libc crt1.o resides\n"
" --libc-static-lib-dir [path] directory where libc crtbegin.o resides\n"
" --library [lib] link against lib\n"
" --library-path [dir] add a directory to the library search path\n"
" --linker-script [path] use a custom linker script\n"
" --name [name] override output name\n"
" --output [file] override destination path\n"
" --release build with optimizations on and debug protection off\n"
" --static output will be statically linked\n"
" --strip exclude debug symbols\n"
" --export [exe|lib|obj] override output type\n"
" --name [name] override output name\n"
" --output [file] override destination path\n"
" --verbose turn on compiler debug output\n"
" --color [auto|off|on] enable or disable colored error messages\n"
" --libc-lib-dir [path] directory where libc crt1.o resides\n"
" --libc-static-lib-dir [path] directory where libc crtbegin.o resides\n"
" --libc-include-dir [path] directory where libc stdlib.h resides\n"
" --zig-std-dir [path] directory where zig standard library resides\n"
" --dynamic-linker [path] set the path to ld.so\n"
" --ld-path [path] set the path to the linker\n"
" --ar-path [path] set the path to ar\n"
" -isystem [dir] add additional search path for other .h files\n"
" -dirafter [dir] same as -isystem but do it last\n"
" --library-path [dir] add a directory to the library search path\n"
" -L[dir] alias for --library-path\n"
" --library [lib] link against lib\n"
" --target-arch [name] specify target architecture\n"
" --target-os [name] specify target operating system\n"
" --target-environ [name] specify target environment\n"
" -mwindows (windows only) --subsystem windows to the linker\n"
" -mconsole (windows only) --subsystem console to the linker\n"
" -municode (windows only) link with unicode\n"
" -mlinker-version [ver] (darwin only) override linker version\n"
" -rdynamic add all symbols to the dynamic symbol table\n"
" -mmacosx-version-min [ver] (darwin only) set Mac OS X deployment target\n"
" -mios-version-min [ver] (darwin only) set iOS deployment target\n"
" --target-os [name] specify target operating system\n"
" --verbose turn on compiler debug output\n"
" --zig-std-dir [path] directory where zig standard library resides\n"
" -L[dir] alias for --library-path\n"
" -dirafter [dir] same as -isystem but do it last\n"
" -framework [name] (darwin only) link against framework\n"
" --linker-script [path] use a custom linker script\n"
" -isystem [dir] add additional search path for other .h files\n"
" -mconsole (windows only) --subsystem console to the linker\n"
" -mios-version-min [ver] (darwin only) set iOS deployment target\n"
" -mlinker-version [ver] (darwin only) override linker version\n"
" -mmacosx-version-min [ver] (darwin only) set Mac OS X deployment target\n"
" -municode (windows only) link with unicode\n"
" -mwindows (windows only) --subsystem windows to the linker\n"
" -rdynamic add all symbols to the dynamic symbol table\n"
" -rpath [path] add directory to the runtime library search path\n"
" --each-lib-rpath add rpath for each used dynamic library\n"
, arg0);
return EXIT_FAILURE;
}
@ -144,6 +146,62 @@ int main(int argc, char **argv) {
ZigList<const char *> rpath_list = {0};
bool each_lib_rpath = false;
if (argc >= 2 && strcmp(argv[1], "build") == 0) {
const char *zig_exe_path = arg0;
init_all_targets();
Buf *zig_std_dir = buf_create_from_str(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();
os_path_join(special_dir, buf_create_from_str("build_runner.zig"), build_runner_path);
ZigList<const char *> args = {0};
args.append(zig_exe_path);
for (int i = 2; i < argc; i += 1) {
if (strcmp(argv[i], "--verbose") == 0) {
verbose = true;
args.append(argv[i]);
} else {
args.append(argv[i]);
}
}
Buf root_source_dir = BUF_INIT;
Buf root_source_code = BUF_INIT;
Buf root_source_name = BUF_INIT;
os_path_split(build_runner_path, &root_source_dir, &root_source_name);
if ((err = os_fetch_file_path(build_runner_path, &root_source_code))) {
fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(build_runner_path), err_str(err));
return 1;
}
CodeGen *g = codegen_create(&root_source_dir, nullptr);
codegen_set_out_name(g, buf_create_from_str("build"));
codegen_set_out_type(g, OutTypeExe);
codegen_set_verbose(g, verbose);
PackageTableEntry *build_pkg = new_package(".", "build.zig");
build_pkg->package_table.put(buf_create_from_str("std"), g->std_package);
g->root_package->package_table.put(buf_create_from_str("@build"), build_pkg);
codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code);
codegen_link(g, "build");
Termination term;
os_spawn_process("./build", args, &term);
if (term.how != TerminationIdClean || term.code != 0) {
fprintf(stderr, "\nBuild failed. Use the following command to reproduce the failure:\n");
fprintf(stderr, "./build");
for (size_t i = 0; i < args.length; i += 1) {
fprintf(stderr, " \"%s\"", args.at(i));
}
fprintf(stderr, "\n");
}
return (term.how == TerminationIdClean) ? term.code : -1;
}
for (int i = 1; i < argc; i += 1) {
char *arg = argv[i];
@ -177,16 +235,6 @@ int main(int argc, char **argv) {
return usage(arg0);
} else if (strcmp(arg, "--output") == 0) {
out_file = argv[i];
} else if (strcmp(arg, "--export") == 0) {
if (strcmp(argv[i], "exe") == 0) {
out_type = OutTypeExe;
} else if (strcmp(argv[i], "lib") == 0) {
out_type = OutTypeLib;
} else if (strcmp(argv[i], "obj") == 0) {
out_type = OutTypeObj;
} else {
return usage(arg0);
}
} else if (strcmp(arg, "--color") == 0) {
if (strcmp(argv[i], "auto") == 0) {
color = ErrColorAuto;
@ -243,8 +291,15 @@ int main(int argc, char **argv) {
}
}
} else if (cmd == CmdInvalid) {
if (strcmp(arg, "build") == 0) {
if (strcmp(arg, "build_exe") == 0) {
cmd = CmdBuild;
out_type = OutTypeExe;
} else if (strcmp(arg, "build_obj") == 0) {
cmd = CmdBuild;
out_type = OutTypeObj;
} else if (strcmp(arg, "build_lib") == 0) {
cmd = CmdBuild;
out_type = OutTypeLib;
} else if (strcmp(arg, "version") == 0) {
cmd = CmdVersion;
} else if (strcmp(arg, "parseh") == 0) {
@ -285,15 +340,7 @@ int main(int argc, char **argv) {
if (!in_file)
return usage(arg0);
if (cmd == CmdBuild && !out_name) {
fprintf(stderr, "--name [name] not provided\n\n");
return usage(arg0);
}
if (cmd == CmdBuild && out_type == OutTypeUnknown) {
fprintf(stderr, "--export [exe|lib|obj] not provided\n\n");
return usage(arg0);
}
assert(cmd != CmdBuild || out_type != OutTypeUnknown);
init_all_targets();
@ -331,6 +378,9 @@ int main(int argc, char **argv) {
Buf root_source_dir = BUF_INIT;
Buf root_source_code = BUF_INIT;
Buf root_source_name = BUF_INIT;
Buf *buf_out_name = (cmd == CmdTest) ? buf_create_from_str("test") :
(out_name == nullptr) ? nullptr : buf_create_from_str(out_name);
if (buf_eql_str(&in_file_buf, "-")) {
os_get_cwd(&root_source_dir);
if ((err = os_fetch_file(stdin, &root_source_code))) {
@ -338,12 +388,24 @@ int main(int argc, char **argv) {
return 1;
}
buf_init_from_str(&root_source_name, "");
} else {
os_path_split(&in_file_buf, &root_source_dir, &root_source_name);
if ((err = os_fetch_file_path(buf_create_from_str(in_file), &root_source_code))) {
fprintf(stderr, "unable to open '%s': %s\n", in_file, err_str(err));
return 1;
}
if (cmd == CmdBuild && buf_out_name == nullptr) {
buf_out_name = buf_alloc();
Buf ext_name = BUF_INIT;
os_path_extname(&root_source_name, buf_out_name, &ext_name);
}
}
if (cmd == CmdBuild && buf_out_name == nullptr) {
fprintf(stderr, "--name [name] not provided and unable to infer\n\n");
return usage(arg0);
}
CodeGen *g = codegen_create(&root_source_dir, target);
@ -361,11 +423,7 @@ int main(int argc, char **argv) {
} else if (cmd == CmdTest) {
codegen_set_out_type(g, OutTypeExe);
}
if (out_name) {
codegen_set_out_name(g, buf_create_from_str(out_name));
} else if (cmd == CmdTest) {
codegen_set_out_name(g, buf_create_from_str("test"));
}
codegen_set_out_name(g, buf_out_name);
if (libc_lib_dir)
codegen_set_libc_lib_dir(g, buf_create_from_str(libc_lib_dir));
if (libc_static_lib_dir)

View File

@ -139,6 +139,32 @@ void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename) {
if (out_basename) buf_init_from_buf(out_basename, full_path);
}
void os_path_extname(Buf *full_path, Buf *out_basename, Buf *out_extname) {
if (buf_len(full_path) == 0) {
buf_init_from_str(out_basename, "");
buf_init_from_str(out_extname, "");
return;
}
size_t i = buf_len(full_path) - 1;
while (true) {
if (buf_ptr(full_path)[i] == '.') {
buf_resize(out_basename, 0);
buf_append_mem(out_basename, buf_ptr(full_path), i);
buf_resize(out_extname, 0);
buf_append_mem(out_extname, buf_ptr(full_path) + i, buf_len(full_path) - i);
return;
}
if (i == 0) {
buf_init_from_buf(out_basename, full_path);
buf_init_from_str(out_extname, "");
return;
}
i -= 1;
}
}
void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) {
buf_init_from_buf(out_full_path, dirname);
uint8_t c = *(buf_ptr(out_full_path) + buf_len(out_full_path) - 1);

View File

@ -34,6 +34,7 @@ int os_exec_process(const char *exe, ZigList<const char *> &args,
void os_path_dirname(Buf *full_path, Buf *out_dirname);
void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename);
void os_path_extname(Buf *full_path, Buf *out_basename, Buf *out_extname);
void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path);
int os_path_real(Buf *rel_path, Buf *out_abs_path);
void os_path_resolve(Buf *ref_path, Buf *target_path, Buf *out_abs_path);

59
std/build.zig Normal file
View File

@ -0,0 +1,59 @@
const io = @import("io.zig");
const mem = @import("mem.zig");
const debug = @import("debug.zig");
const List = @import("list.zig").List;
const Allocator = @import("mem.zig").Allocator;
error ExtraArg;
pub const Builder = struct {
zig_exe: []const u8,
allocator: &Allocator,
exe_list: List(&Exe),
pub fn init(zig_exe: []const u8, allocator: &Allocator) -> Builder {
Builder {
.zig_exe = zig_exe,
.allocator = allocator,
.exe_list = List(&Exe).init(allocator),
}
}
pub fn addExe(self: &Builder, root_src: []const u8, name: []const u8) -> &Exe {
return self.addExeErr(root_src, name) %% |err| handleErr(err);
}
pub fn addExeErr(self: &Builder, root_src: []const u8, name: []const u8) -> %&Exe {
const exe = %return self.allocator.create(Exe);
*exe = Exe {
.root_src = root_src,
.name = name,
};
%return self.exe_list.append(exe);
return exe;
}
pub fn make(self: &Builder, args: []const []const u8) -> %void {
var verbose = false;
for (args) |arg| {
if (mem.eql(u8, arg, "--verbose")) {
verbose = true;
} else {
%%io.stderr.printf("Unrecognized argument: '{}'\n", arg);
return error.ExtraArg;
}
}
for (self.exe_list.toSlice()) |exe| {
%%io.stderr.printf("TODO: invoke this command:\nzig build_exe {} --name {}\n", exe.root_src, exe.name);
}
}
};
const Exe = struct {
root_src: []const u8,
name: []const u8,
};
fn handleErr(err: error) -> noreturn {
debug.panic("error: {}\n", @errorName(err));
}

View File

@ -15,7 +15,7 @@ pub fn assert(ok: bool) {
var panicking = false;
/// This is the default panic implementation.
pub coldcc fn panic(message: []const u8) -> noreturn {
pub coldcc fn panic(comptime format: []const u8, args: ...) -> noreturn {
// TODO
// if (@atomicRmw(AtomicOp.XChg, &panicking, true, AtomicOrder.SeqCst)) { }
if (panicking) {
@ -28,7 +28,7 @@ pub coldcc fn panic(message: []const u8) -> noreturn {
panicking = true;
}
%%io.stderr.printf("{}\n", message);
%%io.stderr.printf(format, args);
%%printStackTrace();
os.abort();
@ -74,7 +74,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream) -> %void {
const name = %return compile_unit.die.getAttrString(st, DW.AT_name);
%return out_stream.printf("{} -> {}\n", return_address, name);
maybe_fp = *(&const ?&const u8)(fp);
maybe_fp = *@bitcast(&const ?&const u8, fp);
}
},
ObjectFormat.coff => {
@ -511,7 +511,6 @@ pub var global_allocator = mem.Allocator {
.allocFn = globalAlloc,
.reallocFn = globalRealloc,
.freeFn = globalFree,
.context = null,
};
var some_mem: [100 * 1024]u8 = undefined;

View File

@ -236,7 +236,7 @@ test "basicHashMapTest" {
}
fn hash_i32(x: i32) -> u32 {
*(&u32)(&x)
*@bitcast(&u32, &x)
}
fn eql_i32(a: i32, b: i32) -> bool {
a == b

View File

@ -1,3 +1,4 @@
pub const build = @import("build.zig");
pub const c = @import("c/index.zig");
pub const cstr = @import("cstr.zig");
pub const debug = @import("debug.zig");

View File

@ -7,12 +7,10 @@ pub const Cmp = math.Cmp;
error NoMem;
pub type Context = u8;
pub const Allocator = struct {
allocFn: fn (self: &Allocator, n: usize) -> %[]u8,
reallocFn: fn (self: &Allocator, old_mem: []u8, new_size: usize) -> %[]u8,
freeFn: fn (self: &Allocator, mem: []u8),
context: ?&Context,
/// Aborts the program if an allocation fails.
fn checkedAlloc(self: &Allocator, comptime T: type, n: usize) -> []T {
@ -22,6 +20,14 @@ pub const Allocator = struct {
}
}
fn create(self: &Allocator, comptime T: type) -> %&T {
&(%return self.alloc(T, 1))[0]
}
fn destroy(self: &Allocator, ptr: var) {
self.free(ptr[0...1]);
}
fn alloc(self: &Allocator, comptime T: type, n: usize) -> %[]T {
const byte_count = %return math.mulOverflow(usize, @sizeOf(T), n);
([]T)(%return self.allocFn(self, byte_count))
@ -37,6 +43,62 @@ pub const Allocator = struct {
}
};
pub const IncrementingAllocator = struct {
allocator: Allocator,
bytes: []u8,
end_index: usize,
fn init(capacity: usize) -> %IncrementingAllocator {
switch (@compileVar("os")) {
Os.linux, Os.darwin, Os.macosx, Os.ios => {
const p = os.posix;
const addr = p.mmap(null, capacity, p.PROT_READ|p.PROT_WRITE,
p.MAP_PRIVATE|p.MAP_ANONYMOUS|p.MAP_NORESERVE, -1, 0);
if (addr == p.MAP_FAILED) {
return error.NoMem;
}
return IncrementingAllocator {
.allocator = Allocator {
.allocFn = alloc,
.reallocFn = realloc,
.freeFn = free,
},
.bytes = (&u8)(addr)[0...capacity],
.end_index = 0,
};
},
else => @compileError("Unsupported OS"),
}
}
fn deinit(self: &IncrementingAllocator) {
_ = os.posix.munmap(self.bytes.ptr, self.bytes.len);
}
fn alloc(allocator: &Allocator, n: usize) -> %[]u8 {
// TODO
//const self = @fieldParentPtr(IncrementingAllocator, "allocator", allocator);
const self = @bitcast(&IncrementingAllocator, allocator);
const new_end_index = self.end_index + n;
if (new_end_index > self.bytes.len) {
return error.NoMem;
}
const result = self.bytes[self.end_index...new_end_index];
self.end_index = new_end_index;
return result;
}
fn realloc(allocator: &Allocator, old_mem: []u8, new_size: usize) -> %[]u8 {
const result = %return alloc(allocator, new_size);
copy(u8, result, old_mem);
return result;
}
fn free(allocator: &Allocator, bytes: []u8) {
// Do nothing. That's the point of an incrementing allocator.
}
};
/// Copy all of source into dest at position 0.
/// dest.len must be >= source.len.
pub fn copy(comptime T: type, dest: []T, source: []const T) {

View File

@ -5,16 +5,29 @@ const arch = switch (@compileVar("arch")) {
};
const errno = @import("errno.zig");
pub const MMAP_PROT_NONE = 0;
pub const MMAP_PROT_READ = 1;
pub const MMAP_PROT_WRITE = 2;
pub const MMAP_PROT_EXEC = 4;
pub const PROT_NONE = 0;
pub const PROT_READ = 1;
pub const PROT_WRITE = 2;
pub const PROT_EXEC = 4;
pub const PROT_GROWSDOWN = 0x01000000;
pub const PROT_GROWSUP = 0x02000000;
pub const MMAP_MAP_FILE = 0;
pub const MMAP_MAP_SHARED = 1;
pub const MMAP_MAP_PRIVATE = 2;
pub const MMAP_MAP_FIXED = 16;
pub const MMAP_MAP_ANON = 32;
pub const MAP_FAILED = @maxValue(usize);
pub const MAP_SHARED = 0x01;
pub const MAP_PRIVATE = 0x02;
pub const MAP_TYPE = 0x0f;
pub const MAP_FIXED = 0x10;
pub const MAP_ANONYMOUS = 0x20;
pub const MAP_NORESERVE = 0x4000;
pub const MAP_GROWSDOWN = 0x0100;
pub const MAP_DENYWRITE = 0x0800;
pub const MAP_EXECUTABLE = 0x1000;
pub const MAP_LOCKED = 0x2000;
pub const MAP_POPULATE = 0x8000;
pub const MAP_NONBLOCK = 0x10000;
pub const MAP_STACK = 0x20000;
pub const MAP_HUGETLB = 0x40000;
pub const MAP_FILE = 0;
pub const SIGHUP = 1;
pub const SIGINT = 2;
@ -226,7 +239,7 @@ pub const AF_MAX = PF_MAX;
/// Get the errno from a syscall return value, or 0 for no error.
pub fn getErrno(r: usize) -> usize {
const signed_r = *(&isize)(&r);
const signed_r = *@bitcast(&isize, &r);
if (signed_r > -4096 and signed_r < 0) usize(-signed_r) else 0
}

View File

@ -0,0 +1,18 @@
const root = @import("@build");
const std = @import("std");
const io = std.io;
const Builder = std.build.Builder;
const mem = std.mem;
pub fn main(args: [][]u8) -> %void {
const zig_exe = args[1];
const leftover_args = args[2...];
// TODO use a more general purpose allocator here
var inc_allocator = %%mem.IncrementingAllocator.init(10 * 1024 * 1024);
defer inc_allocator.deinit();
var builder = Builder.init(zig_exe, &inc_allocator.allocator);
root.build(&builder);
%return builder.make(leftover_args);
}

View File

@ -15,7 +15,7 @@ export fn __udivdi3(a: du_int, b: du_int) -> du_int {
fn du_int_to_udwords(x: du_int) -> udwords {
@setDebugSafety(this, false);
return *(&udwords)(&x);
return *@bitcast(&udwords, &x);
}
export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
@ -66,7 +66,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
if (var rem ?= maybe_rem) {
r[high] = n[high] % d[high];
r[low] = 0;
*rem = *(&du_int)(&r[0]);
*rem = *@bitcast(&du_int, &r[0]);
}
return n[high] / d[high];
}
@ -78,7 +78,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
if (var rem ?= maybe_rem) {
r[low] = n[low];
r[high] = n[high] & (d[high] - 1);
*rem = *(&du_int)(&r[0]);
*rem = *@bitcast(&du_int, &r[0]);
}
return n[high] >> @ctz(d[high]);
}
@ -89,7 +89,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
// 0 <= sr <= n_uword_bits - 2 or sr large
if (sr > n_uword_bits - 2) {
if (var rem ?= maybe_rem) {
*rem = *(&du_int)(&n[0]);
*rem = *@bitcast(&du_int, &n[0]);
}
return 0;
}
@ -113,12 +113,12 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
*rem = n[low] & (d[low] - 1);
}
if (d[low] == 1) {
return *(&du_int)(&n[0]);
return *@bitcast(&du_int, &n[0]);
}
sr = @ctz(d[low]);
q[high] = n[high] >> sr;
q[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr);
return *(&du_int)(&q[0]);
return *@bitcast(&du_int, &q[0]);
}
// K X
// ---
@ -154,7 +154,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
// 0 <= sr <= n_uword_bits - 1 or sr large
if (sr > n_uword_bits - 1) {
if (var rem ?= maybe_rem) {
*rem = *(&du_int)(&n[0]);
*rem = *@bitcast(&du_int, &n[0]);
}
return 0;
}
@ -191,17 +191,17 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
// r.all -= d.all;
// carry = 1;
// }
const s: di_int = (di_int)(*(&du_int)(&d[0]) - *(&du_int)(&r[0]) - 1) >> (n_udword_bits - 1);
const s: di_int = (di_int)(*@bitcast(&du_int, &d[0]) - *@bitcast(&du_int, &r[0]) - 1) >> (n_udword_bits - 1);
carry = su_int(s & 1);
*(&du_int)(&r[0]) -= *(&du_int)(&d[0]) & u64(s);
*@bitcast(&du_int, &r[0]) -= *@bitcast(&du_int, &d[0]) & u64(s);
sr -= 1;
}
*(&du_int)(&q[0]) = (*(&du_int)(&q[0]) << 1) | u64(carry);
*@bitcast(&du_int, &q[0]) = (*@bitcast(&du_int, &q[0]) << 1) | u64(carry);
if (var rem ?= maybe_rem) {
*rem = *(&du_int)(&r[0]);
*rem = *@bitcast(&du_int, &r[0]);
}
return *(&du_int)(&q[0]);
return *@bitcast(&du_int, &q[0]);
}
export fn __umoddi3(a: du_int, b: du_int) -> du_int {

View File

@ -1,5 +1,5 @@
// This file contains functions that zig depends on to coordinate between
// multiple .o files. The symbols are defined LinkOnce so that multiple
// multiple .o files. The symbols are defined Weak so that multiple
// instances of zig_rt.zig do not conflict with each other.
export coldcc fn __zig_panic(message_ptr: &const u8, message_len: usize) -> noreturn {
@ -11,6 +11,6 @@ export coldcc fn __zig_panic(message_ptr: &const u8, message_len: usize) -> nore
} else if (@compileVar("os") == Os.freestanding) {
while (true) {}
} else {
@import("std").debug.panic(message_ptr[0...message_len]);
@import("std").debug.panic("{}\n", message_ptr[0...message_len]);
}
}

View File

@ -15,7 +15,18 @@ test "numLitIntToPtrCast" {
test "pointerReinterpretConstFloatToInt" {
const float: f64 = 5.99999999999994648725e-01;
const float_ptr = &float;
const int_ptr = (&i32)(float_ptr);
const int_ptr = @bitcast(&i32, float_ptr);
const int_val = *int_ptr;
assert(int_val == 858993411);
}
test "implicitly cast a pointer to a const pointer of it" {
var x: i32 = 1;
const xp = &x;
funcWithConstPtrPtr(xp);
assert(x == 2);
}
fn funcWithConstPtrPtr(x: &const &i32) {
**x += 1;
}

View File

@ -284,3 +284,18 @@ fn testCompTimeUIntComparisons(x: u32) {
@compileError("this condition should be comptime known");
}
}
test "const ptr to variable data changes at runtime" {
assert(foo_ref.name[0] == 'a');
foo_ref.name = "b";
assert(foo_ref.name[0] == 'b');
}
const Foo = struct {
name: []const u8,
};
var foo_contents = Foo { .name = "a", };
const foo_ref = &foo_contents;

View File

@ -121,5 +121,5 @@ test "genericFnWithImplicitCast" {
}
fn getByte(ptr: ?&const u8) -> u8 {*??ptr}
fn getFirstByte(comptime T: type, mem: []const T) -> u8 {
getByte((&const u8)(&mem[0]))
getByte(@bitcast(&const u8, &mem[0]))
}

View File

@ -246,15 +246,15 @@ test "typeEquality" {
const global_a: i32 = 1234;
const global_b: &const i32 = &global_a;
const global_c: &const f32 = (&const f32)(global_b);
const global_c: &const f32 = @bitcast(&const f32, global_b);
test "compileTimeGlobalReinterpret" {
const d = (&const i32)(global_c);
const d = @bitcast(&const i32, global_c);
assert(*d == 1234);
}
test "explicitCastMaybePointers" {
const a: ?&i32 = undefined;
const b: ?&f32 = (?&f32)(a);
const b: ?&f32 = @bitcast(?&f32, a);
}
test "genericMallocFree" {
@ -263,7 +263,7 @@ test "genericMallocFree" {
}
const some_mem : [100]u8 = undefined;
fn memAlloc(comptime T: type, n: usize) -> %[]T {
return (&T)(&some_mem[0])[0...n];
return @bitcast(&T, &some_mem[0])[0...n];
}
fn memFree(comptime T: type, memory: []T) { }

View File

@ -41,7 +41,7 @@ const VoidStructFieldsFoo = struct {
test "fn" {
var foo: StructFoo = undefined;
@memset((&u8)(&foo), 0, @sizeOf(StructFoo));
@memset(@bitcast(&u8, &foo), 0, @sizeOf(StructFoo));
foo.a += 1;
foo.b = foo.a == 1;
testFoo(foo);

View File

@ -73,10 +73,8 @@ static TestCase *add_simple_case(const char *case_name, const char *source, cons
test_case->source_files.at(0).relative_path = tmp_source_path;
test_case->source_files.at(0).source_code = source;
test_case->compiler_args.append("build");
test_case->compiler_args.append("build_exe");
test_case->compiler_args.append(tmp_source_path);
test_case->compiler_args.append("--export");
test_case->compiler_args.append("exe");
test_case->compiler_args.append("--name");
test_case->compiler_args.append("test");
test_case->compiler_args.append("--output");
@ -113,15 +111,12 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source
test_case->compile_errors.append(arg);
}
test_case->compiler_args.append("build");
test_case->compiler_args.append("build_obj");
test_case->compiler_args.append(tmp_source_path);
test_case->compiler_args.append("--name");
test_case->compiler_args.append("test");
test_case->compiler_args.append("--export");
test_case->compiler_args.append("obj");
test_case->compiler_args.append("--output");
test_case->compiler_args.append(tmp_exe_path);
@ -142,15 +137,12 @@ static void add_debug_safety_case(const char *case_name, const char *source) {
test_case->source_files.at(0).relative_path = tmp_source_path;
test_case->source_files.at(0).source_code = source;
test_case->compiler_args.append("build");
test_case->compiler_args.append("build_exe");
test_case->compiler_args.append(tmp_source_path);
test_case->compiler_args.append("--name");
test_case->compiler_args.append("test");
test_case->compiler_args.append("--export");
test_case->compiler_args.append("exe");
test_case->compiler_args.append("--output");
test_case->compiler_args.append(tmp_exe_path);
@ -164,15 +156,12 @@ static void add_debug_safety_case(const char *case_name, const char *source) {
test_case->source_files.at(0).source_code = source;
test_case->output = "";
test_case->compiler_args.append("build");
test_case->compiler_args.append("build_exe");
test_case->compiler_args.append(tmp_source_path);
test_case->compiler_args.append("--name");
test_case->compiler_args.append("test");
test_case->compiler_args.append("--export");
test_case->compiler_args.append("exe");
test_case->compiler_args.append("--output");
test_case->compiler_args.append(tmp_exe_path);
@ -471,8 +460,8 @@ const foo : i32 = 0;
const c = @cImport(@cInclude("stdlib.h"));
export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int {
const a_int = (&i32)(a ?? unreachable);
const b_int = (&i32)(b ?? unreachable);
const a_int = @bitcast(&i32, a ?? unreachable);
const b_int = @bitcast(&i32, b ?? unreachable);
if (*a_int < *b_int) {
-1
} else if (*a_int > *b_int) {
@ -485,7 +474,7 @@ export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int {
export fn main(args: c_int, argv: &&u8) -> c_int {
var array = []u32 { 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 };
c.qsort((&c_void)(&array[0]), c_ulong(array.len), @sizeOf(i32), compare_fn);
c.qsort(@bitcast(&c_void, &array[0]), c_ulong(array.len), @sizeOf(i32), compare_fn);
for (array) |item, i| {
if (item != i) {