| author | |
| committer | |
| log | 558b0b87913dfb6e6b76f5dbe2c36b920302faab |
| tree | 40153dfe995f127577db5e277cbec618aff2c30e |
| parent | 2255f275a0397ac44a5e8bc907643082fe304336 |
| parent | d3ce9d0643421da77063472cb1124123cda753bb |
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 | } |
| 2311 | 2311 | ||
| 2312 | test "while loop continue expression, more complicated" { | 2312 | test "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#} |
| 5425 | 5425 | ||
| 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"); |
| 8 | const Value = @import("value.zig").Value; | 8 | const Value = @import("value.zig").Value; |
| 9 | const Type = @import("type.zig").Type; | 9 | const Type = @import("type.zig").Type; |
| 10 | const event = std.event; | 10 | const event = std.event; |
| 11 | const assert = std.debug.assert; | ||
| 11 | 12 | ||
| 12 | pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) !void { | 13 | pub 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) |
| 35 | 36 | ||
| 36 | try renderToLlvmModule(&ofile, fn_val, code); | 37 | try renderToLlvmModule(&ofile, fn_val, code); |
| 37 | 38 | ||
| 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 | } |
| 42 | 57 | ||
| 43 | pub const ObjectFile = struct { | 58 | pub const ObjectFile = struct { |
| ... | @@ -55,5 +70,146 @@ pub const ObjectFile = struct { | ... | @@ -55,5 +70,146 @@ pub const ObjectFile = struct { |
| 55 | pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code) !void { | 70 | pub 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 logic | 71 | // 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 | |||
| 164 | fn 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 | |||
| 176 | fn 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 | |||
| 193 | fn 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 | |||
| 205 | fn 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 | |||
| 209 | fn 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 | |||
| 213 | fn 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 | } |
| 608 | 608 | ||
| 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"); |
| 611 | 615 | ||
| ... | @@ -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 | } |
| 743 | 747 | ||
| 744 | // Kick off rendering to LLVM comp, but it doesn't block the fn decl | 748 | // 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; |
| 10 | const Token = std.zig.Token; | 10 | const Token = std.zig.Token; |
| 11 | const ParsedFile = @import("parsed_file.zig").ParsedFile; | 11 | const ParsedFile = @import("parsed_file.zig").ParsedFile; |
| 12 | const Span = @import("errmsg.zig").Span; | 12 | const Span = @import("errmsg.zig").Span; |
| 13 | const llvm = @import("llvm.zig"); | ||
| 14 | const ObjectFile = @import("codegen.zig").ObjectFile; | ||
| 13 | 15 | ||
| 14 | pub const LVal = enum { | 16 | pub 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 analysis | 63 | /// the instruction that this one derives from in analysis |
| 62 | parent: ?*Instruction, | 64 | parent: ?*Instruction, |
| 63 | 65 | ||
| 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 | } |
| 118 | 121 | ||
| 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 | }; |
| 190 | 210 | ||
| 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 { |
| 214 | 234 | ||
| 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 | }; |
| 218 | 250 | ||
| 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 { |
| 387 | 419 | ||
| 388 | pub const BasicBlock = struct { | 420 | pub 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, |
| 395 | 427 | ||
| 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 analysis | 432 | /// the basic block that is derived from this one in analysis |
| 397 | child: ?*BasicBlock, | 433 | child: ?*BasicBlock, |
| 398 | 434 | ||
| ... | @@ -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 | } |
| 476 | 512 | ||
| 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(); |
| 970 | 1009 | ||
| 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); |
| 974 | 1013 | ||
| ... | @@ -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 | } |
| 1014 | 1053 | ||
| 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 true | 1057 | // then here we want to check if ira.isCompTime() and return early if true |
| 1018 | 1058 |
src-self-hosted/llvm.zig+63-1| ... | @@ -2,29 +2,91 @@ const builtin = @import("builtin"); | ... | @@ -2,29 +2,91 @@ const builtin = @import("builtin"); |
| 2 | const c = @import("c.zig"); | 2 | const c = @import("c.zig"); |
| 3 | const assert = @import("std").debug.assert; | 3 | const assert = @import("std").debug.assert; |
| 4 | 4 | ||
| 5 | pub const AttributeIndex = c_uint; | ||
| 6 | pub const Bool = c_int; | ||
| 7 | |||
| 5 | pub const BuilderRef = removeNullability(c.LLVMBuilderRef); | 8 | pub const BuilderRef = removeNullability(c.LLVMBuilderRef); |
| 6 | pub const ContextRef = removeNullability(c.LLVMContextRef); | 9 | pub const ContextRef = removeNullability(c.LLVMContextRef); |
| 7 | pub const ModuleRef = removeNullability(c.LLVMModuleRef); | 10 | pub const ModuleRef = removeNullability(c.LLVMModuleRef); |
| 8 | pub const ValueRef = removeNullability(c.LLVMValueRef); | 11 | pub const ValueRef = removeNullability(c.LLVMValueRef); |
| 9 | pub const TypeRef = removeNullability(c.LLVMTypeRef); | 12 | pub const TypeRef = removeNullability(c.LLVMTypeRef); |
| 13 | pub const BasicBlockRef = removeNullability(c.LLVMBasicBlockRef); | ||
| 14 | pub const AttributeRef = removeNullability(c.LLVMAttributeRef); | ||
| 10 | 15 | ||
| 16 | pub const AddAttributeAtIndex = c.LLVMAddAttributeAtIndex; | ||
| 11 | pub const AddFunction = c.LLVMAddFunction; | 17 | pub const AddFunction = c.LLVMAddFunction; |
| 18 | pub const ClearCurrentDebugLocation = c.ZigLLVMClearCurrentDebugLocation; | ||
| 19 | pub const ConstInt = c.LLVMConstInt; | ||
| 20 | pub const ConstStringInContext = c.LLVMConstStringInContext; | ||
| 21 | pub const ConstStructInContext = c.LLVMConstStructInContext; | ||
| 12 | pub const CreateBuilderInContext = c.LLVMCreateBuilderInContext; | 22 | pub const CreateBuilderInContext = c.LLVMCreateBuilderInContext; |
| 23 | pub const CreateEnumAttribute = c.LLVMCreateEnumAttribute; | ||
| 24 | pub const CreateStringAttribute = c.LLVMCreateStringAttribute; | ||
| 13 | pub const DisposeBuilder = c.LLVMDisposeBuilder; | 25 | pub const DisposeBuilder = c.LLVMDisposeBuilder; |
| 14 | pub const DisposeModule = c.LLVMDisposeModule; | 26 | pub const DisposeModule = c.LLVMDisposeModule; |
| 27 | pub const DoubleTypeInContext = c.LLVMDoubleTypeInContext; | ||
| 15 | pub const DumpModule = c.LLVMDumpModule; | 28 | pub const DumpModule = c.LLVMDumpModule; |
| 29 | pub const FP128TypeInContext = c.LLVMFP128TypeInContext; | ||
| 30 | pub const FloatTypeInContext = c.LLVMFloatTypeInContext; | ||
| 31 | pub const GetEnumAttributeKindForName = c.LLVMGetEnumAttributeKindForName; | ||
| 32 | pub const GetMDKindIDInContext = c.LLVMGetMDKindIDInContext; | ||
| 33 | pub const HalfTypeInContext = c.LLVMHalfTypeInContext; | ||
| 34 | pub const InsertBasicBlockInContext = c.LLVMInsertBasicBlockInContext; | ||
| 35 | pub const Int128TypeInContext = c.LLVMInt128TypeInContext; | ||
| 36 | pub const Int16TypeInContext = c.LLVMInt16TypeInContext; | ||
| 37 | pub const Int1TypeInContext = c.LLVMInt1TypeInContext; | ||
| 38 | pub const Int32TypeInContext = c.LLVMInt32TypeInContext; | ||
| 39 | pub const Int64TypeInContext = c.LLVMInt64TypeInContext; | ||
| 40 | pub const Int8TypeInContext = c.LLVMInt8TypeInContext; | ||
| 41 | pub const IntPtrTypeForASInContext = c.LLVMIntPtrTypeForASInContext; | ||
| 42 | pub const IntPtrTypeInContext = c.LLVMIntPtrTypeInContext; | ||
| 43 | pub const IntTypeInContext = c.LLVMIntTypeInContext; | ||
| 44 | pub const LabelTypeInContext = c.LLVMLabelTypeInContext; | ||
| 45 | pub const MDNodeInContext = c.LLVMMDNodeInContext; | ||
| 46 | pub const MDStringInContext = c.LLVMMDStringInContext; | ||
| 47 | pub const MetadataTypeInContext = c.LLVMMetadataTypeInContext; | ||
| 16 | pub const ModuleCreateWithNameInContext = c.LLVMModuleCreateWithNameInContext; | 48 | pub const ModuleCreateWithNameInContext = c.LLVMModuleCreateWithNameInContext; |
| 49 | pub const PPCFP128TypeInContext = c.LLVMPPCFP128TypeInContext; | ||
| 50 | pub const StructTypeInContext = c.LLVMStructTypeInContext; | ||
| 51 | pub const TokenTypeInContext = c.LLVMTokenTypeInContext; | ||
| 17 | pub const VoidTypeInContext = c.LLVMVoidTypeInContext; | 52 | pub const VoidTypeInContext = c.LLVMVoidTypeInContext; |
| 53 | pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext; | ||
| 54 | pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext; | ||
| 55 | pub const ConstAllOnes = c.LLVMConstAllOnes; | ||
| 56 | pub const ConstNull = c.LLVMConstNull; | ||
| 57 | |||
| 58 | pub const VerifyModule = LLVMVerifyModule; | ||
| 59 | extern fn LLVMVerifyModule(M: ModuleRef, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool; | ||
| 60 | |||
| 61 | pub const GetInsertBlock = LLVMGetInsertBlock; | ||
| 62 | extern fn LLVMGetInsertBlock(Builder: BuilderRef) BasicBlockRef; | ||
| 18 | 63 | ||
| 19 | pub const FunctionType = LLVMFunctionType; | 64 | pub const FunctionType = LLVMFunctionType; |
| 20 | extern fn LLVMFunctionType( | 65 | extern 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; |
| 26 | 71 | ||
| 72 | pub const GetParam = LLVMGetParam; | ||
| 73 | extern fn LLVMGetParam(Fn: ValueRef, Index: c_uint) ValueRef; | ||
| 74 | |||
| 75 | pub const AppendBasicBlockInContext = LLVMAppendBasicBlockInContext; | ||
| 76 | extern fn LLVMAppendBasicBlockInContext(C: ContextRef, Fn: ValueRef, Name: [*]const u8) ?BasicBlockRef; | ||
| 77 | |||
| 78 | pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd; | ||
| 79 | extern fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef) void; | ||
| 80 | |||
| 81 | pub const AbortProcessAction = VerifierFailureAction.LLVMAbortProcessAction; | ||
| 82 | pub const PrintMessageAction = VerifierFailureAction.LLVMPrintMessageAction; | ||
| 83 | pub const ReturnStatusAction = VerifierFailureAction.LLVMReturnStatusAction; | ||
| 84 | pub const VerifierFailureAction = c.LLVMVerifierFailureAction; | ||
| 85 | |||
| 27 | fn removeNullability(comptime T: type) type { | 86 | fn 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 | |||
| 91 | pub const BuildRet = LLVMBuildRet; | ||
| 92 | extern fn LLVMBuildRet(arg0: BuilderRef, V: ?ValueRef) ValueRef; |
src-self-hosted/scope.zig+32| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | ||
| 2 | const Allocator = mem.Allocator; | 3 | const Allocator = mem.Allocator; |
| 3 | const Decl = @import("decl.zig").Decl; | 4 | const Decl = @import("decl.zig").Decl; |
| 4 | const Compilation = @import("compilation.zig").Compilation; | 5 | const Compilation = @import("compilation.zig").Compilation; |
| ... | @@ -6,6 +7,7 @@ const mem = std.mem; | ... | @@ -6,6 +7,7 @@ const mem = std.mem; |
| 6 | const ast = std.zig.ast; | 7 | const ast = std.zig.ast; |
| 7 | const Value = @import("value.zig").Value; | 8 | const Value = @import("value.zig").Value; |
| 8 | const ir = @import("ir.zig"); | 9 | const ir = @import("ir.zig"); |
| 10 | const Span = @import("errmsg.zig").Span; | ||
| 9 | 11 | ||
| 10 | pub const Scope = struct { | 12 | pub 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, |
| 95 | 97 | ||
| 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 reference | 127 | /// 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); |
| 110 | 142 |
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 | } |
| 74 | 74 | ||
| 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"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const Scope = @import("scope.zig").Scope; | 3 | const Scope = @import("scope.zig").Scope; |
| 4 | const Compilation = @import("compilation.zig").Compilation; | 4 | const Compilation = @import("compilation.zig").Compilation; |
| 5 | const ObjectFile = @import("codegen.zig").ObjectFile; | ||
| 6 | const llvm = @import("llvm.zig"); | ||
| 5 | 7 | ||
| 6 | /// Values are ref-counted, heap-allocated, and copy-on-write | 8 | /// Values are ref-counted, heap-allocated, and copy-on-write |
| 7 | /// If there is only 1 ref then write need not copy | 9 | /// 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 | } |
| 41 | 43 | ||
| 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 | }; |
| 127 | 149 | ||
| 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 { |
| 1587 | 1587 | ||
| 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 | } |
| 3228 | 3228 | ||
| 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 | } |
| 4309 | 4307 | ||
| 4310 | TypeTableEntry **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 | |||
| 4342 | TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) { | 4308 | TypeTableEntry *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) { |
| 6310 | bool fn_type_can_fail(FnTypeId *fn_type_id) { | 6274 | bool 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 | |||
| 6278 | TypeTableEntry *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 | |||
| 6294 | not_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); |
| 20 | uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry); | 20 | uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry); |
| 21 | uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry); | 21 | uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry); |
| 22 | TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, uint32_t size_in_bits); | ||
| 23 | TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); | 22 | TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); |
| 24 | TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type); | 23 | TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type); |
| 25 | TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type); | 24 | TypeTableEntry *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); |
| 204 | bool fn_eval_cacheable(Scope *scope, TypeTableEntry *return_type); | 203 | bool fn_eval_cacheable(Scope *scope, TypeTableEntry *return_type); |
| 205 | AstNode *type_decl_node(TypeTableEntry *type_entry); | 204 | AstNode *type_decl_node(TypeTableEntry *type_entry); |
| 206 | 205 | ||
| 206 | TypeTableEntry *get_primitive_type(CodeGen *g, Buf *name); | ||
| 207 | |||
| 207 | #endif | 208 | #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 | } |
| 5975 | 5975 | ||
| 5976 | static 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 | |||
| 5991 | struct CIntTypeInfo { | 5976 | struct 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 | } |
| 6074 | 6059 | ||
| 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); | ||
| 6206 | 6178 | ||
| 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 | } |
| 3663 | 3662 | ||
| 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 | } |
| 10693 | 10692 | ||
| 10694 | static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) { | 10693 | static 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; |
| 10697 | 10696 | ||
| 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; |
| 10701 | 10700 | ||
| ... | @@ -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 | } |
| 10709 | 10708 | ||
| 10709 | static 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 | |||
| 10710 | static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *value, bool *out) { | 10713 | static 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 |
| 18025 | 18028 | ||
| 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; |
| 18030 | 18033 | ||
| 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; |
| 5 | const assert = debug.assert; | 5 | const assert = debug.assert; |
| 6 | const ArrayList = std.ArrayList; | 6 | const ArrayList = std.ArrayList; |
| 7 | 7 | ||
| 8 | const 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. |
| 11 | pub const Buffer = struct { | 9 | pub 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"); |
| 4 | const debug = @import("../debug/index.zig"); | 4 | const debug = @import("../debug/index.zig"); |
| 5 | const builtin = @import("builtin"); | 5 | const builtin = @import("builtin"); |
| 6 | 6 | ||
| 7 | pub const u160 = @IntType(false, 160); | ||
| 8 | |||
| 9 | const RoundParam = struct { | 7 | const 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 | } |
| 42 | 42 | ||
| 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"); |
| 6 | const debug = std.debug; | 6 | const debug = std.debug; |
| 7 | const mem = std.mem; | 7 | const mem = std.mem; |
| 8 | 8 | ||
| 9 | const u1 = @IntType(false, 1); | ||
| 10 | const 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-paths | 996 | // 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. |
| 998 | 998 | ||
| 999 | const u256 = @IntType(false, 256); | ||
| 1000 | const al = debug.global_allocator; | 999 | const al = debug.global_allocator; |
| 1001 | 1000 | ||
| 1002 | test "big.int comptime_int set" { | 1001 | test "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 | } |
| 76 | 76 | ||
| 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; |
| 80 | 80 | ||
| 81 | const k = i0 / tblsiz; | 81 | const k = i_0 / tblsiz; |
| 82 | // NOTE: musl relies on undefined overflow shift behaviour. Appears that this produces the | 82 | // 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; |
| 87 | 87 | ||
| 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 x | 401 | // 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 here | 403 | // 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; |
| 406 | 406 | ||
| 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; |
| 411 | 411 | ||
| 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)))); |
| 417 | 417 | ||
| 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" { |
| 354 | 354 | ||
| 355 | pub fn Log2Int(comptime T: type) type { | 355 | pub fn Log2Int(comptime T: type) type { |
| 356 | // comptime ceil log2 | 356 | // 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 | } |
| 27 | 27 | ||
| 28 | const u63 = @IntType(false, 63); | ||
| 29 | pub fn posixSleep(seconds: u63, nanoseconds: u63) void { | 28 | pub 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 | } |
| 60 | 60 | ||
| 61 | const u1 = @IntType(false, 1); | ||
| 62 | const u63 = @IntType(false, 63); | ||
| 63 | const i1 = @IntType(true, 1); | ||
| 64 | const i63 = @IntType(true, 63); | ||
| 65 | |||
| 66 | test "@minValue and @maxValue" { | 61 | test "@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 | } |
| 242 | 242 | ||
| 243 | const u24 = @IntType(false, 24); | ||
| 244 | const Foo24Bits = packed struct { | 243 | const Foo24Bits = packed struct { |
| 245 | field: u24, | 244 | field: u24, |
| 246 | }; | 245 | }; |
test/compile_errors.zig+9| ... | @@ -1,6 +1,15 @@ | ... | @@ -1,6 +1,15 @@ |
| 1 | const tests = @import("tests.zig"); | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | ||
| 3 | pub fn addCases(cases: *tests.CompileErrorContext) void { | 3 | pub 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 { |