From f6cd68386d76e4a9a489187c47f218b59e1734f3 Mon Sep 17 00:00:00 2001
From: vegecode <39607947+vegecode@users.noreply.github.com>
Date: Wed, 2 Jan 2019 15:47:47 -0600
Subject: [PATCH 01/13] @bitreverse intrinsic, part of #767 (#1865)
* bitreverse - give bswap behavior
* bitreverse, comptime_ints, negative values still not working?
* bitreverse working for negative comptime ints
* Finished bitreverse test cases
* Undo exporting a bigint function. @bitreverse test name includes ampersand
* added docs entry for @bitreverse
---
doc/langref.html.in | 12 +++++
src/all_types.hpp | 13 ++++++
src/analyze.cpp | 4 ++
src/bigint.cpp | 1 +
src/codegen.cpp | 16 +++++++
src/ir.cpp | 98 ++++++++++++++++++++++++++++++++++++++-
src/ir_print.cpp | 15 ++++++
test/behavior.zig | 1 +
test/cases/bitreverse.zig | 81 ++++++++++++++++++++++++++++++++
9 files changed, 240 insertions(+), 1 deletion(-)
create mode 100644 test/cases/bitreverse.zig
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 2a2b4003fb..6e03d3ec6d 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -5316,6 +5316,18 @@ comptime {
{#header_close#}
+ {#header_open|@bitreverse#}
+ {#syntax#}@bitreverse(comptime T: type, value: T) T{#endsyntax#}
+ {#syntax#}T{#endsyntax#} accepts any integer type.
+
+ Reverses the bitpattern of an integer value, including the sign bit if applicable.
+
+
+ For example 0b10110110 ({#syntax#}u8 = 182{#endsyntax#}, {#syntax#}i8 = -74{#endsyntax#})
+ becomes 0b01101101 ({#syntax#}u8 = 109{#endsyntax#}, {#syntax#}i8 = 109{#endsyntax#}).
+
+ {#header_close#}
+
{#header_open|@byteOffsetOf#}
{#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 2b55f8ee2e..df318729f5 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1415,6 +1415,7 @@ enum BuiltinFnId {
BuiltinFnIdAtomicRmw,
BuiltinFnIdAtomicLoad,
BuiltinFnIdBswap,
+ BuiltinFnIdBitReverse,
};
struct BuiltinFnEntry {
@@ -1488,6 +1489,7 @@ enum ZigLLVMFnId {
ZigLLVMFnIdCeil,
ZigLLVMFnIdSqrt,
ZigLLVMFnIdBswap,
+ ZigLLVMFnIdBitReverse,
};
enum AddSubMul {
@@ -1520,6 +1522,9 @@ struct ZigLLVMFnKey {
struct {
uint32_t bit_count;
} bswap;
+ struct {
+ uint32_t bit_count;
+ } bit_reverse;
} data;
};
@@ -2162,6 +2167,7 @@ enum IrInstructionId {
IrInstructionIdMarkErrRetTracePtr,
IrInstructionIdSqrt,
IrInstructionIdBswap,
+ IrInstructionIdBitReverse,
IrInstructionIdErrSetCast,
IrInstructionIdToBytes,
IrInstructionIdFromBytes,
@@ -3262,6 +3268,13 @@ struct IrInstructionBswap {
IrInstruction *op;
};
+struct IrInstructionBitReverse {
+ IrInstruction base;
+
+ IrInstruction *type;
+ IrInstruction *op;
+};
+
static const size_t slice_ptr_index = 0;
static const size_t slice_len_index = 1;
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 0f2b8e48cc..b9794114a0 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -6121,6 +6121,8 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {
return (uint32_t)(x.data.floating.bit_count) * (uint32_t)2225366385;
case ZigLLVMFnIdBswap:
return (uint32_t)(x.data.bswap.bit_count) * (uint32_t)3661994335;
+ case ZigLLVMFnIdBitReverse:
+ return (uint32_t)(x.data.bit_reverse.bit_count) * (uint32_t)2621398431;
case ZigLLVMFnIdOverflowArithmetic:
return ((uint32_t)(x.data.overflow_arithmetic.bit_count) * 87135777) +
((uint32_t)(x.data.overflow_arithmetic.add_sub_mul) * 31640542) +
@@ -6141,6 +6143,8 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
return a.data.pop_count.bit_count == b.data.pop_count.bit_count;
case ZigLLVMFnIdBswap:
return a.data.bswap.bit_count == b.data.bswap.bit_count;
+ case ZigLLVMFnIdBitReverse:
+ return a.data.bit_reverse.bit_count == b.data.bit_reverse.bit_count;
case ZigLLVMFnIdFloor:
case ZigLLVMFnIdCeil:
case ZigLLVMFnIdSqrt:
diff --git a/src/bigint.cpp b/src/bigint.cpp
index 8a8d028e82..7299f2379c 100644
--- a/src/bigint.cpp
+++ b/src/bigint.cpp
@@ -1722,3 +1722,4 @@ void bigint_incr(BigInt *x) {
bigint_add(x, ©, &one);
}
+
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 6a0596f62f..db8a5f7bb2 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -3789,6 +3789,11 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI
n_args = 1;
key.id = ZigLLVMFnIdBswap;
key.data.bswap.bit_count = (uint32_t)int_type->data.integral.bit_count;
+ } else if (fn_id == BuiltinFnIdBitReverse) {
+ fn_name = "bitreverse";
+ n_args = 1;
+ key.id = ZigLLVMFnIdBitReverse;
+ key.data.bit_reverse.bit_count = (uint32_t)int_type->data.integral.bit_count;
} else {
zig_unreachable();
}
@@ -5096,6 +5101,14 @@ static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInst
return LLVMBuildTrunc(g->builder, shifted, int_type->type_ref, "");
}
+static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutable *executable, IrInstructionBitReverse *instruction) {
+ LLVMValueRef op = ir_llvm_value(g, instruction->op);
+ ZigType *int_type = instruction->base.value.type;
+ assert(int_type->id == ZigTypeIdInt);
+ LLVMValueRef fn_val = get_int_builtin_fn(g, instruction->base.value.type, BuiltinFnIdBitReverse);
+ return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
+}
+
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
AstNode *source_node = instruction->source_node;
Scope *scope = instruction->scope;
@@ -5335,6 +5348,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction);
case IrInstructionIdBswap:
return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction);
+ case IrInstructionIdBitReverse:
+ return ir_render_bit_reverse(g, executable, (IrInstructionBitReverse *)instruction);
}
zig_unreachable();
}
@@ -6758,6 +6773,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
create_builtin_fn(g, BuiltinFnIdThis, "This", 0);
create_builtin_fn(g, BuiltinFnIdBswap, "bswap", 2);
+ create_builtin_fn(g, BuiltinFnIdBitReverse, "bitreverse", 2);
}
static const char *bool_to_str(bool b) {
diff --git a/src/ir.cpp b/src/ir.cpp
index b1429ae8ac..dac5403550 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -861,6 +861,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBswap *) {
return IrInstructionIdBswap;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionBitReverse *) {
+ return IrInstructionIdBitReverse;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) {
return IrInstructionIdCheckRuntimeScope;
}
@@ -2721,6 +2725,17 @@ static IrInstruction *ir_build_bswap(IrBuilder *irb, Scope *scope, AstNode *sour
return &instruction->base;
}
+static IrInstruction *ir_build_bit_reverse(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) {
+ IrInstructionBitReverse *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->type = type;
+ instruction->op = op;
+
+ if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);
+ ir_ref_instruction(op, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) {
IrInstructionCheckRuntimeScope *instruction = ir_build_instruction(irb, scope, source_node);
instruction->scope_is_comptime = scope_is_comptime;
@@ -3646,7 +3661,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
Buf *name = fn_ref_expr->data.symbol_expr.symbol;
auto entry = irb->codegen->builtin_fn_table.maybe_get(name);
- if (!entry) {
+ if (!entry) { // new built in not found
add_node_error(irb->codegen, node,
buf_sprintf("invalid builtin function: '%s'", buf_ptr(name)));
return irb->codegen->invalid_instruction;
@@ -4720,6 +4735,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
IrInstruction *result = ir_build_bswap(irb, scope, node, arg0_value, arg1_value);
return ir_lval_wrap(irb, scope, result, lval);
}
+ case BuiltinFnIdBitReverse:
+ {
+ 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;
+
+ IrInstruction *result = ir_build_bit_reverse(irb, scope, node, arg0_value, arg1_value);
+ return ir_lval_wrap(irb, scope, result, lval);
+ }
}
zig_unreachable();
}
@@ -21115,6 +21145,69 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction
return result;
}
+static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstructionBitReverse *instruction) {
+ ZigType *int_type = ir_resolve_type(ira, instruction->type->child);
+ if (type_is_invalid(int_type))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *op = instruction->op->child;
+ if (type_is_invalid(op->value.type))
+ return ira->codegen->invalid_instruction;
+
+ if (int_type->id != ZigTypeIdInt) {
+ ir_add_error(ira, instruction->type,
+ buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type);
+ if (type_is_invalid(casted_op->value.type))
+ return ira->codegen->invalid_instruction;
+
+ if (int_type->data.integral.bit_count == 0) {
+ IrInstruction *result = ir_const(ira, &instruction->base, int_type);
+ bigint_init_unsigned(&result->value.data.x_bigint, 0);
+ return result;
+ }
+
+ if (instr_is_comptime(casted_op)) {
+ ConstExprValue *val = ir_resolve_const(ira, casted_op, UndefBad);
+ if (!val)
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *result = ir_const(ira, &instruction->base, int_type);
+ size_t num_bits = int_type->data.integral.bit_count;
+ size_t buf_size = (num_bits + 7) / 8;
+ uint8_t *comptime_buf = allocate_nonzero(buf_size);
+ uint8_t *result_buf = allocate_nonzero(buf_size);
+ memset(comptime_buf,0,buf_size);
+ memset(result_buf,0,buf_size);
+
+ bigint_write_twos_complement(&val->data.x_bigint,comptime_buf,num_bits,ira->codegen->is_big_endian);
+
+ size_t bit_i = 0;
+ size_t bit_rev_i = num_bits - 1;
+ for (; bit_i < num_bits; bit_i++, bit_rev_i--) {
+ if (comptime_buf[bit_i / 8] & (1 << (bit_i % 8))) {
+ result_buf[bit_rev_i / 8] |= (1 << (bit_rev_i % 8));
+ }
+ }
+
+ bigint_read_twos_complement(&result->value.data.x_bigint,
+ result_buf,
+ int_type->data.integral.bit_count,
+ ira->codegen->is_big_endian,
+ int_type->data.integral.is_signed);
+
+ return result;
+ }
+
+ IrInstruction *result = ir_build_bit_reverse(&ira->new_irb, instruction->base.scope,
+ instruction->base.source_node, nullptr, casted_op);
+ result->value.type = int_type;
+ return result;
+}
+
static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {
Error err;
@@ -21453,6 +21546,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction);
case IrInstructionIdBswap:
return ir_analyze_instruction_bswap(ira, (IrInstructionBswap *)instruction);
+ case IrInstructionIdBitReverse:
+ return ir_analyze_instruction_bit_reverse(ira, (IrInstructionBitReverse *)instruction);
case IrInstructionIdIntToErr:
return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction);
case IrInstructionIdErrToInt:
@@ -21675,6 +21770,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdPromiseResultType:
case IrInstructionIdSqrt:
case IrInstructionIdBswap:
+ case IrInstructionIdBitReverse:
case IrInstructionIdAtomicLoad:
case IrInstructionIdIntCast:
case IrInstructionIdFloatCast:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index e09b0073eb..b5099db86a 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -1335,6 +1335,18 @@ static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) {
fprintf(irp->f, ")");
}
+static void ir_print_bit_reverse(IrPrint *irp, IrInstructionBitReverse *instruction) {
+ fprintf(irp->f, "@bitreverse(");
+ if (instruction->type != nullptr) {
+ ir_print_other_instruction(irp, instruction->type);
+ } else {
+ fprintf(irp->f, "null");
+ }
+ fprintf(irp->f, ",");
+ ir_print_other_instruction(irp, instruction->op);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
ir_print_prefix(irp, instruction);
switch (instruction->id) {
@@ -1751,6 +1763,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdBswap:
ir_print_bswap(irp, (IrInstructionBswap *)instruction);
break;
+ case IrInstructionIdBitReverse:
+ ir_print_bit_reverse(irp, (IrInstructionBitReverse *)instruction);
+ break;
case IrInstructionIdAtomicLoad:
ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);
break;
diff --git a/test/behavior.zig b/test/behavior.zig
index 8090359772..10cd08dad7 100644
--- a/test/behavior.zig
+++ b/test/behavior.zig
@@ -9,6 +9,7 @@ comptime {
_ = @import("cases/bitcast.zig");
_ = @import("cases/bool.zig");
_ = @import("cases/bswap.zig");
+ _ = @import("cases/bitreverse.zig");
_ = @import("cases/bugs/1076.zig");
_ = @import("cases/bugs/1111.zig");
_ = @import("cases/bugs/1277.zig");
diff --git a/test/cases/bitreverse.zig b/test/cases/bitreverse.zig
new file mode 100644
index 0000000000..3721e68a94
--- /dev/null
+++ b/test/cases/bitreverse.zig
@@ -0,0 +1,81 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const minInt = std.math.minInt;
+
+test "@bitreverse" {
+ comptime testBitReverse();
+ testBitReverse();
+}
+
+fn testBitReverse() void {
+ // using comptime_ints, unsigned
+ assert(@bitreverse(u0, 0) == 0);
+ assert(@bitreverse(u5, 0x12) == 0x9);
+ assert(@bitreverse(u8, 0x12) == 0x48);
+ assert(@bitreverse(u16, 0x1234) == 0x2c48);
+ assert(@bitreverse(u24, 0x123456) == 0x6a2c48);
+ assert(@bitreverse(u32, 0x12345678) == 0x1e6a2c48);
+ assert(@bitreverse(u40, 0x123456789a) == 0x591e6a2c48);
+ assert(@bitreverse(u48, 0x123456789abc) == 0x3d591e6a2c48);
+ assert(@bitreverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48);
+ assert(@bitreverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48);
+ assert(@bitreverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48);
+
+ // using runtime uints, unsigned
+ var num0: u0 = 0;
+ assert(@bitreverse(u0, num0) == 0);
+ var num5: u5 = 0x12;
+ assert(@bitreverse(u5, num5) == 0x9);
+ var num8: u8 = 0x12;
+ assert(@bitreverse(u8, num8) == 0x48);
+ var num16: u16 = 0x1234;
+ assert(@bitreverse(u16, num16) == 0x2c48);
+ var num24: u24 = 0x123456;
+ assert(@bitreverse(u24, num24) == 0x6a2c48);
+ var num32: u32 = 0x12345678;
+ assert(@bitreverse(u32, num32) == 0x1e6a2c48);
+ var num40: u40 = 0x123456789a;
+ assert(@bitreverse(u40, num40) == 0x591e6a2c48);
+ var num48: u48 = 0x123456789abc;
+ assert(@bitreverse(u48, num48) == 0x3d591e6a2c48);
+ var num56: u56 = 0x123456789abcde;
+ assert(@bitreverse(u56, num56) == 0x7b3d591e6a2c48);
+ var num64: u64 = 0x123456789abcdef1;
+ assert(@bitreverse(u64, num64) == 0x8f7b3d591e6a2c48);
+ var num128: u128 = 0x123456789abcdef11121314151617181;
+ assert(@bitreverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48);
+
+ // using comptime_ints, signed, positive
+ assert(@bitreverse(i0, 0) == 0);
+ assert(@bitreverse(i8, @bitCast(i8, u8(0x92))) == @bitCast(i8, u8( 0x49)));
+ assert(@bitreverse(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16( 0x2c48)));
+ assert(@bitreverse(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24( 0x6a2c48)));
+ assert(@bitreverse(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32( 0x1e6a2c48)));
+ assert(@bitreverse(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40( 0x591e6a2c48)));
+ assert(@bitreverse(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48( 0x3d591e6a2c48)));
+ assert(@bitreverse(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56( 0x7b3d591e6a2c48)));
+ assert(@bitreverse(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64,u64(0x8f7b3d591e6a2c48)));
+ assert(@bitreverse(i128, @bitCast(i128,u128(0x123456789abcdef11121314151617181))) == @bitCast(i128,u128(0x818e868a828c84888f7b3d591e6a2c48)));
+
+ // using comptime_ints, signed, negative. Compare to runtime ints returned from llvm.
+ var neg5: i5 = minInt(i5) + 1;
+ assert(@bitreverse(i5, minInt(i5) + 1) == @bitreverse(i5, neg5));
+ var neg8: i8 = -18;
+ assert(@bitreverse(i8, -18) == @bitreverse(i8, neg8));
+ var neg16: i16 = -32694;
+ assert(@bitreverse(i16, -32694) == @bitreverse(i16, neg16));
+ var neg24: i24 = -6773785;
+ assert(@bitreverse(i24, -6773785) == @bitreverse(i24, neg24));
+ var neg32: i32 = -16773785;
+ assert(@bitreverse(i32, -16773785) == @bitreverse(i32, neg32));
+ var neg40: i40 = minInt(i40) + 12345;
+ assert(@bitreverse(i40, minInt(i40) + 12345) == @bitreverse(i40, neg40));
+ var neg48: i48 = minInt(i48) + 12345;
+ assert(@bitreverse(i48, minInt(i48) + 12345) == @bitreverse(i48, neg48));
+ var neg56: i56 = minInt(i56) + 12345;
+ assert(@bitreverse(i56, minInt(i56) + 12345) == @bitreverse(i56, neg56));
+ var neg64: i64 = minInt(i64) + 12345;
+ assert(@bitreverse(i64, minInt(i64) + 12345) == @bitreverse(i64, neg64));
+ var neg128: i128 = minInt(i128) + 12345;
+ assert(@bitreverse(i128, minInt(i128) + 12345) == @bitreverse(i128, neg128));
+}
From 1e781a30f63acc597129a8f0c4fee7390a96192b Mon Sep 17 00:00:00 2001
From: Marcio Giaxa
Date: Fri, 4 Jan 2019 14:19:21 -0200
Subject: [PATCH 02/13] freebsd: add clock const definitions
---
std/os/freebsd/index.zig | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/std/os/freebsd/index.zig b/std/os/freebsd/index.zig
index 603265b956..c122c2d7e1 100644
--- a/std/os/freebsd/index.zig
+++ b/std/os/freebsd/index.zig
@@ -26,6 +26,21 @@ pub const PROT_READ = 1;
pub const PROT_WRITE = 2;
pub const PROT_EXEC = 4;
+pub const CLOCK_REALTIME = 0;
+pub const CLOCK_VIRTUAL = 1;
+pub const CLOCK_PROF = 2;
+pub const CLOCK_MONOTONIC = 4;
+pub const CLOCK_UPTIME = 5;
+pub const CLOCK_UPTIME_PRECISE = 7;
+pub const CLOCK_UPTIME_FAST = 8;
+pub const CLOCK_REALTIME_PRECISE = 9;
+pub const CLOCK_REALTIME_FAST = 10;
+pub const CLOCK_MONOTONIC_PRECISE = 11;
+pub const CLOCK_MONOTONIC_FAST = 12;
+pub const CLOCK_SECOND = 13;
+pub const CLOCK_THREAD_CPUTIME_ID = 14;
+pub const CLOCK_PROCESS_CPUTIME_ID = 15;
+
pub const MAP_FAILED = maxInt(usize);
pub const MAP_SHARED = 0x0001;
pub const MAP_PRIVATE = 0x0002;
From 4d9547ff2e9377abeb87b53e30580cf1a561f9ce Mon Sep 17 00:00:00 2001
From: Marcio Giaxa
Date: Fri, 4 Jan 2019 14:42:45 -0200
Subject: [PATCH 03/13] freebsd: implement clock related functions
- clock_gettime
- clock_getres
---
std/c/freebsd.zig | 2 ++
std/os/freebsd/index.zig | 8 ++++++++
std/os/time.zig | 8 ++++----
3 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/std/c/freebsd.zig b/std/c/freebsd.zig
index eae5516db3..4d5c3810e8 100644
--- a/std/c/freebsd.zig
+++ b/std/c/freebsd.zig
@@ -22,6 +22,8 @@ pub extern "c" fn openat(fd: c_int, path: ?[*]const u8, flags: c_int) c_int;
pub extern "c" fn setgid(ruid: c_uint, euid: c_uint) c_int;
pub extern "c" fn setuid(uid: c_uint) c_int;
pub extern "c" fn kill(pid: c_int, sig: c_int) c_int;
+pub extern "c" fn clock_gettime(clk_id: c_int, tp: *timespec) c_int;
+pub extern "c" fn clock_getres(clk_id: c_int, tp: *timespec) c_int;
/// Renamed from `kevent` to `Kevent` to avoid conflict with function name.
pub const Kevent = extern struct {
diff --git a/std/os/freebsd/index.zig b/std/os/freebsd/index.zig
index c122c2d7e1..9bb683f69e 100644
--- a/std/os/freebsd/index.zig
+++ b/std/os/freebsd/index.zig
@@ -714,6 +714,14 @@ pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize {
return errnoWrap(c.nanosleep(req, rem));
}
+pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
+ return errnoWrap(c.clock_gettime(clk_id, tp));
+}
+
+pub fn clock_getres(clk_id: i32, tp: *timespec) usize {
+ return clock_gettime(clk_id, tp);
+}
+
pub fn setuid(uid: u32) usize {
return errnoWrap(c.setuid(uid));
}
diff --git a/std/os/time.zig b/std/os/time.zig
index c3588838bc..42f32f8fee 100644
--- a/std/os/time.zig
+++ b/std/os/time.zig
@@ -61,7 +61,7 @@ pub fn timestamp() u64 {
/// Get the posix timestamp, UTC, in milliseconds
pub const milliTimestamp = switch (builtin.os) {
Os.windows => milliTimestampWindows,
- Os.linux => milliTimestampPosix,
+ Os.linux, Os.freebsd => milliTimestampPosix,
Os.macosx, Os.ios => milliTimestampDarwin,
else => @compileError("Unsupported OS"),
};
@@ -179,7 +179,7 @@ pub const Timer = struct {
debug.assert(err != windows.FALSE);
self.start_time = @intCast(u64, start_time);
},
- Os.linux => {
+ Os.linux, Os.freebsd => {
//On Linux, seccomp can do arbitrary things to our ability to call
// syscalls, including return any errno value it wants and
// inconsistently throwing errors. Since we can't account for
@@ -215,7 +215,7 @@ pub const Timer = struct {
var clock = clockNative() - self.start_time;
return switch (builtin.os) {
Os.windows => @divFloor(clock * ns_per_s, self.frequency),
- Os.linux => clock,
+ Os.linux, Os.freebsd => clock,
Os.macosx, Os.ios => @divFloor(clock * self.frequency.numer, self.frequency.denom),
else => @compileError("Unsupported OS"),
};
@@ -236,7 +236,7 @@ pub const Timer = struct {
const clockNative = switch (builtin.os) {
Os.windows => clockWindows,
- Os.linux => clockLinux,
+ Os.linux, Os.freebsd => clockLinux,
Os.macosx, Os.ios => clockDarwin,
else => @compileError("Unsupported OS"),
};
From 5c2a1055a03d4ef9e4d292afe8b934cb6a7afa11 Mon Sep 17 00:00:00 2001
From: Marcio Giaxa
Date: Fri, 4 Jan 2019 16:17:46 -0200
Subject: [PATCH 04/13] freebsd: add sockaddr structs
---
std/c/freebsd.zig | 25 +++++++++++++++++++++++++
std/os/freebsd/index.zig | 4 ++++
2 files changed, 29 insertions(+)
diff --git a/std/c/freebsd.zig b/std/c/freebsd.zig
index 4d5c3810e8..2f2f4c0a1b 100644
--- a/std/c/freebsd.zig
+++ b/std/c/freebsd.zig
@@ -93,3 +93,28 @@ pub const dirent = extern struct {
d_pad1: u16,
d_name: [256]u8,
};
+
+pub const in_port_t = u16;
+pub const sa_family_t = u16;
+
+pub const sockaddr = extern union {
+ in: sockaddr_in,
+ in6: sockaddr_in6,
+};
+
+pub const sockaddr_in = extern struct {
+ len: u8,
+ family: sa_family_t,
+ port: in_port_t,
+ addr: [16]u8,
+ zero: [8]u8,
+};
+
+pub const sockaddr_in6 = extern struct {
+ len: u8,
+ family: sa_family_t,
+ port: in_port_t,
+ flowinfo: u32,
+ addr: [16]u8,
+ scope_id: u32,
+};
diff --git a/std/os/freebsd/index.zig b/std/os/freebsd/index.zig
index 9bb683f69e..c333ef2ac4 100644
--- a/std/os/freebsd/index.zig
+++ b/std/os/freebsd/index.zig
@@ -525,6 +525,10 @@ pub const TIOCGPKT = 0x80045438;
pub const TIOCGPTLCK = 0x80045439;
pub const TIOCGEXCL = 0x80045440;
+pub const sockaddr = c.sockaddr;
+pub const sockaddr_in = c.sockaddr_in;
+pub const sockaddr_in6 = c.sockaddr_in6;
+
fn unsigned(s: i32) u32 {
return @bitCast(u32, s);
}
From 1f08be4d7fdf08bda66312ab4b2e401de378083e Mon Sep 17 00:00:00 2001
From: vegecode <39607947+vegecode@users.noreply.github.com>
Date: Fri, 4 Jan 2019 16:34:21 -0600
Subject: [PATCH 05/13] Mark comptime int hardcoded address pointee as a run
time variable #1171 (#1868)
* Mark comptime int hardcoded address as a run time variable #1171
* test case for dereferencing hardcoded address intToPtr
---
src/ir.cpp | 1 +
test/cases/inttoptr.zig | 14 ++++++++++++++
2 files changed, 15 insertions(+)
diff --git a/src/ir.cpp b/src/ir.cpp
index dac5403550..400b07368b 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -20363,6 +20363,7 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru
IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
+ result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);
return result;
}
diff --git a/test/cases/inttoptr.zig b/test/cases/inttoptr.zig
index 6695352383..ba3cc52f09 100644
--- a/test/cases/inttoptr.zig
+++ b/test/cases/inttoptr.zig
@@ -11,3 +11,17 @@ fn randomAddressToFunction() void {
var addr: usize = 0xdeadbeef;
var ptr = @intToPtr(fn () void, addr);
}
+
+test "mutate through ptr initialized with constant intToPtr value" {
+ forceCompilerAnalyzeBranchHardCodedPtrDereference(false);
+}
+
+fn forceCompilerAnalyzeBranchHardCodedPtrDereference(x: bool) void {
+ const hardCodedP = @intToPtr(*volatile u8, 0xdeadbeef);
+ if (x) {
+ hardCodedP.* = hardCodedP.* | 10;
+ } else {
+ return;
+ }
+}
+
From 5f26d1dddbe9004429adca6e55d3344ca58062ae Mon Sep 17 00:00:00 2001
From: Marcio
Date: Sat, 5 Jan 2019 18:34:47 +0000
Subject: [PATCH 06/13] freebsd: fix wrong call to clock_getres (#1871)
Reported-by: daurnimator
---
std/os/freebsd/index.zig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/std/os/freebsd/index.zig b/std/os/freebsd/index.zig
index c333ef2ac4..a3ab5e7749 100644
--- a/std/os/freebsd/index.zig
+++ b/std/os/freebsd/index.zig
@@ -723,7 +723,7 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
}
pub fn clock_getres(clk_id: i32, tp: *timespec) usize {
- return clock_gettime(clk_id, tp);
+ return errnoWrap(c.clock_getres(clk_id, tp));
}
pub fn setuid(uid: u32) usize {
From db928915878c64f9e5c479739bd768bd4ac0b912 Mon Sep 17 00:00:00 2001
From: Jimmi HC
Date: Sun, 6 Jan 2019 17:48:31 +0100
Subject: [PATCH 07/13] Respect the type system instead of ConstExprValue when
getting field
---
src/ir.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
index 400b07368b..d74bef2424 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -14577,8 +14577,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
return ira->codegen->invalid_instruction;
if (type_is_invalid(struct_val->type))
return ira->codegen->invalid_instruction;
- ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index];
- ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_val->type,
+ ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
is_const, is_volatile, PtrLenSingle, align_bytes,
(uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
(uint32_t)host_int_bytes_for_result_type);
From e410b1f915974fe3daeebae324e8c4e4b42090dd Mon Sep 17 00:00:00 2001
From: Jimmi HC
Date: Sun, 6 Jan 2019 17:49:24 +0100
Subject: [PATCH 08/13] Implemented buf_read_value_bytes for ZigTypeIdArray *
Only for x_array.special == ConstArraySpecialNone
---
src/ir.cpp | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
index d74bef2424..2353bb1086 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -20179,8 +20179,29 @@ static Error buf_read_value_bytes(IrAnalyze *ira, AstNode *source_node, uint8_t
val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn);
return ErrorNone;
}
- case ZigTypeIdArray:
- zig_panic("TODO buf_read_value_bytes array type");
+ case ZigTypeIdArray: {
+ uint64_t elem_size = type_size(ira->codegen, val->type->data.array.child_type);
+ size_t len = val->type->data.array.len;
+
+ switch (val->data.x_array.special) {
+ case ConstArraySpecialNone:
+ val->data.x_array.data.s_none.elements = create_const_vals(len);
+ for (size_t i = 0; i < len; i++) {
+ ConstExprValue *elem = &val->data.x_array.data.s_none.elements[i];
+ elem->special = ConstValSpecialStatic;
+ elem->type = val->type->data.array.child_type;
+ if ((err = buf_read_value_bytes(ira, source_node, buf + (elem_size * i), elem)))
+ return err;
+ }
+ break;
+ case ConstArraySpecialUndef:
+ zig_panic("TODO buf_read_value_bytes ConstArraySpecialUndef array type");
+ case ConstArraySpecialBuf:
+ zig_panic("TODO buf_read_value_bytes ConstArraySpecialBuf array type");
+ }
+
+ return ErrorNone;
+ }
case ZigTypeIdStruct:
switch (val->type->data.structure.layout) {
case ContainerLayoutAuto: {
From 55e95daf543a27961fe9ca7a998d3cbd25d2973b Mon Sep 17 00:00:00 2001
From: Jimmi HC
Date: Sun, 6 Jan 2019 17:53:34 +0100
Subject: [PATCH 09/13] Fixed issue where TypeInfo would use types from a prev
CodeGen instance When doing multible codegen passes (such as building
compiler_rt and then something else) the TypeInfo cache code would point to
types from the prev code gen (such as the prev 'bool' type), giving us errors
like "expected type 'bool', but found type 'bool'" This disabling of caching
might have a performance hit, but correctness is better than speed, so let's
have this for now, until someone optimizes this correctly (probably in
stage2)
---
src/ir.cpp | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
index 2353bb1086..4e401b7249 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -16882,16 +16882,12 @@ static void ensure_field_index(ZigType *type, const char *field_name, size_t ind
static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, ZigType *root) {
Error err;
- static ConstExprValue *type_info_var = nullptr; // TODO oops this global variable made it past code review
- static ZigType *type_info_type = nullptr; // TODO oops this global variable made it past code review
- if (type_info_var == nullptr) {
- type_info_var = get_builtin_value(ira->codegen, "TypeInfo");
- assert(type_info_var->type->id == ZigTypeIdMetaType);
+ ConstExprValue *type_info_var = get_builtin_value(ira->codegen, "TypeInfo"); // TODO oops this global variable made it past code review
+ assert(type_info_var->type->id == ZigTypeIdMetaType);
+ assertNoError(ensure_complete_type(ira->codegen, type_info_var->data.x_type));
- assertNoError(ensure_complete_type(ira->codegen, type_info_var->data.x_type));
- type_info_type = type_info_var->data.x_type;
- assert(type_info_type->id == ZigTypeIdUnion);
- }
+ ZigType *type_info_type = type_info_var->data.x_type; // TODO oops this global variable made it past code review
+ assert(type_info_type->id == ZigTypeIdUnion);
if (type_name == nullptr && root == nullptr)
return type_info_type;
From 97702988d1783db6840c642809a41d8f176bb500 Mon Sep 17 00:00:00 2001
From: Jimmi HC
Date: Sun, 6 Jan 2019 17:58:00 +0100
Subject: [PATCH 10/13] Added test case
---
test/cases/ptrcast.zig | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/test/cases/ptrcast.zig b/test/cases/ptrcast.zig
index 6f0e6e5946..54c3dda849 100644
--- a/test/cases/ptrcast.zig
+++ b/test/cases/ptrcast.zig
@@ -34,3 +34,19 @@ fn testReinterpretBytesAsExternStruct() void {
var val = ptr.c;
assertOrPanic(val == 5);
}
+
+test "reinterpret struct field at comptime" {
+ const numLittle = comptime Bytes.init(0x12345678);
+ assertOrPanic(std.mem.eql(u8, []u8{ 0x78, 0x56, 0x34, 0x12 }, numLittle.bytes));
+}
+
+const Bytes = struct {
+ bytes: [4]u8,
+
+ pub fn init(v: u32) Bytes {
+ var res: Bytes = undefined;
+ @ptrCast(*align(1) u32, &res.bytes).* = v;
+
+ return res;
+ }
+};
From da08525bb31c3608667254132b65e409f5869a03 Mon Sep 17 00:00:00 2001
From: Jimmi HC
Date: Sun, 6 Jan 2019 18:02:00 +0100
Subject: [PATCH 11/13] Removed oops comments
---
src/ir.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
index 4e401b7249..531b705538 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -16882,11 +16882,11 @@ static void ensure_field_index(ZigType *type, const char *field_name, size_t ind
static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, ZigType *root) {
Error err;
- ConstExprValue *type_info_var = get_builtin_value(ira->codegen, "TypeInfo"); // TODO oops this global variable made it past code review
+ ConstExprValue *type_info_var = get_builtin_value(ira->codegen, "TypeInfo");
assert(type_info_var->type->id == ZigTypeIdMetaType);
assertNoError(ensure_complete_type(ira->codegen, type_info_var->data.x_type));
- ZigType *type_info_type = type_info_var->data.x_type; // TODO oops this global variable made it past code review
+ ZigType *type_info_type = type_info_var->data.x_type;
assert(type_info_type->id == ZigTypeIdUnion);
if (type_name == nullptr && root == nullptr)
From aa65b946711d6f51050977880f64a70f13637e45 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 8 Jan 2019 10:57:39 -0500
Subject: [PATCH 12/13] fix debug info for function pointers
found when testing against LLVM 8
see https://bugs.llvm.org/show_bug.cgi?id=40198
---
src/all_types.hpp | 1 +
src/analyze.cpp | 5 ++++-
src/codegen.cpp | 2 +-
3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/all_types.hpp b/src/all_types.hpp
index df318729f5..91b24e3110 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1166,6 +1166,7 @@ struct ZigTypeFn {
FnGenParamInfo *gen_param_info;
LLVMTypeRef raw_type_ref;
+ ZigLLVMDIType *raw_di_type;
ZigType *bound_fn_parent;
};
diff --git a/src/analyze.cpp b/src/analyze.cpp
index b9794114a0..af65838eae 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -1220,7 +1220,10 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref,
gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args);
fn_type->type_ref = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0);
- fn_type->di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0);
+ fn_type->data.fn.raw_di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0);
+ fn_type->di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, fn_type->data.fn.raw_di_type,
+ LLVMStoreSizeOfType(g->target_data_ref, fn_type->type_ref),
+ LLVMABIAlignmentOfType(g->target_data_ref, fn_type->type_ref), "");
}
g->fn_type_table.put(&fn_type->data.fn.fn_type_id, fn_type);
diff --git a/src/codegen.cpp b/src/codegen.cpp
index db8a5f7bb2..0c979386e3 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -649,7 +649,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder,
fn_di_scope, buf_ptr(&fn_table_entry->symbol_name), "",
import->di_file, line_number,
- fn_table_entry->type_entry->di_type, is_internal_linkage,
+ fn_table_entry->type_entry->data.fn.raw_di_type, is_internal_linkage,
is_definition, scope_line, flags, is_optimized, nullptr);
scope->di_scope = ZigLLVMSubprogramToScope(subprogram);
From 4d5d0d3adad09e9ce34d281327c424de6402fcdb Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Tue, 8 Jan 2019 14:40:56 -0500
Subject: [PATCH 13/13] `@typeInfo`: more correct return type info
---
src/ir.cpp | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
index 531b705538..6e6c46885b 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -17100,12 +17100,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
ensure_field_index(fn_def_val->type, "return_type", 7);
fn_def_fields[7].special = ConstValSpecialStatic;
fn_def_fields[7].type = ira->codegen->builtin_types.entry_type;
- if (fn_entry->src_implicit_return_type != nullptr)
- fn_def_fields[7].data.x_type = fn_entry->src_implicit_return_type;
- else if (fn_entry->type_entry->data.fn.gen_return_type != nullptr)
- fn_def_fields[7].data.x_type = fn_entry->type_entry->data.fn.gen_return_type;
- else
- fn_def_fields[7].data.x_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
+ fn_def_fields[7].data.x_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
// arg_names: [][] const u8
ensure_field_index(fn_def_val->type, "arg_names", 8);
size_t fn_arg_count = fn_entry->variable_list.length;