mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
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
This commit is contained in:
parent
536c35136a
commit
3ca027ca82
@ -204,6 +204,7 @@ install(TARGETS zig DESTINATION bin)
|
|||||||
|
|
||||||
install(FILES ${C_HEADERS} DESTINATION ${C_HEADERS_DEST})
|
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/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/index.zig" DESTINATION "${ZIG_STD_DEST}/c")
|
||||||
install(FILES "${CMAKE_SOURCE_DIR}/std/c/linux.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/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/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/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/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/compiler_rt.zig" DESTINATION "${ZIG_STD_DEST}/special")
|
||||||
install(FILES "${CMAKE_SOURCE_DIR}/std/special/test_runner.zig" DESTINATION "${ZIG_STD_DEST}/special")
|
install(FILES "${CMAKE_SOURCE_DIR}/std/special/test_runner.zig" DESTINATION "${ZIG_STD_DEST}/special")
|
||||||
|
|||||||
@ -82,13 +82,12 @@ the Zig compiler itself:
|
|||||||
* gcc >= 5.0.0 or clang >= 3.6.0
|
* gcc >= 5.0.0 or clang >= 3.6.0
|
||||||
* cmake >= 2.8.5
|
* cmake >= 2.8.5
|
||||||
|
|
||||||
#### Runtime Dependencies
|
#### Library Dependencies
|
||||||
|
|
||||||
These libraries must be installed on your system, with the development files
|
These libraries must be installed on your system, with the development files
|
||||||
available. The Zig compiler dynamically links against them.
|
available. The Zig compiler dynamically links against them.
|
||||||
|
|
||||||
* LLVM == 4.x
|
* LLVM, Clang, and LLD libraries == 4.x
|
||||||
* libclang == 4.x
|
|
||||||
|
|
||||||
### Debug / Development Build
|
### Debug / Development Build
|
||||||
|
|
||||||
|
|||||||
@ -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
|
calls the public `panic` function exposed in the root source file, or
|
||||||
if there is not one specified, invokes the one provided in
|
if there is not one specified, invokes the one provided in
|
||||||
`std/special/panic.zig`.
|
`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`.
|
||||||
|
|||||||
@ -1196,6 +1196,7 @@ enum BuiltinFnId {
|
|||||||
BuiltinFnIdSetGlobalSection,
|
BuiltinFnIdSetGlobalSection,
|
||||||
BuiltinFnIdSetGlobalLinkage,
|
BuiltinFnIdSetGlobalLinkage,
|
||||||
BuiltinFnIdPanic,
|
BuiltinFnIdPanic,
|
||||||
|
BuiltinFnIdBitCast,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BuiltinFnEntry {
|
struct BuiltinFnEntry {
|
||||||
@ -1719,7 +1720,7 @@ enum IrInstructionId {
|
|||||||
IrInstructionIdFnProto,
|
IrInstructionIdFnProto,
|
||||||
IrInstructionIdTestComptime,
|
IrInstructionIdTestComptime,
|
||||||
IrInstructionIdInitEnum,
|
IrInstructionIdInitEnum,
|
||||||
IrInstructionIdPointerReinterpret,
|
IrInstructionIdBitCast,
|
||||||
IrInstructionIdWidenOrShorten,
|
IrInstructionIdWidenOrShorten,
|
||||||
IrInstructionIdIntToPtr,
|
IrInstructionIdIntToPtr,
|
||||||
IrInstructionIdPtrToInt,
|
IrInstructionIdPtrToInt,
|
||||||
@ -2369,10 +2370,11 @@ struct IrInstructionInitEnum {
|
|||||||
LLVMValueRef tmp_ptr;
|
LLVMValueRef tmp_ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IrInstructionPointerReinterpret {
|
struct IrInstructionBitCast {
|
||||||
IrInstruction base;
|
IrInstruction base;
|
||||||
|
|
||||||
IrInstruction *ptr;
|
IrInstruction *dest_type;
|
||||||
|
IrInstruction *target;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IrInstructionWidenOrShorten {
|
struct IrInstructionWidenOrShorten {
|
||||||
|
|||||||
@ -3355,7 +3355,6 @@ bool type_has_bits(TypeTableEntry *type_entry) {
|
|||||||
bool type_requires_comptime(TypeTableEntry *type_entry) {
|
bool type_requires_comptime(TypeTableEntry *type_entry) {
|
||||||
switch (get_underlying_type(type_entry)->id) {
|
switch (get_underlying_type(type_entry)->id) {
|
||||||
case TypeTableEntryIdInvalid:
|
case TypeTableEntryIdInvalid:
|
||||||
case TypeTableEntryIdUnreachable:
|
|
||||||
case TypeTableEntryIdVar:
|
case TypeTableEntryIdVar:
|
||||||
case TypeTableEntryIdTypeDecl:
|
case TypeTableEntryIdTypeDecl:
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
@ -3383,6 +3382,7 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {
|
|||||||
case TypeTableEntryIdPointer:
|
case TypeTableEntryIdPointer:
|
||||||
case TypeTableEntryIdEnumTag:
|
case TypeTableEntryIdEnumTag:
|
||||||
case TypeTableEntryIdVoid:
|
case TypeTableEntryIdVoid:
|
||||||
|
case TypeTableEntryIdUnreachable:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
|
|||||||
@ -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);
|
PackageTableEntry *entry = allocate<PackageTableEntry>(1);
|
||||||
entry->package_table.init(4);
|
entry->package_table.init(4);
|
||||||
buf_init_from_str(&entry->root_src_dir, root_src_dir);
|
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();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
static LLVMValueRef ir_render_pointer_reinterpret(CodeGen *g, IrExecutable *executable,
|
static LLVMValueRef ir_render_bitcast(CodeGen *g, IrExecutable *executable,
|
||||||
IrInstructionPointerReinterpret *instruction)
|
IrInstructionBitCast *instruction)
|
||||||
{
|
{
|
||||||
TypeTableEntry *wanted_type = instruction->base.value.type;
|
TypeTableEntry *wanted_type = instruction->base.value.type;
|
||||||
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
|
LLVMValueRef target = ir_llvm_value(g, instruction->target);
|
||||||
return LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, "");
|
return LLVMBuildBitCast(g->builder, target, wanted_type->type_ref, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executable,
|
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);
|
return ir_render_init_enum(g, executable, (IrInstructionInitEnum *)instruction);
|
||||||
case IrInstructionIdStructInit:
|
case IrInstructionIdStructInit:
|
||||||
return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
|
return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
|
||||||
case IrInstructionIdPointerReinterpret:
|
case IrInstructionIdBitCast:
|
||||||
return ir_render_pointer_reinterpret(g, executable, (IrInstructionPointerReinterpret *)instruction);
|
return ir_render_bitcast(g, executable, (IrInstructionBitCast *)instruction);
|
||||||
case IrInstructionIdWidenOrShorten:
|
case IrInstructionIdWidenOrShorten:
|
||||||
return ir_render_widen_or_shorten(g, executable, (IrInstructionWidenOrShorten *)instruction);
|
return ir_render_widen_or_shorten(g, executable, (IrInstructionWidenOrShorten *)instruction);
|
||||||
case IrInstructionIdPtrToInt:
|
case IrInstructionIdPtrToInt:
|
||||||
@ -3638,8 +3638,14 @@ static void do_code_gen(CodeGen *g) {
|
|||||||
} else {
|
} else {
|
||||||
assert(var->gen_arg_index != SIZE_MAX);
|
assert(var->gen_arg_index != SIZE_MAX);
|
||||||
TypeTableEntry *gen_type;
|
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)) {
|
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);
|
var->value_ref = LLVMGetParam(fn, var->gen_arg_index);
|
||||||
} else {
|
} else {
|
||||||
gen_type = var->value->type;
|
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, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2);
|
||||||
create_builtin_fn(g, BuiltinFnIdSetGlobalLinkage, "setGlobalLinkage", 2);
|
create_builtin_fn(g, BuiltinFnIdSetGlobalLinkage, "setGlobalLinkage", 2);
|
||||||
create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1);
|
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) {
|
static void add_compile_var(CodeGen *g, const char *name, ConstExprValue *value) {
|
||||||
|
|||||||
@ -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_linker_script(CodeGen *g, const char *linker_script);
|
||||||
void codegen_set_omit_zigrt(CodeGen *g, bool omit_zigrt);
|
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_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);
|
void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code);
|
||||||
|
|||||||
135
src/ir.cpp
135
src/ir.cpp
@ -480,8 +480,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionInitEnum *) {
|
|||||||
return IrInstructionIdInitEnum;
|
return IrInstructionIdInitEnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionPointerReinterpret *) {
|
static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {
|
||||||
return IrInstructionIdPointerReinterpret;
|
return IrInstructionIdBitCast;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionWidenOrShorten *) {
|
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;
|
return new_instruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
static IrInstruction *ir_build_pointer_reinterpret(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||||
IrInstruction *ptr)
|
IrInstruction *dest_type, IrInstruction *target)
|
||||||
{
|
{
|
||||||
IrInstructionPointerReinterpret *instruction = ir_build_instruction<IrInstructionPointerReinterpret>(
|
IrInstructionBitCast *instruction = ir_build_instruction<IrInstructionBitCast>(
|
||||||
irb, scope, source_node);
|
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;
|
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)
|
size_t index)
|
||||||
{
|
{
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0: return instruction->ptr;
|
case 0: return instruction->dest_type;
|
||||||
|
case 1: return instruction->target;
|
||||||
default: return nullptr;
|
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);
|
return ir_instruction_testcomptime_get_dep((IrInstructionTestComptime *) instruction, index);
|
||||||
case IrInstructionIdInitEnum:
|
case IrInstructionIdInitEnum:
|
||||||
return ir_instruction_initenum_get_dep((IrInstructionInitEnum *) instruction, index);
|
return ir_instruction_initenum_get_dep((IrInstructionInitEnum *) instruction, index);
|
||||||
case IrInstructionIdPointerReinterpret:
|
case IrInstructionIdBitCast:
|
||||||
return ir_instruction_pointerreinterpret_get_dep((IrInstructionPointerReinterpret *) instruction, index);
|
return ir_instruction_bitcast_get_dep((IrInstructionBitCast *) instruction, index);
|
||||||
case IrInstructionIdWidenOrShorten:
|
case IrInstructionIdWidenOrShorten:
|
||||||
return ir_instruction_widenorshorten_get_dep((IrInstructionWidenOrShorten *) instruction, index);
|
return ir_instruction_widenorshorten_get_dep((IrInstructionWidenOrShorten *) instruction, index);
|
||||||
case IrInstructionIdIntToPtr:
|
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);
|
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();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
@ -6364,34 +6381,6 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc
|
|||||||
return result;
|
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,
|
static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction *source_instr,
|
||||||
IrInstruction *value, TypeTableEntry *wanted_type)
|
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
|
// explicit cast from child type of maybe type to maybe type
|
||||||
if (wanted_type->id == TypeTableEntryIdMaybe) {
|
if (wanted_type->id == TypeTableEntryIdMaybe) {
|
||||||
if (types_match_const_cast_only(wanted_type->data.maybe.child_type, actual_type)) {
|
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;
|
ConstExprValue *array_ptr_val;
|
||||||
if (array_ptr->value.special != ConstValSpecialRuntime &&
|
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 = const_ptr_pointee(&array_ptr->value)) &&
|
||||||
array_ptr_val->special != ConstValSpecialRuntime &&
|
array_ptr_val->special != ConstValSpecialRuntime &&
|
||||||
(array_type->id != TypeTableEntryIdPointer ||
|
(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);
|
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,
|
static TypeTableEntry *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
|
||||||
IrInstructionDeclRef *instruction)
|
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) {
|
static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
|
||||||
switch (instruction->id) {
|
switch (instruction->id) {
|
||||||
case IrInstructionIdInvalid:
|
case IrInstructionIdInvalid:
|
||||||
case IrInstructionIdPointerReinterpret:
|
|
||||||
case IrInstructionIdWidenOrShorten:
|
case IrInstructionIdWidenOrShorten:
|
||||||
case IrInstructionIdIntToPtr:
|
case IrInstructionIdIntToPtr:
|
||||||
case IrInstructionIdPtrToInt:
|
case IrInstructionIdPtrToInt:
|
||||||
@ -12449,6 +12464,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
|
|||||||
return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction);
|
return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction);
|
||||||
case IrInstructionIdPanic:
|
case IrInstructionIdPanic:
|
||||||
return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);
|
return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);
|
||||||
|
case IrInstructionIdBitCast:
|
||||||
|
return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction);
|
||||||
case IrInstructionIdMaybeWrap:
|
case IrInstructionIdMaybeWrap:
|
||||||
case IrInstructionIdErrWrapCode:
|
case IrInstructionIdErrWrapCode:
|
||||||
case IrInstructionIdErrWrapPayload:
|
case IrInstructionIdErrWrapPayload:
|
||||||
@ -12620,7 +12637,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
|||||||
case IrInstructionIdFnProto:
|
case IrInstructionIdFnProto:
|
||||||
case IrInstructionIdTestComptime:
|
case IrInstructionIdTestComptime:
|
||||||
case IrInstructionIdInitEnum:
|
case IrInstructionIdInitEnum:
|
||||||
case IrInstructionIdPointerReinterpret:
|
case IrInstructionIdBitCast:
|
||||||
case IrInstructionIdWidenOrShorten:
|
case IrInstructionIdWidenOrShorten:
|
||||||
case IrInstructionIdPtrToInt:
|
case IrInstructionIdPtrToInt:
|
||||||
case IrInstructionIdIntToPtr:
|
case IrInstructionIdIntToPtr:
|
||||||
|
|||||||
@ -765,9 +765,9 @@ static void ir_print_init_enum(IrPrint *irp, IrInstructionInitEnum *instruction)
|
|||||||
fprintf(irp->f, "}");
|
fprintf(irp->f, "}");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ir_print_pointer_reinterpret(IrPrint *irp, IrInstructionPointerReinterpret *instruction) {
|
static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
|
||||||
fprintf(irp->f, "@pointerReinterpret(");
|
fprintf(irp->f, "@bitcast(");
|
||||||
ir_print_other_instruction(irp, instruction->ptr);
|
ir_print_other_instruction(irp, instruction->target);
|
||||||
fprintf(irp->f, ")");
|
fprintf(irp->f, ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1098,8 +1098,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
|||||||
case IrInstructionIdInitEnum:
|
case IrInstructionIdInitEnum:
|
||||||
ir_print_init_enum(irp, (IrInstructionInitEnum *)instruction);
|
ir_print_init_enum(irp, (IrInstructionInitEnum *)instruction);
|
||||||
break;
|
break;
|
||||||
case IrInstructionIdPointerReinterpret:
|
case IrInstructionIdBitCast:
|
||||||
ir_print_pointer_reinterpret(irp, (IrInstructionPointerReinterpret *)instruction);
|
ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);
|
||||||
break;
|
break;
|
||||||
case IrInstructionIdWidenOrShorten:
|
case IrInstructionIdWidenOrShorten:
|
||||||
ir_print_widen_or_shorten(irp, (IrInstructionWidenOrShorten *)instruction);
|
ir_print_widen_or_shorten(irp, (IrInstructionWidenOrShorten *)instruction);
|
||||||
|
|||||||
168
src/main.cpp
168
src/main.cpp
@ -19,46 +19,48 @@
|
|||||||
static int usage(const char *arg0) {
|
static int usage(const char *arg0) {
|
||||||
fprintf(stderr, "Usage: %s [command] [options]\n"
|
fprintf(stderr, "Usage: %s [command] [options]\n"
|
||||||
"Commands:\n"
|
"Commands:\n"
|
||||||
" build [sources] create executable, object, or library from source\n"
|
" build build project from build.zig\n"
|
||||||
" test [sources] create and run a test build\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"
|
" 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"
|
" targets list available compilation targets\n"
|
||||||
|
" test [source] create and run a test build\n"
|
||||||
|
" version print version number and exit\n"
|
||||||
"Options:\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"
|
" --release build with optimizations on and debug protection off\n"
|
||||||
" --static output will be statically linked\n"
|
" --static output will be statically linked\n"
|
||||||
" --strip exclude debug symbols\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-arch [name] specify target architecture\n"
|
||||||
" --target-os [name] specify target operating system\n"
|
|
||||||
" --target-environ [name] specify target environment\n"
|
" --target-environ [name] specify target environment\n"
|
||||||
" -mwindows (windows only) --subsystem windows to the linker\n"
|
" --target-os [name] specify target operating system\n"
|
||||||
" -mconsole (windows only) --subsystem console to the linker\n"
|
" --verbose turn on compiler debug output\n"
|
||||||
" -municode (windows only) link with unicode\n"
|
" --zig-std-dir [path] directory where zig standard library resides\n"
|
||||||
" -mlinker-version [ver] (darwin only) override linker version\n"
|
" -L[dir] alias for --library-path\n"
|
||||||
" -rdynamic add all symbols to the dynamic symbol table\n"
|
" -dirafter [dir] same as -isystem but do it last\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"
|
|
||||||
" -framework [name] (darwin only) link against framework\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"
|
" -rpath [path] add directory to the runtime library search path\n"
|
||||||
" --each-lib-rpath add rpath for each used dynamic library\n"
|
|
||||||
, arg0);
|
, arg0);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
@ -144,6 +146,62 @@ int main(int argc, char **argv) {
|
|||||||
ZigList<const char *> rpath_list = {0};
|
ZigList<const char *> rpath_list = {0};
|
||||||
bool each_lib_rpath = false;
|
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) {
|
for (int i = 1; i < argc; i += 1) {
|
||||||
char *arg = argv[i];
|
char *arg = argv[i];
|
||||||
|
|
||||||
@ -177,16 +235,6 @@ int main(int argc, char **argv) {
|
|||||||
return usage(arg0);
|
return usage(arg0);
|
||||||
} else if (strcmp(arg, "--output") == 0) {
|
} else if (strcmp(arg, "--output") == 0) {
|
||||||
out_file = argv[i];
|
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) {
|
} else if (strcmp(arg, "--color") == 0) {
|
||||||
if (strcmp(argv[i], "auto") == 0) {
|
if (strcmp(argv[i], "auto") == 0) {
|
||||||
color = ErrColorAuto;
|
color = ErrColorAuto;
|
||||||
@ -243,8 +291,15 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (cmd == CmdInvalid) {
|
} else if (cmd == CmdInvalid) {
|
||||||
if (strcmp(arg, "build") == 0) {
|
if (strcmp(arg, "build_exe") == 0) {
|
||||||
cmd = CmdBuild;
|
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) {
|
} else if (strcmp(arg, "version") == 0) {
|
||||||
cmd = CmdVersion;
|
cmd = CmdVersion;
|
||||||
} else if (strcmp(arg, "parseh") == 0) {
|
} else if (strcmp(arg, "parseh") == 0) {
|
||||||
@ -285,15 +340,7 @@ int main(int argc, char **argv) {
|
|||||||
if (!in_file)
|
if (!in_file)
|
||||||
return usage(arg0);
|
return usage(arg0);
|
||||||
|
|
||||||
if (cmd == CmdBuild && !out_name) {
|
assert(cmd != CmdBuild || out_type != OutTypeUnknown);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
init_all_targets();
|
init_all_targets();
|
||||||
|
|
||||||
@ -331,6 +378,9 @@ int main(int argc, char **argv) {
|
|||||||
Buf root_source_dir = BUF_INIT;
|
Buf root_source_dir = BUF_INIT;
|
||||||
Buf root_source_code = BUF_INIT;
|
Buf root_source_code = BUF_INIT;
|
||||||
Buf root_source_name = 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, "-")) {
|
if (buf_eql_str(&in_file_buf, "-")) {
|
||||||
os_get_cwd(&root_source_dir);
|
os_get_cwd(&root_source_dir);
|
||||||
if ((err = os_fetch_file(stdin, &root_source_code))) {
|
if ((err = os_fetch_file(stdin, &root_source_code))) {
|
||||||
@ -338,12 +388,24 @@ int main(int argc, char **argv) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
buf_init_from_str(&root_source_name, "");
|
buf_init_from_str(&root_source_name, "");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
os_path_split(&in_file_buf, &root_source_dir, &root_source_name);
|
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))) {
|
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));
|
fprintf(stderr, "unable to open '%s': %s\n", in_file, err_str(err));
|
||||||
return 1;
|
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);
|
CodeGen *g = codegen_create(&root_source_dir, target);
|
||||||
@ -361,11 +423,7 @@ int main(int argc, char **argv) {
|
|||||||
} else if (cmd == CmdTest) {
|
} else if (cmd == CmdTest) {
|
||||||
codegen_set_out_type(g, OutTypeExe);
|
codegen_set_out_type(g, OutTypeExe);
|
||||||
}
|
}
|
||||||
if (out_name) {
|
codegen_set_out_name(g, buf_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"));
|
|
||||||
}
|
|
||||||
if (libc_lib_dir)
|
if (libc_lib_dir)
|
||||||
codegen_set_libc_lib_dir(g, buf_create_from_str(libc_lib_dir));
|
codegen_set_libc_lib_dir(g, buf_create_from_str(libc_lib_dir));
|
||||||
if (libc_static_lib_dir)
|
if (libc_static_lib_dir)
|
||||||
|
|||||||
26
src/os.cpp
26
src/os.cpp
@ -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);
|
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) {
|
void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) {
|
||||||
buf_init_from_buf(out_full_path, dirname);
|
buf_init_from_buf(out_full_path, dirname);
|
||||||
uint8_t c = *(buf_ptr(out_full_path) + buf_len(out_full_path) - 1);
|
uint8_t c = *(buf_ptr(out_full_path) + buf_len(out_full_path) - 1);
|
||||||
|
|||||||
@ -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_dirname(Buf *full_path, Buf *out_dirname);
|
||||||
void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename);
|
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);
|
void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path);
|
||||||
int os_path_real(Buf *rel_path, Buf *out_abs_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);
|
void os_path_resolve(Buf *ref_path, Buf *target_path, Buf *out_abs_path);
|
||||||
|
|||||||
59
std/build.zig
Normal file
59
std/build.zig
Normal 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));
|
||||||
|
}
|
||||||
@ -15,7 +15,7 @@ pub fn assert(ok: bool) {
|
|||||||
|
|
||||||
var panicking = false;
|
var panicking = false;
|
||||||
/// This is the default panic implementation.
|
/// 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
|
// TODO
|
||||||
// if (@atomicRmw(AtomicOp.XChg, &panicking, true, AtomicOrder.SeqCst)) { }
|
// if (@atomicRmw(AtomicOp.XChg, &panicking, true, AtomicOrder.SeqCst)) { }
|
||||||
if (panicking) {
|
if (panicking) {
|
||||||
@ -28,7 +28,7 @@ pub coldcc fn panic(message: []const u8) -> noreturn {
|
|||||||
panicking = true;
|
panicking = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
%%io.stderr.printf("{}\n", message);
|
%%io.stderr.printf(format, args);
|
||||||
%%printStackTrace();
|
%%printStackTrace();
|
||||||
|
|
||||||
os.abort();
|
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);
|
const name = %return compile_unit.die.getAttrString(st, DW.AT_name);
|
||||||
|
|
||||||
%return out_stream.printf("{} -> {}\n", return_address, name);
|
%return out_stream.printf("{} -> {}\n", return_address, name);
|
||||||
maybe_fp = *(&const ?&const u8)(fp);
|
maybe_fp = *@bitcast(&const ?&const u8, fp);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ObjectFormat.coff => {
|
ObjectFormat.coff => {
|
||||||
@ -511,7 +511,6 @@ pub var global_allocator = mem.Allocator {
|
|||||||
.allocFn = globalAlloc,
|
.allocFn = globalAlloc,
|
||||||
.reallocFn = globalRealloc,
|
.reallocFn = globalRealloc,
|
||||||
.freeFn = globalFree,
|
.freeFn = globalFree,
|
||||||
.context = null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var some_mem: [100 * 1024]u8 = undefined;
|
var some_mem: [100 * 1024]u8 = undefined;
|
||||||
|
|||||||
@ -236,7 +236,7 @@ test "basicHashMapTest" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn hash_i32(x: i32) -> u32 {
|
fn hash_i32(x: i32) -> u32 {
|
||||||
*(&u32)(&x)
|
*@bitcast(&u32, &x)
|
||||||
}
|
}
|
||||||
fn eql_i32(a: i32, b: i32) -> bool {
|
fn eql_i32(a: i32, b: i32) -> bool {
|
||||||
a == b
|
a == b
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
pub const build = @import("build.zig");
|
||||||
pub const c = @import("c/index.zig");
|
pub const c = @import("c/index.zig");
|
||||||
pub const cstr = @import("cstr.zig");
|
pub const cstr = @import("cstr.zig");
|
||||||
pub const debug = @import("debug.zig");
|
pub const debug = @import("debug.zig");
|
||||||
|
|||||||
66
std/mem.zig
66
std/mem.zig
@ -7,12 +7,10 @@ pub const Cmp = math.Cmp;
|
|||||||
|
|
||||||
error NoMem;
|
error NoMem;
|
||||||
|
|
||||||
pub type Context = u8;
|
|
||||||
pub const Allocator = struct {
|
pub const Allocator = struct {
|
||||||
allocFn: fn (self: &Allocator, n: usize) -> %[]u8,
|
allocFn: fn (self: &Allocator, n: usize) -> %[]u8,
|
||||||
reallocFn: fn (self: &Allocator, old_mem: []u8, new_size: usize) -> %[]u8,
|
reallocFn: fn (self: &Allocator, old_mem: []u8, new_size: usize) -> %[]u8,
|
||||||
freeFn: fn (self: &Allocator, mem: []u8),
|
freeFn: fn (self: &Allocator, mem: []u8),
|
||||||
context: ?&Context,
|
|
||||||
|
|
||||||
/// Aborts the program if an allocation fails.
|
/// Aborts the program if an allocation fails.
|
||||||
fn checkedAlloc(self: &Allocator, comptime T: type, n: usize) -> []T {
|
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 {
|
fn alloc(self: &Allocator, comptime T: type, n: usize) -> %[]T {
|
||||||
const byte_count = %return math.mulOverflow(usize, @sizeOf(T), n);
|
const byte_count = %return math.mulOverflow(usize, @sizeOf(T), n);
|
||||||
([]T)(%return self.allocFn(self, byte_count))
|
([]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.
|
/// Copy all of source into dest at position 0.
|
||||||
/// dest.len must be >= source.len.
|
/// dest.len must be >= source.len.
|
||||||
pub fn copy(comptime T: type, dest: []T, source: []const T) {
|
pub fn copy(comptime T: type, dest: []T, source: []const T) {
|
||||||
|
|||||||
@ -5,16 +5,29 @@ const arch = switch (@compileVar("arch")) {
|
|||||||
};
|
};
|
||||||
const errno = @import("errno.zig");
|
const errno = @import("errno.zig");
|
||||||
|
|
||||||
pub const MMAP_PROT_NONE = 0;
|
pub const PROT_NONE = 0;
|
||||||
pub const MMAP_PROT_READ = 1;
|
pub const PROT_READ = 1;
|
||||||
pub const MMAP_PROT_WRITE = 2;
|
pub const PROT_WRITE = 2;
|
||||||
pub const MMAP_PROT_EXEC = 4;
|
pub const PROT_EXEC = 4;
|
||||||
|
pub const PROT_GROWSDOWN = 0x01000000;
|
||||||
|
pub const PROT_GROWSUP = 0x02000000;
|
||||||
|
|
||||||
pub const MMAP_MAP_FILE = 0;
|
pub const MAP_FAILED = @maxValue(usize);
|
||||||
pub const MMAP_MAP_SHARED = 1;
|
pub const MAP_SHARED = 0x01;
|
||||||
pub const MMAP_MAP_PRIVATE = 2;
|
pub const MAP_PRIVATE = 0x02;
|
||||||
pub const MMAP_MAP_FIXED = 16;
|
pub const MAP_TYPE = 0x0f;
|
||||||
pub const MMAP_MAP_ANON = 32;
|
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 SIGHUP = 1;
|
||||||
pub const SIGINT = 2;
|
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.
|
/// Get the errno from a syscall return value, or 0 for no error.
|
||||||
pub fn getErrno(r: usize) -> usize {
|
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
|
if (signed_r > -4096 and signed_r < 0) usize(-signed_r) else 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
18
std/special/build_runner.zig
Normal file
18
std/special/build_runner.zig
Normal 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);
|
||||||
|
}
|
||||||
@ -15,7 +15,7 @@ export fn __udivdi3(a: du_int, b: du_int) -> du_int {
|
|||||||
|
|
||||||
fn du_int_to_udwords(x: du_int) -> udwords {
|
fn du_int_to_udwords(x: du_int) -> udwords {
|
||||||
@setDebugSafety(this, false);
|
@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 {
|
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) {
|
if (var rem ?= maybe_rem) {
|
||||||
r[high] = n[high] % d[high];
|
r[high] = n[high] % d[high];
|
||||||
r[low] = 0;
|
r[low] = 0;
|
||||||
*rem = *(&du_int)(&r[0]);
|
*rem = *@bitcast(&du_int, &r[0]);
|
||||||
}
|
}
|
||||||
return n[high] / d[high];
|
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) {
|
if (var rem ?= maybe_rem) {
|
||||||
r[low] = n[low];
|
r[low] = n[low];
|
||||||
r[high] = n[high] & (d[high] - 1);
|
r[high] = n[high] & (d[high] - 1);
|
||||||
*rem = *(&du_int)(&r[0]);
|
*rem = *@bitcast(&du_int, &r[0]);
|
||||||
}
|
}
|
||||||
return n[high] >> @ctz(d[high]);
|
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
|
// 0 <= sr <= n_uword_bits - 2 or sr large
|
||||||
if (sr > n_uword_bits - 2) {
|
if (sr > n_uword_bits - 2) {
|
||||||
if (var rem ?= maybe_rem) {
|
if (var rem ?= maybe_rem) {
|
||||||
*rem = *(&du_int)(&n[0]);
|
*rem = *@bitcast(&du_int, &n[0]);
|
||||||
}
|
}
|
||||||
return 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);
|
*rem = n[low] & (d[low] - 1);
|
||||||
}
|
}
|
||||||
if (d[low] == 1) {
|
if (d[low] == 1) {
|
||||||
return *(&du_int)(&n[0]);
|
return *@bitcast(&du_int, &n[0]);
|
||||||
}
|
}
|
||||||
sr = @ctz(d[low]);
|
sr = @ctz(d[low]);
|
||||||
q[high] = n[high] >> sr;
|
q[high] = n[high] >> sr;
|
||||||
q[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> 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
|
// 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
|
// 0 <= sr <= n_uword_bits - 1 or sr large
|
||||||
if (sr > n_uword_bits - 1) {
|
if (sr > n_uword_bits - 1) {
|
||||||
if (var rem ?= maybe_rem) {
|
if (var rem ?= maybe_rem) {
|
||||||
*rem = *(&du_int)(&n[0]);
|
*rem = *@bitcast(&du_int, &n[0]);
|
||||||
}
|
}
|
||||||
return 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;
|
// r.all -= d.all;
|
||||||
// carry = 1;
|
// 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);
|
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;
|
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) {
|
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 {
|
export fn __umoddi3(a: du_int, b: du_int) -> du_int {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
// This file contains functions that zig depends on to coordinate between
|
// 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.
|
// instances of zig_rt.zig do not conflict with each other.
|
||||||
|
|
||||||
export coldcc fn __zig_panic(message_ptr: &const u8, message_len: usize) -> noreturn {
|
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) {
|
} else if (@compileVar("os") == Os.freestanding) {
|
||||||
while (true) {}
|
while (true) {}
|
||||||
} else {
|
} else {
|
||||||
@import("std").debug.panic(message_ptr[0...message_len]);
|
@import("std").debug.panic("{}\n", message_ptr[0...message_len]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,18 @@ test "numLitIntToPtrCast" {
|
|||||||
test "pointerReinterpretConstFloatToInt" {
|
test "pointerReinterpretConstFloatToInt" {
|
||||||
const float: f64 = 5.99999999999994648725e-01;
|
const float: f64 = 5.99999999999994648725e-01;
|
||||||
const float_ptr = &float;
|
const float_ptr = &float;
|
||||||
const int_ptr = (&i32)(float_ptr);
|
const int_ptr = @bitcast(&i32, float_ptr);
|
||||||
const int_val = *int_ptr;
|
const int_val = *int_ptr;
|
||||||
assert(int_val == 858993411);
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@ -284,3 +284,18 @@ fn testCompTimeUIntComparisons(x: u32) {
|
|||||||
@compileError("this condition should be comptime known");
|
@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;
|
||||||
|
|||||||
@ -121,5 +121,5 @@ test "genericFnWithImplicitCast" {
|
|||||||
}
|
}
|
||||||
fn getByte(ptr: ?&const u8) -> u8 {*??ptr}
|
fn getByte(ptr: ?&const u8) -> u8 {*??ptr}
|
||||||
fn getFirstByte(comptime T: type, mem: []const T) -> u8 {
|
fn getFirstByte(comptime T: type, mem: []const T) -> u8 {
|
||||||
getByte((&const u8)(&mem[0]))
|
getByte(@bitcast(&const u8, &mem[0]))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -246,15 +246,15 @@ test "typeEquality" {
|
|||||||
|
|
||||||
const global_a: i32 = 1234;
|
const global_a: i32 = 1234;
|
||||||
const global_b: &const i32 = &global_a;
|
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" {
|
test "compileTimeGlobalReinterpret" {
|
||||||
const d = (&const i32)(global_c);
|
const d = @bitcast(&const i32, global_c);
|
||||||
assert(*d == 1234);
|
assert(*d == 1234);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "explicitCastMaybePointers" {
|
test "explicitCastMaybePointers" {
|
||||||
const a: ?&i32 = undefined;
|
const a: ?&i32 = undefined;
|
||||||
const b: ?&f32 = (?&f32)(a);
|
const b: ?&f32 = @bitcast(?&f32, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "genericMallocFree" {
|
test "genericMallocFree" {
|
||||||
@ -263,7 +263,7 @@ test "genericMallocFree" {
|
|||||||
}
|
}
|
||||||
const some_mem : [100]u8 = undefined;
|
const some_mem : [100]u8 = undefined;
|
||||||
fn memAlloc(comptime T: type, n: usize) -> %[]T {
|
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) { }
|
fn memFree(comptime T: type, memory: []T) { }
|
||||||
|
|
||||||
|
|||||||
@ -41,7 +41,7 @@ const VoidStructFieldsFoo = struct {
|
|||||||
|
|
||||||
test "fn" {
|
test "fn" {
|
||||||
var foo: StructFoo = undefined;
|
var foo: StructFoo = undefined;
|
||||||
@memset((&u8)(&foo), 0, @sizeOf(StructFoo));
|
@memset(@bitcast(&u8, &foo), 0, @sizeOf(StructFoo));
|
||||||
foo.a += 1;
|
foo.a += 1;
|
||||||
foo.b = foo.a == 1;
|
foo.b = foo.a == 1;
|
||||||
testFoo(foo);
|
testFoo(foo);
|
||||||
|
|||||||
@ -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).relative_path = tmp_source_path;
|
||||||
test_case->source_files.at(0).source_code = source;
|
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(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("--name");
|
||||||
test_case->compiler_args.append("test");
|
test_case->compiler_args.append("test");
|
||||||
test_case->compiler_args.append("--output");
|
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->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(tmp_source_path);
|
||||||
|
|
||||||
test_case->compiler_args.append("--name");
|
test_case->compiler_args.append("--name");
|
||||||
test_case->compiler_args.append("test");
|
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("--output");
|
||||||
test_case->compiler_args.append(tmp_exe_path);
|
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).relative_path = tmp_source_path;
|
||||||
test_case->source_files.at(0).source_code = source;
|
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(tmp_source_path);
|
||||||
|
|
||||||
test_case->compiler_args.append("--name");
|
test_case->compiler_args.append("--name");
|
||||||
test_case->compiler_args.append("test");
|
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("--output");
|
||||||
test_case->compiler_args.append(tmp_exe_path);
|
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->source_files.at(0).source_code = source;
|
||||||
test_case->output = "";
|
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(tmp_source_path);
|
||||||
|
|
||||||
test_case->compiler_args.append("--name");
|
test_case->compiler_args.append("--name");
|
||||||
test_case->compiler_args.append("test");
|
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("--output");
|
||||||
test_case->compiler_args.append(tmp_exe_path);
|
test_case->compiler_args.append(tmp_exe_path);
|
||||||
|
|
||||||
@ -471,8 +460,8 @@ const foo : i32 = 0;
|
|||||||
const c = @cImport(@cInclude("stdlib.h"));
|
const c = @cImport(@cInclude("stdlib.h"));
|
||||||
|
|
||||||
export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int {
|
export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int {
|
||||||
const a_int = (&i32)(a ?? unreachable);
|
const a_int = @bitcast(&i32, a ?? unreachable);
|
||||||
const b_int = (&i32)(b ?? unreachable);
|
const b_int = @bitcast(&i32, b ?? unreachable);
|
||||||
if (*a_int < *b_int) {
|
if (*a_int < *b_int) {
|
||||||
-1
|
-1
|
||||||
} else if (*a_int > *b_int) {
|
} 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 {
|
export fn main(args: c_int, argv: &&u8) -> c_int {
|
||||||
var array = []u32 { 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 };
|
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| {
|
for (array) |item, i| {
|
||||||
if (item != i) {
|
if (item != i) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user