authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-16 13:37:16-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-16 13:37:16-04:00
log558b0b87913dfb6e6b76f5dbe2c36b920302faab
tree40153dfe995f127577db5e277cbec618aff2c30e
parent2255f275a0397ac44a5e8bc907643082fe304336
parentd3ce9d0643421da77063472cb1124123cda753bb

Merge remote-tracking branch 'origin/master' into llvm7


25 files changed, 486 insertions(+), 130 deletions(-)

doc/langref.html.in+6-6
...@@ -2310,11 +2310,11 @@ test "while loop continue expression" {...@@ -2310,11 +2310,11 @@ test "while loop continue expression" {
2310}2310}
23112311
2312test "while loop continue expression, more complicated" {2312test "while loop continue expression, more complicated" {
2313 var i1: usize = 1;2313 var i: usize = 1;
2314 var j1: usize = 1;2314 var j: usize = 1;
2315 while (i1 * j1 < 2000) : ({ i1 *= 2; j1 *= 3; }) {2315 while (i * j < 2000) : ({ i *= 2; j *= 3; }) {
2316 const my_ij1 = i1 * j1;2316 const my_ij = i * j;
2317 assert(my_ij1 < 2000);2317 assert(my_ij < 2000);
2318 }2318 }
2319}2319}
2320 {#code_end#}2320 {#code_end#}
...@@ -5424,7 +5424,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -5424,7 +5424,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
5424 {#header_close#}5424 {#header_close#}
54255425
5426 {#header_open|@IntType#}5426 {#header_open|@IntType#}
5427 <pre><code class="zig">@IntType(comptime is_signed: bool, comptime bit_count: u8) type</code></pre>5427 <pre><code class="zig">@IntType(comptime is_signed: bool, comptime bit_count: u32) type</code></pre>
5428 <p>5428 <p>
5429 This function returns an integer type with the given signness and bit count.5429 This function returns an integer type with the given signness and bit count.
5430 </p>5430 </p>
src-self-hosted/codegen.zig+157-1
...@@ -8,6 +8,7 @@ const ir = @import("ir.zig");...@@ -8,6 +8,7 @@ const ir = @import("ir.zig");
8const Value = @import("value.zig").Value;8const Value = @import("value.zig").Value;
9const Type = @import("type.zig").Type;9const Type = @import("type.zig").Type;
10const event = std.event;10const event = std.event;
11const assert = std.debug.assert;
1112
12pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) !void {13pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) !void {
13 fn_val.base.ref();14 fn_val.base.ref();
...@@ -35,9 +36,23 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)...@@ -35,9 +36,23 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
3536
36 try renderToLlvmModule(&ofile, fn_val, code);37 try renderToLlvmModule(&ofile, fn_val, code);
3738
39 // TODO module level assembly
40 //if (buf_len(&g->global_asm) != 0) {
41 // LLVMSetModuleInlineAsm(g->module, buf_ptr(&g->global_asm));
42 //}
43
44 // TODO
45 //ZigLLVMDIBuilderFinalize(g->dbuilder);
46
38 if (comp.verbose_llvm_ir) {47 if (comp.verbose_llvm_ir) {
39 llvm.DumpModule(ofile.module);48 llvm.DumpModule(ofile.module);
40 }49 }
50
51 // verify the llvm module when safety is on
52 if (std.debug.runtime_safety) {
53 var error_ptr: ?[*]u8 = null;
54 _ = llvm.VerifyModule(ofile.module, llvm.AbortProcessAction, &error_ptr);
55 }
41}56}
4257
43pub const ObjectFile = struct {58pub const ObjectFile = struct {
...@@ -55,5 +70,146 @@ pub const ObjectFile = struct {...@@ -55,5 +70,146 @@ pub const ObjectFile = struct {
55pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code) !void {70pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code) !void {
56 // TODO audit more of codegen.cpp:fn_llvm_value and port more logic71 // TODO audit more of codegen.cpp:fn_llvm_value and port more logic
57 const llvm_fn_type = try fn_val.base.typeof.getLlvmType(ofile);72 const llvm_fn_type = try fn_val.base.typeof.getLlvmType(ofile);
58 const llvm_fn = llvm.AddFunction(ofile.module, fn_val.symbol_name.ptr(), llvm_fn_type);73 const llvm_fn = llvm.AddFunction(
74 ofile.module,
75 fn_val.symbol_name.ptr(),
76 llvm_fn_type,
77 ) orelse return error.OutOfMemory;
78
79 const want_fn_safety = fn_val.block_scope.safety.get(ofile.comp);
80 if (want_fn_safety and ofile.comp.haveLibC()) {
81 try addLLVMFnAttr(ofile, llvm_fn, "sspstrong");
82 try addLLVMFnAttrStr(ofile, llvm_fn, "stack-protector-buffer-size", "4");
83 }
84
85 // TODO
86 //if (fn_val.align_stack) |align_stack| {
87 // try addLLVMFnAttrInt(ofile, llvm_fn, "alignstack", align_stack);
88 //}
89
90 const fn_type = fn_val.base.typeof.cast(Type.Fn).?;
91
92 try addLLVMFnAttr(ofile, llvm_fn, "nounwind");
93 //add_uwtable_attr(g, fn_table_entry->llvm_value);
94 try addLLVMFnAttr(ofile, llvm_fn, "nobuiltin");
95
96 //if (g->build_mode == BuildModeDebug && fn_table_entry->fn_inline != FnInlineAlways) {
97 // ZigLLVMAddFunctionAttr(fn_table_entry->llvm_value, "no-frame-pointer-elim", "true");
98 // ZigLLVMAddFunctionAttr(fn_table_entry->llvm_value, "no-frame-pointer-elim-non-leaf", nullptr);
99 //}
100
101 //if (fn_table_entry->section_name) {
102 // LLVMSetSection(fn_table_entry->llvm_value, buf_ptr(fn_table_entry->section_name));
103 //}
104 //if (fn_table_entry->align_bytes > 0) {
105 // LLVMSetAlignment(fn_table_entry->llvm_value, (unsigned)fn_table_entry->align_bytes);
106 //} else {
107 // // We'd like to set the best alignment for the function here, but on Darwin LLVM gives
108 // // "Cannot getTypeInfo() on a type that is unsized!" assertion failure when calling
109 // // any of the functions for getting alignment. Not specifying the alignment should
110 // // use the ABI alignment, which is fine.
111 //}
112
113 //if (!type_has_bits(return_type)) {
114 // // nothing to do
115 //} else if (type_is_codegen_pointer(return_type)) {
116 // addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
117 //} else if (handle_is_ptr(return_type) &&
118 // calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc))
119 //{
120 // addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
121 // addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");
122 //}
123
124 // TODO set parameter attributes
125
126 // TODO
127 //uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
128 //if (err_ret_trace_arg_index != UINT32_MAX) {
129 // addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull");
130 //}
131
132 const cur_ret_ptr = if (fn_type.return_type.handleIsPtr()) llvm.GetParam(llvm_fn, 0) else null;
133
134 // build all basic blocks
135 for (code.basic_block_list.toSlice()) |bb| {
136 bb.llvm_block = llvm.AppendBasicBlockInContext(
137 ofile.context,
138 llvm_fn,
139 bb.name_hint,
140 ) orelse return error.OutOfMemory;
141 }
142 const entry_bb = code.basic_block_list.at(0);
143 llvm.PositionBuilderAtEnd(ofile.builder, entry_bb.llvm_block);
144
145 llvm.ClearCurrentDebugLocation(ofile.builder);
146
147 // TODO set up error return tracing
148 // TODO allocate temporary stack values
149 // TODO create debug variable declarations for variables and allocate all local variables
150 // TODO finishing error return trace setup. we have to do this after all the allocas.
151 // TODO create debug variable declarations for parameters
152
153 for (code.basic_block_list.toSlice()) |current_block| {
154 llvm.PositionBuilderAtEnd(ofile.builder, current_block.llvm_block);
155 for (current_block.instruction_list.toSlice()) |instruction| {
156 if (instruction.ref_count == 0 and !instruction.hasSideEffects()) continue;
157
158 instruction.llvm_value = try instruction.render(ofile, fn_val);
159 }
160 current_block.llvm_exit_block = llvm.GetInsertBlock(ofile.builder);
161 }
162}
163
164fn addLLVMAttr(
165 ofile: *ObjectFile,
166 val: llvm.ValueRef,
167 attr_index: llvm.AttributeIndex,
168 attr_name: []const u8,
169) !void {
170 const kind_id = llvm.GetEnumAttributeKindForName(attr_name.ptr, attr_name.len);
171 assert(kind_id != 0);
172 const llvm_attr = llvm.CreateEnumAttribute(ofile.context, kind_id, 0) orelse return error.OutOfMemory;
173 llvm.AddAttributeAtIndex(val, attr_index, llvm_attr);
174}
175
176fn addLLVMAttrStr(
177 ofile: *ObjectFile,
178 val: llvm.ValueRef,
179 attr_index: llvm.AttributeIndex,
180 attr_name: []const u8,
181 attr_val: []const u8,
182) !void {
183 const llvm_attr = llvm.CreateStringAttribute(
184 ofile.context,
185 attr_name.ptr,
186 @intCast(c_uint, attr_name.len),
187 attr_val.ptr,
188 @intCast(c_uint, attr_val.len),
189 ) orelse return error.OutOfMemory;
190 llvm.AddAttributeAtIndex(val, attr_index, llvm_attr);
191}
192
193fn addLLVMAttrInt(
194 val: llvm.ValueRef,
195 attr_index: llvm.AttributeIndex,
196 attr_name: []const u8,
197 attr_val: u64,
198) !void {
199 const kind_id = llvm.GetEnumAttributeKindForName(attr_name.ptr, attr_name.len);
200 assert(kind_id != 0);
201 const llvm_attr = llvm.CreateEnumAttribute(ofile.context, kind_id, attr_val) orelse return error.OutOfMemory;
202 llvm.AddAttributeAtIndex(val, attr_index, llvm_attr);
203}
204
205fn addLLVMFnAttr(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8) !void {
206 return addLLVMAttr(ofile, fn_val, @maxValue(llvm.AttributeIndex), attr_name);
207}
208
209fn addLLVMFnAttrStr(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8, attr_val: []const u8) !void {
210 return addLLVMAttrStr(ofile, fn_val, @maxValue(llvm.AttributeIndex), attr_name, attr_val);
211}
212
213fn addLLVMFnAttrInt(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8, attr_val: u64) !void {
214 return addLLVMAttrInt(ofile, fn_val, @maxValue(llvm.AttributeIndex), attr_name, attr_val);
59}215}
src-self-hosted/compilation.zig+5-1
...@@ -606,6 +606,10 @@ pub const Compilation = struct {...@@ -606,6 +606,10 @@ pub const Compilation = struct {
606 return error.Todo;606 return error.Todo;
607 }607 }
608608
609 pub fn haveLibC(self: *Compilation) bool {
610 return self.libc_link_lib != null;
611 }
612
609 pub fn addLinkLib(self: *Compilation, name: []const u8, provided_explicitly: bool) !*LinkLib {613 pub fn addLinkLib(self: *Compilation, name: []const u8, provided_explicitly: bool) !*LinkLib {
610 const is_libc = mem.eql(u8, name, "c");614 const is_libc = mem.eql(u8, name, "c");
611615
...@@ -741,7 +745,7 @@ async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {...@@ -741,7 +745,7 @@ async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
741 analyzed_code.dump();745 analyzed_code.dump();
742 }746 }
743747
744 // Kick off rendering to LLVM comp, but it doesn't block the fn decl748 // Kick off rendering to LLVM module, but it doesn't block the fn decl
745 // analysis from being complete.749 // analysis from being complete.
746 try comp.build_group.call(codegen.renderToLlvm, comp, fn_val, analyzed_code);750 try comp.build_group.call(codegen.renderToLlvm, comp, fn_val, analyzed_code);
747}751}
src-self-hosted/ir.zig+48-8
...@@ -10,6 +10,8 @@ const assert = std.debug.assert;...@@ -10,6 +10,8 @@ const assert = std.debug.assert;
10const Token = std.zig.Token;10const Token = std.zig.Token;
11const ParsedFile = @import("parsed_file.zig").ParsedFile;11const ParsedFile = @import("parsed_file.zig").ParsedFile;
12const Span = @import("errmsg.zig").Span;12const Span = @import("errmsg.zig").Span;
13const llvm = @import("llvm.zig");
14const ObjectFile = @import("codegen.zig").ObjectFile;
1315
14pub const LVal = enum {16pub const LVal = enum {
15 None,17 None,
...@@ -61,6 +63,9 @@ pub const Instruction = struct {...@@ -61,6 +63,9 @@ pub const Instruction = struct {
61 /// the instruction that this one derives from in analysis63 /// the instruction that this one derives from in analysis
62 parent: ?*Instruction,64 parent: ?*Instruction,
6365
66 /// populated durign codegen
67 llvm_value: ?llvm.ValueRef,
68
64 pub fn cast(base: *Instruction, comptime T: type) ?*T {69 pub fn cast(base: *Instruction, comptime T: type) ?*T {
65 if (base.id == comptime typeToId(T)) {70 if (base.id == comptime typeToId(T)) {
66 return @fieldParentPtr(T, "base", base);71 return @fieldParentPtr(T, "base", base);
...@@ -108,14 +113,25 @@ pub const Instruction = struct {...@@ -108,14 +113,25 @@ pub const Instruction = struct {
108 inline while (i < @memberCount(Id)) : (i += 1) {113 inline while (i < @memberCount(Id)) : (i += 1) {
109 if (base.id == @field(Id, @memberName(Id, i))) {114 if (base.id == @field(Id, @memberName(Id, i))) {
110 const T = @field(Instruction, @memberName(Id, i));115 const T = @field(Instruction, @memberName(Id, i));
111 const new_inst = try @fieldParentPtr(T, "base", base).analyze(ira);116 return @fieldParentPtr(T, "base", base).analyze(ira);
112 new_inst.linkToParent(base);
113 return new_inst;
114 }117 }
115 }118 }
116 unreachable;119 unreachable;
117 }120 }
118121
122 pub fn render(base: *Instruction, ofile: *ObjectFile, fn_val: *Value.Fn) (error{OutOfMemory}!?llvm.ValueRef) {
123 switch (base.id) {
124 Id.Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val),
125 Id.Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val),
126 Id.Ref => @panic("TODO"),
127 Id.DeclVar => @panic("TODO"),
128 Id.CheckVoidStmt => @panic("TODO"),
129 Id.Phi => @panic("TODO"),
130 Id.Br => @panic("TODO"),
131 Id.AddImplicitReturnType => @panic("TODO"),
132 }
133 }
134
119 fn getAsParam(param: *Instruction) !*Instruction {135 fn getAsParam(param: *Instruction) !*Instruction {
120 const child = param.child orelse return error.SemanticAnalysisFailed;136 const child = param.child orelse return error.SemanticAnalysisFailed;
121 switch (child.val) {137 switch (child.val) {
...@@ -186,6 +202,10 @@ pub const Instruction = struct {...@@ -186,6 +202,10 @@ pub const Instruction = struct {
186 new_inst.val = IrVal{ .KnownValue = self.base.val.KnownValue.getRef() };202 new_inst.val = IrVal{ .KnownValue = self.base.val.KnownValue.getRef() };
187 return new_inst;203 return new_inst;
188 }204 }
205
206 pub fn render(self: *Const, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef {
207 return self.base.val.KnownValue.getLlvmConst(ofile);
208 }
189 };209 };
190210
191 pub const Return = struct {211 pub const Return = struct {
...@@ -214,6 +234,18 @@ pub const Instruction = struct {...@@ -214,6 +234,18 @@ pub const Instruction = struct {
214234
215 return ira.irb.build(Return, self.base.scope, self.base.span, Params{ .return_value = casted_value });235 return ira.irb.build(Return, self.base.scope, self.base.span, Params{ .return_value = casted_value });
216 }236 }
237
238 pub fn render(self: *Return, ofile: *ObjectFile, fn_val: *Value.Fn) ?llvm.ValueRef {
239 const value = self.params.return_value.llvm_value;
240 const return_type = self.params.return_value.getKnownType();
241
242 if (return_type.handleIsPtr()) {
243 @panic("TODO");
244 } else {
245 _ = llvm.BuildRet(ofile.builder, value);
246 }
247 return null;
248 }
217 };249 };
218250
219 pub const Ref = struct {251 pub const Ref = struct {
...@@ -387,12 +419,16 @@ pub const Variable = struct {...@@ -387,12 +419,16 @@ pub const Variable = struct {
387419
388pub const BasicBlock = struct {420pub const BasicBlock = struct {
389 ref_count: usize,421 ref_count: usize,
390 name_hint: []const u8,422 name_hint: [*]const u8, // must be a C string literal
391 debug_id: usize,423 debug_id: usize,
392 scope: *Scope,424 scope: *Scope,
393 instruction_list: std.ArrayList(*Instruction),425 instruction_list: std.ArrayList(*Instruction),
394 ref_instruction: ?*Instruction,426 ref_instruction: ?*Instruction,
395427
428 /// for codegen
429 llvm_block: llvm.BasicBlockRef,
430 llvm_exit_block: llvm.BasicBlockRef,
431
396 /// the basic block that is derived from this one in analysis432 /// the basic block that is derived from this one in analysis
397 child: ?*BasicBlock,433 child: ?*BasicBlock,
398434
...@@ -426,7 +462,7 @@ pub const Code = struct {...@@ -426,7 +462,7 @@ pub const Code = struct {
426 pub fn dump(self: *Code) void {462 pub fn dump(self: *Code) void {
427 var bb_i: usize = 0;463 var bb_i: usize = 0;
428 for (self.basic_block_list.toSliceConst()) |bb| {464 for (self.basic_block_list.toSliceConst()) |bb| {
429 std.debug.warn("{}_{}:\n", bb.name_hint, bb.debug_id);465 std.debug.warn("{s}_{}:\n", bb.name_hint, bb.debug_id);
430 for (bb.instruction_list.toSliceConst()) |instr| {466 for (bb.instruction_list.toSliceConst()) |instr| {
431 std.debug.warn(" ");467 std.debug.warn(" ");
432 instr.dump();468 instr.dump();
...@@ -475,7 +511,7 @@ pub const Builder = struct {...@@ -475,7 +511,7 @@ pub const Builder = struct {
475 }511 }
476512
477 /// No need to clean up resources thanks to the arena allocator.513 /// No need to clean up resources thanks to the arena allocator.
478 pub fn createBasicBlock(self: *Builder, scope: *Scope, name_hint: []const u8) !*BasicBlock {514 pub fn createBasicBlock(self: *Builder, scope: *Scope, name_hint: [*]const u8) !*BasicBlock {
479 const basic_block = try self.arena().create(BasicBlock{515 const basic_block = try self.arena().create(BasicBlock{
480 .ref_count = 0,516 .ref_count = 0,
481 .name_hint = name_hint,517 .name_hint = name_hint,
...@@ -485,6 +521,8 @@ pub const Builder = struct {...@@ -485,6 +521,8 @@ pub const Builder = struct {
485 .child = null,521 .child = null,
486 .parent = null,522 .parent = null,
487 .ref_instruction = null,523 .ref_instruction = null,
524 .llvm_block = undefined,
525 .llvm_exit_block = undefined,
488 });526 });
489 self.next_debug_id += 1;527 self.next_debug_id += 1;
490 return basic_block;528 return basic_block;
...@@ -600,7 +638,7 @@ pub const Builder = struct {...@@ -600,7 +638,7 @@ pub const Builder = struct {
600 if (block.label) |label| {638 if (block.label) |label| {
601 block_scope.incoming_values = std.ArrayList(*Instruction).init(irb.arena());639 block_scope.incoming_values = std.ArrayList(*Instruction).init(irb.arena());
602 block_scope.incoming_blocks = std.ArrayList(*BasicBlock).init(irb.arena());640 block_scope.incoming_blocks = std.ArrayList(*BasicBlock).init(irb.arena());
603 block_scope.end_block = try irb.createBasicBlock(parent_scope, "BlockEnd");641 block_scope.end_block = try irb.createBasicBlock(parent_scope, c"BlockEnd");
604 block_scope.is_comptime = try irb.buildConstBool(642 block_scope.is_comptime = try irb.buildConstBool(
605 parent_scope,643 parent_scope,
606 Span.token(block.lbrace),644 Span.token(block.lbrace),
...@@ -777,6 +815,7 @@ pub const Builder = struct {...@@ -777,6 +815,7 @@ pub const Builder = struct {
777 .span = span,815 .span = span,
778 .child = null,816 .child = null,
779 .parent = null,817 .parent = null,
818 .llvm_value = undefined,
780 },819 },
781 .params = params,820 .params = params,
782 });821 });
...@@ -968,7 +1007,7 @@ pub async fn gen(...@@ -968,7 +1007,7 @@ pub async fn gen(
968 var irb = try Builder.init(comp, parsed_file);1007 var irb = try Builder.init(comp, parsed_file);
969 errdefer irb.abort();1008 errdefer irb.abort();
9701009
971 const entry_block = try irb.createBasicBlock(scope, "Entry");1010 const entry_block = try irb.createBasicBlock(scope, c"Entry");
972 entry_block.ref(); // Entry block gets a reference because we enter it to begin.1011 entry_block.ref(); // Entry block gets a reference because we enter it to begin.
973 try irb.setCursorAtEndAndAppendBlock(entry_block);1012 try irb.setCursorAtEndAndAppendBlock(entry_block);
9741013
...@@ -1013,6 +1052,7 @@ pub async fn analyze(comp: *Compilation, parsed_file: *ParsedFile, old_code: *Co...@@ -1013,6 +1052,7 @@ pub async fn analyze(comp: *Compilation, parsed_file: *ParsedFile, old_code: *Co
1013 }1052 }
10141053
1015 const return_inst = try old_instruction.analyze(&ira);1054 const return_inst = try old_instruction.analyze(&ira);
1055 return_inst.linkToParent(old_instruction);
1016 // Note: if we ever modify the above to handle error.CompileError by continuing analysis,1056 // Note: if we ever modify the above to handle error.CompileError by continuing analysis,
1017 // then here we want to check if ira.isCompTime() and return early if true1057 // then here we want to check if ira.isCompTime() and return early if true
10181058
src-self-hosted/llvm.zig+63-1
...@@ -2,29 +2,91 @@ const builtin = @import("builtin");...@@ -2,29 +2,91 @@ const builtin = @import("builtin");
2const c = @import("c.zig");2const c = @import("c.zig");
3const assert = @import("std").debug.assert;3const assert = @import("std").debug.assert;
44
5pub const AttributeIndex = c_uint;
6pub const Bool = c_int;
7
5pub const BuilderRef = removeNullability(c.LLVMBuilderRef);8pub const BuilderRef = removeNullability(c.LLVMBuilderRef);
6pub const ContextRef = removeNullability(c.LLVMContextRef);9pub const ContextRef = removeNullability(c.LLVMContextRef);
7pub const ModuleRef = removeNullability(c.LLVMModuleRef);10pub const ModuleRef = removeNullability(c.LLVMModuleRef);
8pub const ValueRef = removeNullability(c.LLVMValueRef);11pub const ValueRef = removeNullability(c.LLVMValueRef);
9pub const TypeRef = removeNullability(c.LLVMTypeRef);12pub const TypeRef = removeNullability(c.LLVMTypeRef);
13pub const BasicBlockRef = removeNullability(c.LLVMBasicBlockRef);
14pub const AttributeRef = removeNullability(c.LLVMAttributeRef);
1015
16pub const AddAttributeAtIndex = c.LLVMAddAttributeAtIndex;
11pub const AddFunction = c.LLVMAddFunction;17pub const AddFunction = c.LLVMAddFunction;
18pub const ClearCurrentDebugLocation = c.ZigLLVMClearCurrentDebugLocation;
19pub const ConstInt = c.LLVMConstInt;
20pub const ConstStringInContext = c.LLVMConstStringInContext;
21pub const ConstStructInContext = c.LLVMConstStructInContext;
12pub const CreateBuilderInContext = c.LLVMCreateBuilderInContext;22pub const CreateBuilderInContext = c.LLVMCreateBuilderInContext;
23pub const CreateEnumAttribute = c.LLVMCreateEnumAttribute;
24pub const CreateStringAttribute = c.LLVMCreateStringAttribute;
13pub const DisposeBuilder = c.LLVMDisposeBuilder;25pub const DisposeBuilder = c.LLVMDisposeBuilder;
14pub const DisposeModule = c.LLVMDisposeModule;26pub const DisposeModule = c.LLVMDisposeModule;
27pub const DoubleTypeInContext = c.LLVMDoubleTypeInContext;
15pub const DumpModule = c.LLVMDumpModule;28pub const DumpModule = c.LLVMDumpModule;
29pub const FP128TypeInContext = c.LLVMFP128TypeInContext;
30pub const FloatTypeInContext = c.LLVMFloatTypeInContext;
31pub const GetEnumAttributeKindForName = c.LLVMGetEnumAttributeKindForName;
32pub const GetMDKindIDInContext = c.LLVMGetMDKindIDInContext;
33pub const HalfTypeInContext = c.LLVMHalfTypeInContext;
34pub const InsertBasicBlockInContext = c.LLVMInsertBasicBlockInContext;
35pub const Int128TypeInContext = c.LLVMInt128TypeInContext;
36pub const Int16TypeInContext = c.LLVMInt16TypeInContext;
37pub const Int1TypeInContext = c.LLVMInt1TypeInContext;
38pub const Int32TypeInContext = c.LLVMInt32TypeInContext;
39pub const Int64TypeInContext = c.LLVMInt64TypeInContext;
40pub const Int8TypeInContext = c.LLVMInt8TypeInContext;
41pub const IntPtrTypeForASInContext = c.LLVMIntPtrTypeForASInContext;
42pub const IntPtrTypeInContext = c.LLVMIntPtrTypeInContext;
43pub const IntTypeInContext = c.LLVMIntTypeInContext;
44pub const LabelTypeInContext = c.LLVMLabelTypeInContext;
45pub const MDNodeInContext = c.LLVMMDNodeInContext;
46pub const MDStringInContext = c.LLVMMDStringInContext;
47pub const MetadataTypeInContext = c.LLVMMetadataTypeInContext;
16pub const ModuleCreateWithNameInContext = c.LLVMModuleCreateWithNameInContext;48pub const ModuleCreateWithNameInContext = c.LLVMModuleCreateWithNameInContext;
49pub const PPCFP128TypeInContext = c.LLVMPPCFP128TypeInContext;
50pub const StructTypeInContext = c.LLVMStructTypeInContext;
51pub const TokenTypeInContext = c.LLVMTokenTypeInContext;
17pub const VoidTypeInContext = c.LLVMVoidTypeInContext;52pub const VoidTypeInContext = c.LLVMVoidTypeInContext;
53pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext;
54pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext;
55pub const ConstAllOnes = c.LLVMConstAllOnes;
56pub const ConstNull = c.LLVMConstNull;
57
58pub const VerifyModule = LLVMVerifyModule;
59extern fn LLVMVerifyModule(M: ModuleRef, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool;
60
61pub const GetInsertBlock = LLVMGetInsertBlock;
62extern fn LLVMGetInsertBlock(Builder: BuilderRef) BasicBlockRef;
1863
19pub const FunctionType = LLVMFunctionType;64pub const FunctionType = LLVMFunctionType;
20extern fn LLVMFunctionType(65extern fn LLVMFunctionType(
21 ReturnType: TypeRef,66 ReturnType: TypeRef,
22 ParamTypes: [*]TypeRef,67 ParamTypes: [*]TypeRef,
23 ParamCount: c_uint,68 ParamCount: c_uint,
24 IsVarArg: c_int,69 IsVarArg: Bool,
25) ?TypeRef;70) ?TypeRef;
2671
72pub const GetParam = LLVMGetParam;
73extern fn LLVMGetParam(Fn: ValueRef, Index: c_uint) ValueRef;
74
75pub const AppendBasicBlockInContext = LLVMAppendBasicBlockInContext;
76extern fn LLVMAppendBasicBlockInContext(C: ContextRef, Fn: ValueRef, Name: [*]const u8) ?BasicBlockRef;
77
78pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd;
79extern fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef) void;
80
81pub const AbortProcessAction = VerifierFailureAction.LLVMAbortProcessAction;
82pub const PrintMessageAction = VerifierFailureAction.LLVMPrintMessageAction;
83pub const ReturnStatusAction = VerifierFailureAction.LLVMReturnStatusAction;
84pub const VerifierFailureAction = c.LLVMVerifierFailureAction;
85
27fn removeNullability(comptime T: type) type {86fn removeNullability(comptime T: type) type {
28 comptime assert(@typeId(T) == builtin.TypeId.Optional);87 comptime assert(@typeId(T) == builtin.TypeId.Optional);
29 return T.Child;88 return T.Child;
30}89}
90
91pub const BuildRet = LLVMBuildRet;
92extern fn LLVMBuildRet(arg0: BuilderRef, V: ?ValueRef) ValueRef;
src-self-hosted/scope.zig+32
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
2const Allocator = mem.Allocator;3const Allocator = mem.Allocator;
3const Decl = @import("decl.zig").Decl;4const Decl = @import("decl.zig").Decl;
4const Compilation = @import("compilation.zig").Compilation;5const Compilation = @import("compilation.zig").Compilation;
...@@ -6,6 +7,7 @@ const mem = std.mem;...@@ -6,6 +7,7 @@ const mem = std.mem;
6const ast = std.zig.ast;7const ast = std.zig.ast;
7const Value = @import("value.zig").Value;8const Value = @import("value.zig").Value;
8const ir = @import("ir.zig");9const ir = @import("ir.zig");
10const Span = @import("errmsg.zig").Span;
911
10pub const Scope = struct {12pub const Scope = struct {
11 id: Id,13 id: Id,
...@@ -93,6 +95,35 @@ pub const Scope = struct {...@@ -93,6 +95,35 @@ pub const Scope = struct {
93 end_block: *ir.BasicBlock,95 end_block: *ir.BasicBlock,
94 is_comptime: *ir.Instruction,96 is_comptime: *ir.Instruction,
9597
98 safety: Safety,
99
100 const Safety = union(enum) {
101 Auto,
102 Manual: Manual,
103
104 const Manual = struct {
105 /// the source span that disabled the safety value
106 span: Span,
107
108 /// whether safety is enabled
109 enabled: bool,
110 };
111
112 fn get(self: Safety, comp: *Compilation) bool {
113 return switch (self) {
114 Safety.Auto => switch (comp.build_mode) {
115 builtin.Mode.Debug,
116 builtin.Mode.ReleaseSafe,
117 => true,
118 builtin.Mode.ReleaseFast,
119 builtin.Mode.ReleaseSmall,
120 => false,
121 },
122 @TagType(Safety).Manual => |man| man.enabled,
123 };
124 }
125 };
126
96 /// Creates a Block scope with 1 reference127 /// Creates a Block scope with 1 reference
97 pub fn create(comp: *Compilation, parent: ?*Scope) !*Block {128 pub fn create(comp: *Compilation, parent: ?*Scope) !*Block {
98 const self = try comp.a().create(Block{129 const self = try comp.a().create(Block{
...@@ -105,6 +136,7 @@ pub const Scope = struct {...@@ -105,6 +136,7 @@ pub const Scope = struct {
105 .incoming_blocks = undefined,136 .incoming_blocks = undefined,
106 .end_block = undefined,137 .end_block = undefined,
107 .is_comptime = undefined,138 .is_comptime = undefined,
139 .safety = Safety.Auto,
108 });140 });
109 errdefer comp.a().destroy(self);141 errdefer comp.a().destroy(self);
110142
src-self-hosted/type.zig+75
...@@ -72,6 +72,81 @@ pub const Type = struct {...@@ -72,6 +72,81 @@ pub const Type = struct {
72 }72 }
73 }73 }
7474
75 pub fn handleIsPtr(base: *Type) bool {
76 switch (base.id) {
77 Id.Type,
78 Id.ComptimeFloat,
79 Id.ComptimeInt,
80 Id.Undefined,
81 Id.Null,
82 Id.Namespace,
83 Id.Block,
84 Id.BoundFn,
85 Id.ArgTuple,
86 Id.Opaque,
87 => unreachable,
88
89 Id.NoReturn,
90 Id.Void,
91 Id.Bool,
92 Id.Int,
93 Id.Float,
94 Id.Pointer,
95 Id.ErrorSet,
96 Id.Enum,
97 Id.Fn,
98 Id.Promise,
99 => return false,
100
101 Id.Struct => @panic("TODO"),
102 Id.Array => @panic("TODO"),
103 Id.Optional => @panic("TODO"),
104 Id.ErrorUnion => @panic("TODO"),
105 Id.Union => @panic("TODO"),
106 }
107 }
108
109 pub fn hasBits(base: *Type) bool {
110 switch (base.id) {
111 Id.Type,
112 Id.ComptimeFloat,
113 Id.ComptimeInt,
114 Id.Undefined,
115 Id.Null,
116 Id.Namespace,
117 Id.Block,
118 Id.BoundFn,
119 Id.ArgTuple,
120 Id.Opaque,
121 => unreachable,
122
123 Id.Void,
124 Id.NoReturn,
125 => return false,
126
127 Id.Bool,
128 Id.Int,
129 Id.Float,
130 Id.Fn,
131 Id.Promise,
132 => return true,
133
134 Id.ErrorSet => @panic("TODO"),
135 Id.Enum => @panic("TODO"),
136 Id.Pointer => @panic("TODO"),
137 Id.Struct => @panic("TODO"),
138 Id.Array => @panic("TODO"),
139 Id.Optional => @panic("TODO"),
140 Id.ErrorUnion => @panic("TODO"),
141 Id.Union => @panic("TODO"),
142 }
143 }
144
145 pub fn cast(base: *Type, comptime T: type) ?*T {
146 if (base.id != @field(Id, @typeName(T))) return null;
147 return @fieldParentPtr(T, "base", base);
148 }
149
75 pub fn dump(base: *const Type) void {150 pub fn dump(base: *const Type) void {
76 std.debug.warn("{}", @tagName(base.id));151 std.debug.warn("{}", @tagName(base.id));
77 }152 }
src-self-hosted/value.zig+22
...@@ -2,6 +2,8 @@ const std = @import("std");...@@ -2,6 +2,8 @@ const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const Scope = @import("scope.zig").Scope;3const Scope = @import("scope.zig").Scope;
4const Compilation = @import("compilation.zig").Compilation;4const Compilation = @import("compilation.zig").Compilation;
5const ObjectFile = @import("codegen.zig").ObjectFile;
6const llvm = @import("llvm.zig");
57
6/// Values are ref-counted, heap-allocated, and copy-on-write8/// Values are ref-counted, heap-allocated, and copy-on-write
7/// If there is only 1 ref then write need not copy9/// If there is only 1 ref then write need not copy
...@@ -39,6 +41,17 @@ pub const Value = struct {...@@ -39,6 +41,17 @@ pub const Value = struct {
39 std.debug.warn("{}", @tagName(base.id));41 std.debug.warn("{}", @tagName(base.id));
40 }42 }
4143
44 pub fn getLlvmConst(base: *Value, ofile: *ObjectFile) (error{OutOfMemory}!?llvm.ValueRef) {
45 switch (base.id) {
46 Id.Type => unreachable,
47 Id.Fn => @panic("TODO"),
48 Id.Void => return null,
49 Id.Bool => return @fieldParentPtr(Bool, "base", base).getLlvmConst(ofile),
50 Id.NoReturn => unreachable,
51 Id.Ptr => @panic("TODO"),
52 }
53 }
54
42 pub const Id = enum {55 pub const Id = enum {
43 Type,56 Type,
44 Fn,57 Fn,
...@@ -123,6 +136,15 @@ pub const Value = struct {...@@ -123,6 +136,15 @@ pub const Value = struct {
123 pub fn destroy(self: *Bool, comp: *Compilation) void {136 pub fn destroy(self: *Bool, comp: *Compilation) void {
124 comp.a().destroy(self);137 comp.a().destroy(self);
125 }138 }
139
140 pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) ?llvm.ValueRef {
141 const llvm_type = llvm.Int1TypeInContext(ofile.context);
142 if (self.x) {
143 return llvm.ConstAllOnes(llvm_type);
144 } else {
145 return llvm.ConstNull(llvm_type);
146 }
147 }
126 };148 };
127149
128 pub const NoReturn = struct {150 pub const NoReturn = struct {
src/all_types.hpp-4
...@@ -1587,7 +1587,6 @@ struct CodeGen {...@@ -1587,7 +1587,6 @@ struct CodeGen {
15871587
1588 struct {1588 struct {
1589 TypeTableEntry *entry_bool;1589 TypeTableEntry *entry_bool;
1590 TypeTableEntry *entry_int[2][12]; // [signed,unsigned][2,3,4,5,6,7,8,16,29,32,64,128]
1591 TypeTableEntry *entry_c_int[CIntTypeCount];1590 TypeTableEntry *entry_c_int[CIntTypeCount];
1592 TypeTableEntry *entry_c_longdouble;1591 TypeTableEntry *entry_c_longdouble;
1593 TypeTableEntry *entry_c_void;1592 TypeTableEntry *entry_c_void;
...@@ -1596,12 +1595,9 @@ struct CodeGen {...@@ -1596,12 +1595,9 @@ struct CodeGen {
1596 TypeTableEntry *entry_u32;1595 TypeTableEntry *entry_u32;
1597 TypeTableEntry *entry_u29;1596 TypeTableEntry *entry_u29;
1598 TypeTableEntry *entry_u64;1597 TypeTableEntry *entry_u64;
1599 TypeTableEntry *entry_u128;
1600 TypeTableEntry *entry_i8;1598 TypeTableEntry *entry_i8;
1601 TypeTableEntry *entry_i16;
1602 TypeTableEntry *entry_i32;1599 TypeTableEntry *entry_i32;
1603 TypeTableEntry *entry_i64;1600 TypeTableEntry *entry_i64;
1604 TypeTableEntry *entry_i128;
1605 TypeTableEntry *entry_isize;1601 TypeTableEntry *entry_isize;
1606 TypeTableEntry *entry_usize;1602 TypeTableEntry *entry_usize;
1607 TypeTableEntry *entry_f16;1603 TypeTableEntry *entry_f16;
src/analyze.cpp+31-42
...@@ -3227,9 +3227,8 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {...@@ -3227,9 +3227,8 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
3227 }3227 }
32283228
3229 {3229 {
3230 auto entry = g->primitive_type_table.maybe_get(tld->name);3230 TypeTableEntry *type = get_primitive_type(g, tld->name);
3231 if (entry) {3231 if (type != nullptr) {
3232 TypeTableEntry *type = entry->value;
3233 add_node_error(g, tld->source_node,3232 add_node_error(g, tld->source_node,
3234 buf_sprintf("declaration shadows type '%s'", buf_ptr(&type->name)));3233 buf_sprintf("declaration shadows type '%s'", buf_ptr(&type->name)));
3235 }3234 }
...@@ -3474,9 +3473,8 @@ VariableTableEntry *add_variable(CodeGen *g, AstNode *source_node, Scope *parent...@@ -3474,9 +3473,8 @@ VariableTableEntry *add_variable(CodeGen *g, AstNode *source_node, Scope *parent
3474 add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));3473 add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
3475 variable_entry->value->type = g->builtin_types.entry_invalid;3474 variable_entry->value->type = g->builtin_types.entry_invalid;
3476 } else {3475 } else {
3477 auto primitive_table_entry = g->primitive_type_table.maybe_get(name);3476 TypeTableEntry *type = get_primitive_type(g, name);
3478 if (primitive_table_entry) {3477 if (type != nullptr) {
3479 TypeTableEntry *type = primitive_table_entry->value;
3480 add_node_error(g, source_node,3478 add_node_error(g, source_node,
3481 buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name)));3479 buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name)));
3482 variable_entry->value->type = g->builtin_types.entry_invalid;3480 variable_entry->value->type = g->builtin_types.entry_invalid;
...@@ -4307,43 +4305,7 @@ void semantic_analyze(CodeGen *g) {...@@ -4307,43 +4305,7 @@ void semantic_analyze(CodeGen *g) {
4307 }4305 }
4308}4306}
43094307
4310TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
4311 size_t index;
4312 if (size_in_bits == 2) {
4313 index = 0;
4314 } else if (size_in_bits == 3) {
4315 index = 1;
4316 } else if (size_in_bits == 4) {
4317 index = 2;
4318 } else if (size_in_bits == 5) {
4319 index = 3;
4320 } else if (size_in_bits == 6) {
4321 index = 4;
4322 } else if (size_in_bits == 7) {
4323 index = 5;
4324 } else if (size_in_bits == 8) {
4325 index = 6;
4326 } else if (size_in_bits == 16) {
4327 index = 7;
4328 } else if (size_in_bits == 29) {
4329 index = 8;
4330 } else if (size_in_bits == 32) {
4331 index = 9;
4332 } else if (size_in_bits == 64) {
4333 index = 10;
4334 } else if (size_in_bits == 128) {
4335 index = 11;
4336 } else {
4337 return nullptr;
4338 }
4339 return &g->builtin_types.entry_int[is_signed ? 0 : 1][index];
4340}
4341
4342TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {4308TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
4343 TypeTableEntry **common_entry = get_int_type_ptr(g, is_signed, size_in_bits);
4344 if (common_entry)
4345 return *common_entry;
4346
4347 TypeId type_id = {};4309 TypeId type_id = {};
4348 type_id.id = TypeTableEntryIdInt;4310 type_id.id = TypeTableEntryIdInt;
4349 type_id.data.integer.is_signed = is_signed;4311 type_id.data.integer.is_signed = is_signed;
...@@ -4953,6 +4915,8 @@ bool fn_eval_cacheable(Scope *scope, TypeTableEntry *return_type) {...@@ -4953,6 +4915,8 @@ bool fn_eval_cacheable(Scope *scope, TypeTableEntry *return_type) {
4953 while (scope) {4915 while (scope) {
4954 if (scope->id == ScopeIdVarDecl) {4916 if (scope->id == ScopeIdVarDecl) {
4955 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;4917 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
4918 if (type_is_invalid(var_scope->var->value->type))
4919 return false;
4956 if (can_mutate_comptime_var_state(var_scope->var->value))4920 if (can_mutate_comptime_var_state(var_scope->var->value))
4957 return false;4921 return false;
4958 } else if (scope->id == ScopeIdFnDef) {4922 } else if (scope->id == ScopeIdFnDef) {
...@@ -6310,3 +6274,28 @@ bool type_can_fail(TypeTableEntry *type_entry) {...@@ -6310,3 +6274,28 @@ bool type_can_fail(TypeTableEntry *type_entry) {
6310bool fn_type_can_fail(FnTypeId *fn_type_id) {6274bool fn_type_can_fail(FnTypeId *fn_type_id) {
6311 return type_can_fail(fn_type_id->return_type) || fn_type_id->cc == CallingConventionAsync;6275 return type_can_fail(fn_type_id->return_type) || fn_type_id->cc == CallingConventionAsync;
6312}6276}
6277
6278TypeTableEntry *get_primitive_type(CodeGen *g, Buf *name) {
6279 if (buf_len(name) >= 2) {
6280 uint8_t first_c = buf_ptr(name)[0];
6281 if (first_c == 'i' || first_c == 'u') {
6282 for (size_t i = 1; i < buf_len(name); i += 1) {
6283 uint8_t c = buf_ptr(name)[i];
6284 if (c < '0' || c > '9') {
6285 goto not_integer;
6286 }
6287 }
6288 bool is_signed = (first_c == 'i');
6289 uint32_t bit_count = atoi(buf_ptr(name) + 1);
6290 return get_int_type(g, is_signed, bit_count);
6291 }
6292 }
6293
6294not_integer:
6295
6296 auto primitive_table_entry = g->primitive_type_table.maybe_get(name);
6297 if (primitive_table_entry != nullptr) {
6298 return primitive_table_entry->value;
6299 }
6300 return nullptr;
6301}
src/analyze.hpp+2-1
...@@ -19,7 +19,6 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type...@@ -19,7 +19,6 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type
19 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count);19 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count);
20uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry);20uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry);
21uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry);21uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry);
22TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, uint32_t size_in_bits);
23TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);22TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
24TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);23TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
25TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type);24TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type);
...@@ -204,4 +203,6 @@ bool type_can_fail(TypeTableEntry *type_entry);...@@ -204,4 +203,6 @@ bool type_can_fail(TypeTableEntry *type_entry);
204bool fn_eval_cacheable(Scope *scope, TypeTableEntry *return_type);203bool fn_eval_cacheable(Scope *scope, TypeTableEntry *return_type);
205AstNode *type_decl_node(TypeTableEntry *type_entry);204AstNode *type_decl_node(TypeTableEntry *type_entry);
206205
206TypeTableEntry *get_primitive_type(CodeGen *g, Buf *name);
207
207#endif208#endif
src/codegen.cpp-28
...@@ -5973,21 +5973,6 @@ static void do_code_gen(CodeGen *g) {...@@ -5973,21 +5973,6 @@ static void do_code_gen(CodeGen *g) {
5973 }5973 }
5974}5974}
59755975
5976static const uint8_t int_sizes_in_bits[] = {
5977 2,
5978 3,
5979 4,
5980 5,
5981 6,
5982 7,
5983 8,
5984 16,
5985 29,
5986 32,
5987 64,
5988 128,
5989};
5990
5991struct CIntTypeInfo {5976struct CIntTypeInfo {
5992 CIntType id;5977 CIntType id;
5993 const char *name;5978 const char *name;
...@@ -6072,16 +6057,6 @@ static void define_builtin_types(CodeGen *g) {...@@ -6072,16 +6057,6 @@ static void define_builtin_types(CodeGen *g) {
6072 g->builtin_types.entry_arg_tuple = entry;6057 g->builtin_types.entry_arg_tuple = entry;
6073 }6058 }
60746059
6075 for (size_t int_size_i = 0; int_size_i < array_length(int_sizes_in_bits); int_size_i += 1) {
6076 uint8_t size_in_bits = int_sizes_in_bits[int_size_i];
6077 for (size_t is_sign_i = 0; is_sign_i < array_length(is_signed_list); is_sign_i += 1) {
6078 bool is_signed = is_signed_list[is_sign_i];
6079 TypeTableEntry *entry = make_int_type(g, is_signed, size_in_bits);
6080 g->primitive_type_table.put(&entry->name, entry);
6081 get_int_type_ptr(g, is_signed, size_in_bits)[0] = entry;
6082 }
6083 }
6084
6085 for (size_t i = 0; i < array_length(c_int_type_infos); i += 1) {6060 for (size_t i = 0; i < array_length(c_int_type_infos); i += 1) {
6086 const CIntTypeInfo *info = &c_int_type_infos[i];6061 const CIntTypeInfo *info = &c_int_type_infos[i];
6087 uint32_t size_in_bits = target_c_type_size_in_bits(&g->zig_target, info->id);6062 uint32_t size_in_bits = target_c_type_size_in_bits(&g->zig_target, info->id);
...@@ -6197,12 +6172,9 @@ static void define_builtin_types(CodeGen *g) {...@@ -6197,12 +6172,9 @@ static void define_builtin_types(CodeGen *g) {
6197 g->builtin_types.entry_u29 = get_int_type(g, false, 29);6172 g->builtin_types.entry_u29 = get_int_type(g, false, 29);
6198 g->builtin_types.entry_u32 = get_int_type(g, false, 32);6173 g->builtin_types.entry_u32 = get_int_type(g, false, 32);
6199 g->builtin_types.entry_u64 = get_int_type(g, false, 64);6174 g->builtin_types.entry_u64 = get_int_type(g, false, 64);
6200 g->builtin_types.entry_u128 = get_int_type(g, false, 128);
6201 g->builtin_types.entry_i8 = get_int_type(g, true, 8);6175 g->builtin_types.entry_i8 = get_int_type(g, true, 8);
6202 g->builtin_types.entry_i16 = get_int_type(g, true, 16);
6203 g->builtin_types.entry_i32 = get_int_type(g, true, 32);6176 g->builtin_types.entry_i32 = get_int_type(g, true, 32);
6204 g->builtin_types.entry_i64 = get_int_type(g, true, 64);6177 g->builtin_types.entry_i64 = get_int_type(g, true, 64);
6205 g->builtin_types.entry_i128 = get_int_type(g, true, 128);
62066178
6207 {6179 {
6208 g->builtin_types.entry_c_void = get_opaque_type(g, nullptr, nullptr, "c_void");6180 g->builtin_types.entry_c_void = get_opaque_type(g, nullptr, nullptr, "c_void");
src/ir.cpp+12-9
...@@ -3217,9 +3217,8 @@ static VariableTableEntry *create_local_var(CodeGen *codegen, AstNode *node, Sco...@@ -3217,9 +3217,8 @@ static VariableTableEntry *create_local_var(CodeGen *codegen, AstNode *node, Sco
3217 add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));3217 add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
3218 variable_entry->value->type = codegen->builtin_types.entry_invalid;3218 variable_entry->value->type = codegen->builtin_types.entry_invalid;
3219 } else {3219 } else {
3220 auto primitive_table_entry = codegen->primitive_type_table.maybe_get(name);3220 TypeTableEntry *type = get_primitive_type(codegen, name);
3221 if (primitive_table_entry) {3221 if (type != nullptr) {
3222 TypeTableEntry *type = primitive_table_entry->value;
3223 add_node_error(codegen, node,3222 add_node_error(codegen, node,
3224 buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name)));3223 buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name)));
3225 variable_entry->value->type = codegen->builtin_types.entry_invalid;3224 variable_entry->value->type = codegen->builtin_types.entry_invalid;
...@@ -3661,9 +3660,9 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3661,9 +3660,9 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
3661 return &const_instruction->base;3660 return &const_instruction->base;
3662 }3661 }
36633662
3664 auto primitive_table_entry = irb->codegen->primitive_type_table.maybe_get(variable_name);3663 TypeTableEntry *primitive_type = get_primitive_type(irb->codegen, variable_name);
3665 if (primitive_table_entry) {3664 if (primitive_type != nullptr) {
3666 IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_table_entry->value);3665 IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_type);
3667 if (lval == LValPtr) {3666 if (lval == LValPtr) {
3668 return ir_build_ref(irb, scope, node, value, false, false);3667 return ir_build_ref(irb, scope, node, value, false, false);
3669 } else {3668 } else {
...@@ -10691,11 +10690,11 @@ static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out...@@ -10691,11 +10690,11 @@ static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out
10691 return true;10690 return true;
10692}10691}
1069310692
10694static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) {10693static bool ir_resolve_unsigned(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *int_type, uint64_t *out) {
10695 if (type_is_invalid(value->value.type))10694 if (type_is_invalid(value->value.type))
10696 return false;10695 return false;
1069710696
10698 IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->codegen->builtin_types.entry_usize);10697 IrInstruction *casted_value = ir_implicit_cast(ira, value, int_type);
10699 if (type_is_invalid(casted_value->value.type))10698 if (type_is_invalid(casted_value->value.type))
10700 return false;10699 return false;
1070110700
...@@ -10707,6 +10706,10 @@ static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out...@@ -10707,6 +10706,10 @@ static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out
10707 return true;10706 return true;
10708}10707}
1070910708
10709static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) {
10710 return ir_resolve_unsigned(ira, value, ira->codegen->builtin_types.entry_usize, out);
10711}
10712
10710static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *value, bool *out) {10713static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *value, bool *out) {
10711 if (type_is_invalid(value->value.type))10714 if (type_is_invalid(value->value.type))
10712 return false;10715 return false;
...@@ -18025,7 +18028,7 @@ static TypeTableEntry *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstruc...@@ -18025,7 +18028,7 @@ static TypeTableEntry *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstruc
1802518028
18026 IrInstruction *bit_count_value = instruction->bit_count->other;18029 IrInstruction *bit_count_value = instruction->bit_count->other;
18027 uint64_t bit_count;18030 uint64_t bit_count;
18028 if (!ir_resolve_usize(ira, bit_count_value, &bit_count))18031 if (!ir_resolve_unsigned(ira, bit_count_value, ira->codegen->builtin_types.entry_u32, &bit_count))
18029 return ira->codegen->builtin_types.entry_invalid;18032 return ira->codegen->builtin_types.entry_invalid;
1803018033
18031 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);18034 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
src/translate_c.cpp+1-1
...@@ -427,7 +427,7 @@ static AstNode *get_global(Context *c, Buf *name) {...@@ -427,7 +427,7 @@ static AstNode *get_global(Context *c, Buf *name) {
427 if (entry)427 if (entry)
428 return entry->value;428 return entry->value;
429 }429 }
430 if (c->codegen->primitive_type_table.maybe_get(name) != nullptr) {430 if (get_primitive_type(c->codegen, name) != nullptr) {
431 return trans_create_node_symbol(c, name);431 return trans_create_node_symbol(c, name);
432 }432 }
433 return nullptr;433 return nullptr;
std/buffer.zig-2
...@@ -5,8 +5,6 @@ const Allocator = mem.Allocator;...@@ -5,8 +5,6 @@ const Allocator = mem.Allocator;
5const assert = debug.assert;5const assert = debug.assert;
6const ArrayList = std.ArrayList;6const ArrayList = std.ArrayList;
77
8const fmt = std.fmt;
9
10/// A buffer that allocates memory and maintains a null byte at the end.8/// A buffer that allocates memory and maintains a null byte at the end.
11pub const Buffer = struct {9pub const Buffer = struct {
12 list: ArrayList(u8),10 list: ArrayList(u8),
std/crypto/sha1.zig-2
...@@ -4,8 +4,6 @@ const endian = @import("../endian.zig");...@@ -4,8 +4,6 @@ const endian = @import("../endian.zig");
4const debug = @import("../debug/index.zig");4const debug = @import("../debug/index.zig");
5const builtin = @import("builtin");5const builtin = @import("builtin");
66
7pub const u160 = @IntType(false, 160);
8
9const RoundParam = struct {7const RoundParam = struct {
10 a: usize,8 a: usize,
11 b: usize,9 b: usize,
std/event/future.zig+10
...@@ -40,6 +40,16 @@ pub fn Future(comptime T: type) type {...@@ -40,6 +40,16 @@ pub fn Future(comptime T: type) type {
40 return &self.data;40 return &self.data;
41 }41 }
4242
43 /// Gets the data without waiting for it. If it's available, a pointer is
44 /// returned. Otherwise, null is returned.
45 pub fn getOrNull(self: *Self) ?*T {
46 if (@atomicLoad(u8, &self.available, AtomicOrder.SeqCst) == 1) {
47 return &self.data;
48 } else {
49 return null;
50 }
51 }
52
43 /// Make the data become available. May be called only once.53 /// Make the data become available. May be called only once.
44 /// Before calling this, modify the `data` property.54 /// Before calling this, modify the `data` property.
45 pub fn resolve(self: *Self) void {55 pub fn resolve(self: *Self) void {
std/json.zig-3
...@@ -6,9 +6,6 @@ const std = @import("index.zig");...@@ -6,9 +6,6 @@ const std = @import("index.zig");
6const debug = std.debug;6const debug = std.debug;
7const mem = std.mem;7const mem = std.mem;
88
9const u1 = @IntType(false, 1);
10const u256 = @IntType(false, 256);
11
12// A single token slice into the parent string.9// A single token slice into the parent string.
13//10//
14// Use `token.slice()` on the input at the current position to get the current slice.11// Use `token.slice()` on the input at the current position to get the current slice.
std/math/big/int.zig-1
...@@ -996,7 +996,6 @@ pub const Int = struct {...@@ -996,7 +996,6 @@ pub const Int = struct {
996// They will still run on larger than this and should pass, but the multi-limb code-paths996// They will still run on larger than this and should pass, but the multi-limb code-paths
997// may be untested in some cases.997// may be untested in some cases.
998998
999const u256 = @IntType(false, 256);
1000const al = debug.global_allocator;999const al = debug.global_allocator;
10011000
1002test "big.int comptime_int set" {1001test "big.int comptime_int set" {
std/math/exp2.zig+12-12
...@@ -75,18 +75,18 @@ fn exp2_32(x: f32) f32 {...@@ -75,18 +75,18 @@ fn exp2_32(x: f32) f32 {
75 }75 }
7676
77 var uf = x + redux;77 var uf = x + redux;
78 var i0 = @bitCast(u32, uf);78 var i_0 = @bitCast(u32, uf);
79 i0 += tblsiz / 2;79 i_0 += tblsiz / 2;
8080
81 const k = i0 / tblsiz;81 const k = i_0 / tblsiz;
82 // NOTE: musl relies on undefined overflow shift behaviour. Appears that this produces the82 // NOTE: musl relies on undefined overflow shift behaviour. Appears that this produces the
83 // intended result but should confirm how GCC/Clang handle this to ensure.83 // intended result but should confirm how GCC/Clang handle this to ensure.
84 const uk = @bitCast(f64, u64(0x3FF + k) << 52);84 const uk = @bitCast(f64, u64(0x3FF + k) << 52);
85 i0 &= tblsiz - 1;85 i_0 &= tblsiz - 1;
86 uf -= redux;86 uf -= redux;
8787
88 const z: f64 = x - uf;88 const z: f64 = x - uf;
89 var r: f64 = exp2ft[i0];89 var r: f64 = exp2ft[i_0];
90 const t: f64 = r * z;90 const t: f64 = r * z;
91 r = r + t * (P1 + z * P2) + t * (z * z) * (P3 + z * P4);91 r = r + t * (P1 + z * P2) + t * (z * z) * (P3 + z * P4);
92 return @floatCast(f32, r * uk);92 return @floatCast(f32, r * uk);
...@@ -401,18 +401,18 @@ fn exp2_64(x: f64) f64 {...@@ -401,18 +401,18 @@ fn exp2_64(x: f64) f64 {
401 // reduce x401 // reduce x
402 var uf = x + redux;402 var uf = x + redux;
403 // NOTE: musl performs an implicit 64-bit to 32-bit u32 truncation here403 // NOTE: musl performs an implicit 64-bit to 32-bit u32 truncation here
404 var i0 = @truncate(u32, @bitCast(u64, uf));404 var i_0 = @truncate(u32, @bitCast(u64, uf));
405 i0 += tblsiz / 2;405 i_0 += tblsiz / 2;
406406
407 const k: u32 = i0 / tblsiz * tblsiz;407 const k: u32 = i_0 / tblsiz * tblsiz;
408 const ik = @bitCast(i32, k / tblsiz);408 const ik = @bitCast(i32, k / tblsiz);
409 i0 %= tblsiz;409 i_0 %= tblsiz;
410 uf -= redux;410 uf -= redux;
411411
412 // r = exp2(y) = exp2t[i0] * p(z - eps[i])412 // r = exp2(y) = exp2t[i_0] * p(z - eps[i])
413 var z = x - uf;413 var z = x - uf;
414 const t = exp2dt[2 * i0];414 const t = exp2dt[2 * i_0];
415 z -= exp2dt[2 * i0 + 1];415 z -= exp2dt[2 * i_0 + 1];
416 const r = t + t * z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * P5))));416 const r = t + t * z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * P5))));
417417
418 return math.scalbn(r, ik);418 return math.scalbn(r, ik);
std/math/index.zig+1-1
...@@ -354,7 +354,7 @@ test "math.rotl" {...@@ -354,7 +354,7 @@ test "math.rotl" {
354354
355pub fn Log2Int(comptime T: type) type {355pub fn Log2Int(comptime T: type) type {
356 // comptime ceil log2356 // comptime ceil log2
357 comptime var count: usize = 0;357 comptime var count = 0;
358 comptime var s = T.bit_count - 1;358 comptime var s = T.bit_count - 1;
359 inline while (s != 0) : (s >>= 1) {359 inline while (s != 0) : (s >>= 1) {
360 count += 1;360 count += 1;
std/os/time.zig-1
...@@ -25,7 +25,6 @@ pub fn sleep(seconds: usize, nanoseconds: usize) void {...@@ -25,7 +25,6 @@ pub fn sleep(seconds: usize, nanoseconds: usize) void {
25 }25 }
26}26}
2727
28const u63 = @IntType(false, 63);
29pub fn posixSleep(seconds: u63, nanoseconds: u63) void {28pub fn posixSleep(seconds: u63, nanoseconds: u63) void {
30 var req = posix.timespec{29 var req = posix.timespec{
31 .tv_sec = seconds,30 .tv_sec = seconds,
test/cases/misc.zig-5
...@@ -58,11 +58,6 @@ test "floating point primitive bit counts" {...@@ -58,11 +58,6 @@ test "floating point primitive bit counts" {
58 assert(f64.bit_count == 64);58 assert(f64.bit_count == 64);
59}59}
6060
61const u1 = @IntType(false, 1);
62const u63 = @IntType(false, 63);
63const i1 = @IntType(true, 1);
64const i63 = @IntType(true, 63);
65
66test "@minValue and @maxValue" {61test "@minValue and @maxValue" {
67 assert(@maxValue(u1) == 1);62 assert(@maxValue(u1) == 1);
68 assert(@maxValue(u8) == 255);63 assert(@maxValue(u8) == 255);
test/cases/struct.zig-1
...@@ -240,7 +240,6 @@ fn getC(data: *const BitField1) u2 {...@@ -240,7 +240,6 @@ fn getC(data: *const BitField1) u2 {
240 return data.c;240 return data.c;
241}241}
242242
243const u24 = @IntType(false, 24);
244const Foo24Bits = packed struct {243const Foo24Bits = packed struct {
245 field: u24,244 field: u24,
246};245};
test/compile_errors.zig+9
...@@ -1,6 +1,15 @@...@@ -1,6 +1,15 @@
1const tests = @import("tests.zig");1const tests = @import("tests.zig");
22
3pub fn addCases(cases: *tests.CompileErrorContext) void {3pub fn addCases(cases: *tests.CompileErrorContext) void {
4 cases.add(
5 "optional pointer to void in extern struct",
6 \\comptime {
7 \\ _ = @IntType(false, @maxValue(u32) + 1);
8 \\}
9 ,
10 ".tmp_source.zig:2:40: error: integer value 4294967296 cannot be implicitly casted to type 'u32'",
11 );
12
4 cases.add(13 cases.add(
5 "optional pointer to void in extern struct",14 "optional pointer to void in extern struct",
6 \\const Foo = extern struct {15 \\const Foo = extern struct {