authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-11 22:26:55-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-11 22:26:55-05:00
logeb3726c502e92ec4a3689732a76479c6d561cff5
tree91f14deeaffd5e475c11be3ec8572b66a3799b37
parentd1d3dbc7b5bc986849db476e491300ffd18d4db5
parent3268276b58d8b65cb295b738d7c14174005bd84e

Merge branch 'master' into llvm6


11 files changed, 156 insertions(+), 20 deletions(-)

CMakeLists.txt+1
...@@ -425,6 +425,7 @@ set(ZIG_STD_FILES...@@ -425,6 +425,7 @@ set(ZIG_STD_FILES
425 "math/tan.zig"425 "math/tan.zig"
426 "math/tanh.zig"426 "math/tanh.zig"
427 "math/trunc.zig"427 "math/trunc.zig"
428 "math/x86_64/sqrt.zig"
428 "mem.zig"429 "mem.zig"
429 "net.zig"430 "net.zig"
430 "os/child_process.zig"431 "os/child_process.zig"
src/all_types.hpp+1
...@@ -1421,6 +1421,7 @@ struct CodeGen {...@@ -1421,6 +1421,7 @@ struct CodeGen {
1421 HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;1421 HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;
1422 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names;1422 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names;
1423 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;1423 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
1424 HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table;
14241425
14251426
1426 ZigList<ImportTableEntry *> import_queue;1427 ZigList<ImportTableEntry *> import_queue;
src/analyze.cpp+8
...@@ -4370,6 +4370,12 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {...@@ -4370,6 +4370,12 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {
4370}4370}
43714371
4372void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {4372void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
4373 auto entry = g->string_literals_table.maybe_get(str);
4374 if (entry != nullptr) {
4375 *const_val = *entry->value;
4376 return;
4377 }
4378
4373 const_val->special = ConstValSpecialStatic;4379 const_val->special = ConstValSpecialStatic;
4374 const_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str));4380 const_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str));
4375 const_val->data.x_array.s_none.elements = create_const_vals(buf_len(str));4381 const_val->data.x_array.s_none.elements = create_const_vals(buf_len(str));
...@@ -4380,6 +4386,8 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {...@@ -4380,6 +4386,8 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
4380 this_char->type = g->builtin_types.entry_u8;4386 this_char->type = g->builtin_types.entry_u8;
4381 bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(str)[i]);4387 bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(str)[i]);
4382 }4388 }
4389
4390 g->string_literals_table.put(str, const_val);
4383}4391}
43844392
4385ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str) {4393ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str) {
src/buffer.cpp+4-1
...@@ -67,9 +67,12 @@ bool buf_eql_buf(Buf *buf, Buf *other) {...@@ -67,9 +67,12 @@ bool buf_eql_buf(Buf *buf, Buf *other) {
6767
68uint32_t buf_hash(Buf *buf) {68uint32_t buf_hash(Buf *buf) {
69 assert(buf->list.length);69 assert(buf->list.length);
70 size_t interval = buf->list.length / 256;
71 if (interval == 0)
72 interval = 1;
70 // FNV 32-bit hash73 // FNV 32-bit hash
71 uint32_t h = 2166136261;74 uint32_t h = 2166136261;
72 for (size_t i = 0; i < buf_len(buf); i += 1) {75 for (size_t i = 0; i < buf_len(buf); i += interval) {
73 h = h ^ ((uint8_t)buf->list.at(i));76 h = h ^ ((uint8_t)buf->list.at(i));
74 h = h * 16777619;77 h = h * 16777619;
75 }78 }
src/codegen.cpp+1
...@@ -87,6 +87,7 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out...@@ -87,6 +87,7 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
87 g->memoized_fn_eval_table.init(16);87 g->memoized_fn_eval_table.init(16);
88 g->exported_symbol_names.init(8);88 g->exported_symbol_names.init(8);
89 g->external_prototypes.init(8);89 g->external_prototypes.init(8);
90 g->string_literals_table.init(16);
90 g->is_test_build = false;91 g->is_test_build = false;
91 g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib);92 g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib);
92 buf_resize(&g->global_asm, 0);93 buf_resize(&g->global_asm, 0);
src/ir.cpp+4-4
...@@ -13224,9 +13224,9 @@ static TypeTableEntry *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstr...@@ -13224,9 +13224,9 @@ static TypeTableEntry *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstr
13224 os_path_resolve(&source_dir_path, rel_file_path, &file_path);13224 os_path_resolve(&source_dir_path, rel_file_path, &file_path);
1322513225
13226 // load from file system into const expr13226 // load from file system into const expr
13227 Buf file_contents = BUF_INIT;13227 Buf *file_contents = buf_alloc();
13228 int err;13228 int err;
13229 if ((err = os_fetch_file_path(&file_path, &file_contents))) {13229 if ((err = os_fetch_file_path(&file_path, file_contents))) {
13230 if (err == ErrorFileNotFound) {13230 if (err == ErrorFileNotFound) {
13231 ir_add_error(ira, instruction->name, buf_sprintf("unable to find '%s'", buf_ptr(&file_path)));13231 ir_add_error(ira, instruction->name, buf_sprintf("unable to find '%s'", buf_ptr(&file_path)));
13232 return ira->codegen->builtin_types.entry_invalid;13232 return ira->codegen->builtin_types.entry_invalid;
...@@ -13240,9 +13240,9 @@ static TypeTableEntry *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstr...@@ -13240,9 +13240,9 @@ static TypeTableEntry *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstr
13240 // we'll have to invalidate the cache13240 // we'll have to invalidate the cache
1324113241
13242 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);13242 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
13243 init_const_str_lit(ira->codegen, out_val, &file_contents);13243 init_const_str_lit(ira->codegen, out_val, file_contents);
1324413244
13245 return get_array_type(ira->codegen, ira->codegen->builtin_types.entry_u8, buf_len(&file_contents));13245 return get_array_type(ira->codegen, ira->codegen->builtin_types.entry_u8, buf_len(file_contents));
13246}13246}
1324713247
13248static TypeTableEntry *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchg *instruction) {13248static TypeTableEntry *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchg *instruction) {
std/endian.zig+8-3
...@@ -2,11 +2,11 @@ const mem = @import("mem.zig");...@@ -2,11 +2,11 @@ const mem = @import("mem.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4pub fn swapIfLe(comptime T: type, x: T) -> T {4pub fn swapIfLe(comptime T: type, x: T) -> T {
5 return swapIf(false, T, x);5 return swapIf(builtin.Endian.Little, T, x);
6}6}
77
8pub fn swapIfBe(comptime T: type, x: T) -> T {8pub fn swapIfBe(comptime T: type, x: T) -> T {
9 return swapIf(true, T, x);9 return swapIf(builtin.Endian.Big, T, x);
10}10}
1111
12pub fn swapIf(endian: builtin.Endian, comptime T: type, x: T) -> T {12pub fn swapIf(endian: builtin.Endian, comptime T: type, x: T) -> T {
...@@ -15,6 +15,11 @@ pub fn swapIf(endian: builtin.Endian, comptime T: type, x: T) -> T {...@@ -15,6 +15,11 @@ pub fn swapIf(endian: builtin.Endian, comptime T: type, x: T) -> T {
1515
16pub fn swap(comptime T: type, x: T) -> T {16pub fn swap(comptime T: type, x: T) -> T {
17 var buf: [@sizeOf(T)]u8 = undefined;17 var buf: [@sizeOf(T)]u8 = undefined;
18 mem.writeInt(buf[0..], x, false);18 mem.writeInt(buf[0..], x, builtin.Endian.Little);
19 return mem.readInt(buf, T, builtin.Endian.Big);19 return mem.readInt(buf, T, builtin.Endian.Big);
20}20}
21
22test "swap" {
23 const debug = @import("debug/index.zig");
24 debug.assert(swap(u32, 0xDEADBEEF) == 0xEFBEADDE);
25}
std/linked_list.zig+87-8
...@@ -4,8 +4,18 @@ const assert = debug.assert;...@@ -4,8 +4,18 @@ const assert = debug.assert;
4const mem = std.mem;4const mem = std.mem;
5const Allocator = mem.Allocator;5const Allocator = mem.Allocator;
66
7/// Generic doubly linked list.7/// Generic non-intrusive doubly linked list.
8pub fn LinkedList(comptime T: type) -> type {8pub fn LinkedList(comptime T: type) -> type {
9 return BaseLinkedList(T, void, "");
10}
11
12/// Generic intrusive doubly linked list.
13pub fn IntrusiveLinkedList(comptime ParentType: type, comptime field_name: []const u8) -> type {
14 return BaseLinkedList(void, ParentType, field_name);
15}
16
17/// Generic doubly linked list.
18fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_name: []const u8) -> type {
9 return struct {19 return struct {
10 const Self = this;20 const Self = this;
1121
...@@ -15,13 +25,23 @@ pub fn LinkedList(comptime T: type) -> type {...@@ -15,13 +25,23 @@ pub fn LinkedList(comptime T: type) -> type {
15 next: ?&Node,25 next: ?&Node,
16 data: T,26 data: T,
1727
18 pub fn init(data: &const T) -> Node {28 pub fn init(value: &const T) -> Node {
19 return Node {29 return Node {
20 .prev = null,30 .prev = null,
21 .next = null,31 .next = null,
22 .data = *data,32 .data = *value,
23 };33 };
24 }34 }
35
36 pub fn initIntrusive() -> Node {
37 // TODO: when #678 is solved this can become `init`.
38 return Node.init({});
39 }
40
41 pub fn toData(node: &Node) -> &ParentType {
42 comptime assert(isIntrusive());
43 return @fieldParentPtr(ParentType, field_name, node);
44 }
25 };45 };
2646
27 first: ?&Node,47 first: ?&Node,
...@@ -40,6 +60,10 @@ pub fn LinkedList(comptime T: type) -> type {...@@ -40,6 +60,10 @@ pub fn LinkedList(comptime T: type) -> type {
40 };60 };
41 }61 }
4262
63 fn isIntrusive() -> bool {
64 return ParentType != void or field_name.len != 0;
65 }
66
43 /// Insert a new node after an existing one.67 /// Insert a new node after an existing one.
44 ///68 ///
45 /// Arguments:69 /// Arguments:
...@@ -167,6 +191,7 @@ pub fn LinkedList(comptime T: type) -> type {...@@ -167,6 +191,7 @@ pub fn LinkedList(comptime T: type) -> type {
167 /// Returns:191 /// Returns:
168 /// A pointer to the new node.192 /// A pointer to the new node.
169 pub fn allocateNode(list: &Self, allocator: &Allocator) -> %&Node {193 pub fn allocateNode(list: &Self, allocator: &Allocator) -> %&Node {
194 comptime assert(!isIntrusive());
170 return allocator.create(Node);195 return allocator.create(Node);
171 }196 }
172197
...@@ -176,6 +201,7 @@ pub fn LinkedList(comptime T: type) -> type {...@@ -176,6 +201,7 @@ pub fn LinkedList(comptime T: type) -> type {
176 /// node: Pointer to the node to deallocate.201 /// node: Pointer to the node to deallocate.
177 /// allocator: Dynamic memory allocator.202 /// allocator: Dynamic memory allocator.
178 pub fn destroyNode(list: &Self, node: &Node, allocator: &Allocator) {203 pub fn destroyNode(list: &Self, node: &Node, allocator: &Allocator) {
204 comptime assert(!isIntrusive());
179 allocator.destroy(node);205 allocator.destroy(node);
180 }206 }
181207
...@@ -188,6 +214,7 @@ pub fn LinkedList(comptime T: type) -> type {...@@ -188,6 +214,7 @@ pub fn LinkedList(comptime T: type) -> type {
188 /// Returns:214 /// Returns:
189 /// A pointer to the new node.215 /// A pointer to the new node.
190 pub fn createNode(list: &Self, data: &const T, allocator: &Allocator) -> %&Node {216 pub fn createNode(list: &Self, data: &const T, allocator: &Allocator) -> %&Node {
217 comptime assert(!isIntrusive());
191 var node = try list.allocateNode(allocator);218 var node = try list.allocateNode(allocator);
192 *node = Node.init(data);219 *node = Node.init(data);
193 return node;220 return node;
...@@ -199,11 +226,11 @@ test "basic linked list test" {...@@ -199,11 +226,11 @@ test "basic linked list test" {
199 const allocator = debug.global_allocator;226 const allocator = debug.global_allocator;
200 var list = LinkedList(u32).init();227 var list = LinkedList(u32).init();
201228
202 var one = list.createNode(1, allocator) catch unreachable;229 var one = try list.createNode(1, allocator);
203 var two = list.createNode(2, allocator) catch unreachable;230 var two = try list.createNode(2, allocator);
204 var three = list.createNode(3, allocator) catch unreachable;231 var three = try list.createNode(3, allocator);
205 var four = list.createNode(4, allocator) catch unreachable;232 var four = try list.createNode(4, allocator);
206 var five = list.createNode(5, allocator) catch unreachable;233 var five = try list.createNode(5, allocator);
207 defer {234 defer {
208 list.destroyNode(one, allocator);235 list.destroyNode(one, allocator);
209 list.destroyNode(two, allocator);236 list.destroyNode(two, allocator);
...@@ -246,3 +273,55 @@ test "basic linked list test" {...@@ -246,3 +273,55 @@ test "basic linked list test" {
246 assert ((??list.last ).data == 4);273 assert ((??list.last ).data == 4);
247 assert (list.len == 2);274 assert (list.len == 2);
248}275}
276
277const link = "link";
278const ElementList = IntrusiveLinkedList(Element, link);
279const Element = struct {
280 value: u32,
281 link: IntrusiveLinkedList(Element, link).Node,
282};
283
284test "basic intrusive linked list test" {
285 const allocator = debug.global_allocator;
286 var list = ElementList.init();
287
288 var one = Element { .value = 1, .link = ElementList.Node.initIntrusive() };
289 var two = Element { .value = 2, .link = ElementList.Node.initIntrusive() };
290 var three = Element { .value = 3, .link = ElementList.Node.initIntrusive() };
291 var four = Element { .value = 4, .link = ElementList.Node.initIntrusive() };
292 var five = Element { .value = 5, .link = ElementList.Node.initIntrusive() };
293
294 list.append(&two.link); // {2}
295 list.append(&five.link); // {2, 5}
296 list.prepend(&one.link); // {1, 2, 5}
297 list.insertBefore(&five.link, &four.link); // {1, 2, 4, 5}
298 list.insertAfter(&two.link, &three.link); // {1, 2, 3, 4, 5}
299
300 // Traverse forwards.
301 {
302 var it = list.first;
303 var index: u32 = 1;
304 while (it) |node| : (it = node.next) {
305 assert(node.toData().value == index);
306 index += 1;
307 }
308 }
309
310 // Traverse backwards.
311 {
312 var it = list.last;
313 var index: u32 = 1;
314 while (it) |node| : (it = node.prev) {
315 assert(node.toData().value == (6 - index));
316 index += 1;
317 }
318 }
319
320 var first = list.popFirst(); // {2, 3, 4, 5}
321 var last = list.pop(); // {2, 3, 4}
322 list.remove(&three.link); // {2, 4}
323
324 assert ((??list.first).toData().value == 2);
325 assert ((??list.last ).toData().value == 4);
326 assert (list.len == 2);
327}
std/math/sqrt.zig+14-4
...@@ -18,11 +18,21 @@ pub fn sqrt(x: var) -> (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @...@@ -18,11 +18,21 @@ pub fn sqrt(x: var) -> (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @
18 return T(sqrt64(x));18 return T(sqrt64(x));
19 },19 },
20 TypeId.Float => {20 TypeId.Float => {
21 return switch (T) {21 switch (T) {
22 f32 => sqrt32(x),22 f32 => {
23 f64 => sqrt64(x),23 switch (builtin.arch) {
24 builtin.Arch.x86_64 => return @import("x86_64/sqrt.zig").sqrt32(x),
25 else => return sqrt32(x),
26 }
27 },
28 f64 => {
29 switch (builtin.arch) {
30 builtin.Arch.x86_64 => return @import("x86_64/sqrt.zig").sqrt64(x),
31 else => return sqrt64(x),
32 }
33 },
24 else => @compileError("sqrt not implemented for " ++ @typeName(T)),34 else => @compileError("sqrt not implemented for " ++ @typeName(T)),
25 };35 }
26 },36 },
27 TypeId.IntLiteral => comptime {37 TypeId.IntLiteral => comptime {
28 if (x > @maxValue(u128)) {38 if (x > @maxValue(u128)) {
std/math/x86_64/sqrt.zig created+15
...@@ -0,0 +1,15 @@
1pub fn sqrt32(x: f32) -> f32 {
2 return asm (
3 \\sqrtss %%xmm0, %%xmm0
4 : [ret] "={xmm0}" (-> f32)
5 : [x] "{xmm0}" (x)
6 );
7}
8
9pub fn sqrt64(x: f64) -> f64 {
10 return asm (
11 \\sqrtsd %%xmm0, %%xmm0
12 : [ret] "={xmm0}" (-> f64)
13 : [x] "{xmm0}" (x)
14 );
15}
test/cases/eval.zig+13
...@@ -375,3 +375,16 @@ test "f128 at compile time is lossy" {...@@ -375,3 +375,16 @@ test "f128 at compile time is lossy" {
375375
376// TODO need a better implementation of bigfloat_init_bigint376// TODO need a better implementation of bigfloat_init_bigint
377// assert(f128(1 << 113) == 10384593717069655257060992658440192);377// assert(f128(1 << 113) == 10384593717069655257060992658440192);
378
379pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) -> type {
380 return struct {
381 pub const Node = struct { };
382 };
383}
384
385test "string literal used as comptime slice is memoized" {
386 const a = "link";
387 const b = "link";
388 comptime assert(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
389 comptime assert(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
390}