authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-15 02:20:42-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-02-15 02:20:42-05:00
log567c9b688effdb64e3995df09af4b45105515c2c
tree11bc01aa7484d427455a12502710b0ee286fb6aa
parentee5e196f8832359cfe05808677f143d4f460f6bc
parent99b19adeb31469cbc4a906f036bb4d70d8730916
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #1965 from ziglang/c-pointer-type

implement C pointers

37 files changed, 1308 insertions(+), 447 deletions(-)

doc/docgen.zig+1
......@@ -916,6 +916,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
916916 std.zig.Token.Id.AngleBracketAngleBracketRightEqual,
917917 std.zig.Token.Id.Tilde,
918918 std.zig.Token.Id.BracketStarBracket,
919 std.zig.Token.Id.BracketStarCBracket,
919920 => try writeEscaped(out, src[token.start..token.end]),
920921
921922 std.zig.Token.Id.Invalid => return parseError(
doc/langref.html.in+62-5
......@@ -1694,7 +1694,7 @@ test "comptime @intToPtr" {
16941694 }
16951695}
16961696 {#code_end#}
1697 {#see_also|Optional Pointers#}
1697 {#see_also|Optional Pointers|@intToPtr|@ptrToInt#}
16981698 {#header_open|volatile#}
16991699 <p>Loads and stores are assumed to not have side effects. If a given load or store
17001700 should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}.
......@@ -1823,7 +1823,9 @@ fn foo(bytes: []u8) u32 {
18231823}
18241824 {#code_end#}
18251825 {#header_close#}
1826 {#see_also|C Pointers#}
18261827 {#header_close#}
1828
18271829 {#header_open|Slices#}
18281830 {#code_begin|test_safety|index out of bounds#}
18291831const assert = @import("std").debug.assert;
......@@ -3981,7 +3983,7 @@ test "implicit cast - invoke a type as a function" {
39813983 {#code_end#}
39823984 <p>
39833985 Implicit casts are only allowed when it is completely unambiguous how to get from one type to another,
3984 and the transformation is guaranteed to be safe.
3986 and the transformation is guaranteed to be safe. There is one exception, which is {#link|C Pointers#}.
39853987 </p>
39863988 {#header_open|Implicit Cast: Stricter Qualification#}
39873989 <p>
......@@ -6104,6 +6106,10 @@ test "call foo" {
61046106 <p>
61056107 Converts a pointer of one type to a pointer of another type.
61066108 </p>
6109 <p>
6110 {#link|Optional Pointers#} are allowed. Casting an optional pointer which is {#link|null#}
6111 to a non-optional pointer invokes safety-checked {#link|Undefined Behavior#}.
6112 </p>
61076113 {#header_close#}
61086114
61096115 {#header_open|@ptrToInt#}
......@@ -7345,10 +7351,27 @@ fn bar(f: *Foo) void {
73457351 {#code_end#}
73467352 {#header_close#}
73477353
7348 {#header_open|Out of Bounds Float To Integer Cast#}
7354 {#header_open|Out of Bounds Float to Integer Cast#}
73497355 <p>TODO</p>
73507356 {#header_close#}
73517357
7358 {#header_open|Pointer Cast Invalid Null#}
7359 <p>At compile-time:</p>
7360 {#code_begin|test_err|null pointer casted to type#}
7361comptime {
7362 const opt_ptr: ?*i32 = null;
7363 const ptr = @ptrCast(*i32, opt_ptr);
7364}
7365 {#code_end#}
7366 <p>At runtime:</p>
7367 {#code_begin|exe_err#}
7368pub fn main() void {
7369 var opt_ptr: ?*i32 = null;
7370 var ptr = @ptrCast(*i32, opt_ptr);
7371}
7372 {#code_end#}
7373 {#header_close#}
7374
73527375 {#header_close#}
73537376 {#header_open|Memory#}
73547377 <p>TODO: explain no default allocator in zig</p>
......@@ -7439,6 +7462,7 @@ pub fn main() void {
74397462 {#code_end#}
74407463 {#see_also|String Literals#}
74417464 {#header_close#}
7465
74427466 {#header_open|Import from C Header File#}
74437467 <p>
74447468 The {#syntax#}@cImport{#endsyntax#} builtin function can be used
......@@ -7477,6 +7501,36 @@ const c = @cImport({
74777501 {#code_end#}
74787502 {#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#}
74797503 {#header_close#}
7504
7505 {#header_open|C Pointers#}
7506 <p>
7507 This type is to be avoided whenever possible. The only valid reason for using a C pointer is in
7508 auto-generated code from translating C code.
7509 </p>
7510 <p>
7511 When importing C header files, it is ambiguous whether pointers should be translated as
7512 single-item pointers ({#syntax#}*T{#endsyntax#}) or unknown-length pointers ({#syntax#}[*]T{#endsyntax#}).
7513 C pointers are a compromise so that Zig code can utilize translated header files directly.
7514 </p>
7515 <p>{#syntax#}[*c]T{#endsyntax#} - C pointer.</p>
7516 <ul>
7517 <li>Supports all the syntax of the other two pointer types.</li>
7518 <li>Implicitly casts to other pointer types, as well as {#link|Optional Pointers#}.
7519 When a C pointer is implicitly casted to a non-optional pointer, safety-checked
7520 {#link|Undefined Behavior#} occurs if the address is 0.
7521 </li>
7522 <li>Allows address 0. On non-freestanding targets, dereferencing address 0 is safety-checked
7523 {#link|Undefined Behavior#}. Optional C pointers introduce another bit to keep track of
7524 null, just like {#syntax#}?usize{#endsyntax#}. Note that creating an optional C pointer
7525 is unnecessary as one can use normal {#link|Optional Pointers#}.
7526 </li>
7527 <li>Supports {#link|implicit casting|Implicit Casts#} to and from integers.</li>
7528 <li>Supports comparison with integers.</li>
7529 <li>Does not support Zig-only pointer attributes such as alignment. Use normal {#link|Pointers#}
7530 please!</li>
7531 </ul>
7532 {#header_close#}
7533
74807534 {#header_open|Exporting a C Library#}
74817535 <p>
74827536 One of the primary use cases for Zig is exporting a library with the C ABI for other programming languages
......@@ -8164,7 +8218,8 @@ ArrayTypeStart &lt;- LBRACKET Expr? RBRACKET
81648218PtrTypeStart
81658219 &lt;- ASTERISK
81668220 / ASTERISK2
8167 / LBRACKET ASTERISK RBRACKET
8221 / PTRUNKNOWN
8222 / PTRC
81688223
81698224# ContainerDecl specific
81708225ContainerDeclAuto &lt;- ContainerDeclType LBRACE ContainerMembers RBRACE
......@@ -8262,7 +8317,7 @@ LARROW2 &lt;- '&lt;&lt;' ![=] skip
82628317LARROW2EQUAL &lt;- '&lt;&lt;=' skip
82638318LARROWEQUAL &lt;- '&lt;=' skip
82648319LBRACE &lt;- '{' skip
8265LBRACKET &lt;- '[' skip
8320LBRACKET &lt;- '[' ![*] skip
82668321LPAREN &lt;- '(' skip
82678322MINUS &lt;- '-' ![%=&gt;] skip
82688323MINUSEQUAL &lt;- '-=' skip
......@@ -8279,6 +8334,8 @@ PLUS2 &lt;- '++' skip
82798334PLUSEQUAL &lt;- '+=' skip
82808335PLUSPERCENT &lt;- '+%' ![=] skip
82818336PLUSPERCENTEQUAL &lt;- '+%=' skip
8337PTRC &lt;- '[*c]' skip
8338PTRUNKNOWN &lt;- '[*]' skip
82828339QUESTIONMARK &lt;- '?' skip
82838340RARROW &lt;- '&gt;' ![&gt;=] skip
82848341RARROW2 &lt;- '&gt;&gt;' ![=] skip
src-self-hosted/codegen.zig+21-21
......@@ -137,10 +137,10 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
137137
138138pub const ObjectFile = struct {
139139 comp: *Compilation,
140 module: llvm.ModuleRef,
141 builder: llvm.BuilderRef,
140 module: *llvm.Module,
141 builder: *llvm.Builder,
142142 dibuilder: *llvm.DIBuilder,
143 context: llvm.ContextRef,
143 context: *llvm.Context,
144144 lock: event.Lock,
145145 arena: *std.mem.Allocator,
146146
......@@ -323,7 +323,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
323323
324324fn addLLVMAttr(
325325 ofile: *ObjectFile,
326 val: llvm.ValueRef,
326 val: *llvm.Value,
327327 attr_index: llvm.AttributeIndex,
328328 attr_name: []const u8,
329329) !void {
......@@ -335,7 +335,7 @@ fn addLLVMAttr(
335335
336336fn addLLVMAttrStr(
337337 ofile: *ObjectFile,
338 val: llvm.ValueRef,
338 val: *llvm.Value,
339339 attr_index: llvm.AttributeIndex,
340340 attr_name: []const u8,
341341 attr_val: []const u8,
......@@ -351,7 +351,7 @@ fn addLLVMAttrStr(
351351}
352352
353353fn addLLVMAttrInt(
354 val: llvm.ValueRef,
354 val: *llvm.Value,
355355 attr_index: llvm.AttributeIndex,
356356 attr_name: []const u8,
357357 attr_val: u64,
......@@ -362,25 +362,25 @@ fn addLLVMAttrInt(
362362 llvm.AddAttributeAtIndex(val, attr_index, llvm_attr);
363363}
364364
365fn addLLVMFnAttr(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8) !void {
365fn addLLVMFnAttr(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8) !void {
366366 return addLLVMAttr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name);
367367}
368368
369fn addLLVMFnAttrStr(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8, attr_val: []const u8) !void {
369fn addLLVMFnAttrStr(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8, attr_val: []const u8) !void {
370370 return addLLVMAttrStr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);
371371}
372372
373fn addLLVMFnAttrInt(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8, attr_val: u64) !void {
373fn addLLVMFnAttrInt(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8, attr_val: u64) !void {
374374 return addLLVMAttrInt(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);
375375}
376376
377377fn renderLoadUntyped(
378378 ofile: *ObjectFile,
379 ptr: llvm.ValueRef,
379 ptr: *llvm.Value,
380380 alignment: Type.Pointer.Align,
381381 vol: Type.Pointer.Vol,
382382 name: [*]const u8,
383) !llvm.ValueRef {
383) !*llvm.Value {
384384 const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory;
385385 switch (vol) {
386386 Type.Pointer.Vol.Non => {},
......@@ -390,11 +390,11 @@ fn renderLoadUntyped(
390390 return result;
391391}
392392
393fn renderLoad(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Pointer, name: [*]const u8) !llvm.ValueRef {
393fn renderLoad(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer, name: [*]const u8) !*llvm.Value {
394394 return renderLoadUntyped(ofile, ptr, ptr_type.key.alignment, ptr_type.key.vol, name);
395395}
396396
397pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Pointer) !?llvm.ValueRef {
397pub fn getHandleValue(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer) !?*llvm.Value {
398398 const child_type = ptr_type.key.child_type;
399399 if (!child_type.hasBits()) {
400400 return null;
......@@ -407,11 +407,11 @@ pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Po
407407
408408pub fn renderStoreUntyped(
409409 ofile: *ObjectFile,
410 value: llvm.ValueRef,
411 ptr: llvm.ValueRef,
410 value: *llvm.Value,
411 ptr: *llvm.Value,
412412 alignment: Type.Pointer.Align,
413413 vol: Type.Pointer.Vol,
414) !llvm.ValueRef {
414) !*llvm.Value {
415415 const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory;
416416 switch (vol) {
417417 Type.Pointer.Vol.Non => {},
......@@ -423,10 +423,10 @@ pub fn renderStoreUntyped(
423423
424424pub fn renderStore(
425425 ofile: *ObjectFile,
426 value: llvm.ValueRef,
427 ptr: llvm.ValueRef,
426 value: *llvm.Value,
427 ptr: *llvm.Value,
428428 ptr_type: *Type.Pointer,
429) !llvm.ValueRef {
429) !*llvm.Value {
430430 return renderStoreUntyped(ofile, value, ptr, ptr_type.key.alignment, ptr_type.key.vol);
431431}
432432
......@@ -435,7 +435,7 @@ pub fn renderAlloca(
435435 var_type: *Type,
436436 name: []const u8,
437437 alignment: Type.Pointer.Align,
438) !llvm.ValueRef {
438) !*llvm.Value {
439439 const llvm_var_type = try var_type.getLlvmType(ofile.arena, ofile.context);
440440 const name_with_null = try std.cstr.addNullByte(ofile.arena, name);
441441 const result = llvm.BuildAlloca(ofile.builder, llvm_var_type, name_with_null.ptr) orelse return error.OutOfMemory;
......@@ -443,7 +443,7 @@ pub fn renderAlloca(
443443 return result;
444444}
445445
446pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: llvm.TypeRef) u32 {
446pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: *llvm.Type) u32 {
447447 return switch (alignment) {
448448 Type.Pointer.Align.Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type),
449449 Type.Pointer.Align.Override => |a| a,
src-self-hosted/compilation.zig+11-11
......@@ -37,7 +37,7 @@ const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
3737/// Data that is local to the event loop.
3838pub const ZigCompiler = struct {
3939 loop: *event.Loop,
40 llvm_handle_pool: std.atomic.Stack(llvm.ContextRef),
40 llvm_handle_pool: std.atomic.Stack(*llvm.Context),
4141 lld_lock: event.Lock,
4242
4343 /// TODO pool these so that it doesn't have to lock
......@@ -60,7 +60,7 @@ pub const ZigCompiler = struct {
6060 return ZigCompiler{
6161 .loop = loop,
6262 .lld_lock = event.Lock.init(loop),
63 .llvm_handle_pool = std.atomic.Stack(llvm.ContextRef).init(),
63 .llvm_handle_pool = std.atomic.Stack(*llvm.Context).init(),
6464 .prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)),
6565 .native_libc = event.Future(LibCInstallation).init(loop),
6666 };
......@@ -70,7 +70,7 @@ pub const ZigCompiler = struct {
7070 fn deinit(self: *ZigCompiler) void {
7171 self.lld_lock.deinit();
7272 while (self.llvm_handle_pool.pop()) |node| {
73 c.LLVMContextDispose(node.data);
73 llvm.ContextDispose(node.data);
7474 self.loop.allocator.destroy(node);
7575 }
7676 }
......@@ -80,11 +80,11 @@ pub const ZigCompiler = struct {
8080 pub fn getAnyLlvmContext(self: *ZigCompiler) !LlvmHandle {
8181 if (self.llvm_handle_pool.pop()) |node| return LlvmHandle{ .node = node };
8282
83 const context_ref = c.LLVMContextCreate() orelse return error.OutOfMemory;
84 errdefer c.LLVMContextDispose(context_ref);
83 const context_ref = llvm.ContextCreate() orelse return error.OutOfMemory;
84 errdefer llvm.ContextDispose(context_ref);
8585
86 const node = try self.loop.allocator.create(std.atomic.Stack(llvm.ContextRef).Node);
87 node.* = std.atomic.Stack(llvm.ContextRef).Node{
86 const node = try self.loop.allocator.create(std.atomic.Stack(*llvm.Context).Node);
87 node.* = std.atomic.Stack(*llvm.Context).Node{
8888 .next = undefined,
8989 .data = context_ref,
9090 };
......@@ -114,7 +114,7 @@ pub const ZigCompiler = struct {
114114};
115115
116116pub const LlvmHandle = struct {
117 node: *std.atomic.Stack(llvm.ContextRef).Node,
117 node: *std.atomic.Stack(*llvm.Context).Node,
118118
119119 pub fn release(self: LlvmHandle, zig_compiler: *ZigCompiler) void {
120120 zig_compiler.llvm_handle_pool.push(self.node);
......@@ -128,7 +128,7 @@ pub const Compilation = struct {
128128 llvm_triple: Buffer,
129129 root_src_path: ?[]const u8,
130130 target: Target,
131 llvm_target: llvm.TargetRef,
131 llvm_target: *llvm.Target,
132132 build_mode: builtin.Mode,
133133 zig_lib_dir: []const u8,
134134 zig_std_dir: []const u8,
......@@ -212,8 +212,8 @@ pub const Compilation = struct {
212212 false_value: *Value.Bool,
213213 noreturn_value: *Value.NoReturn,
214214
215 target_machine: llvm.TargetMachineRef,
216 target_data_ref: llvm.TargetDataRef,
215 target_machine: *llvm.TargetMachine,
216 target_data_ref: *llvm.TargetData,
217217 target_layout_str: [*]u8,
218218 target_ptr_bits: u32,
219219
src-self-hosted/ir.zig+10-10
......@@ -67,7 +67,7 @@ pub const Inst = struct {
6767 parent: ?*Inst,
6868
6969 /// populated durign codegen
70 llvm_value: ?llvm.ValueRef,
70 llvm_value: ?*llvm.Value,
7171
7272 pub fn cast(base: *Inst, comptime T: type) ?*T {
7373 if (base.id == comptime typeToId(T)) {
......@@ -129,7 +129,7 @@ pub const Inst = struct {
129129 }
130130 }
131131
132 pub fn render(base: *Inst, ofile: *ObjectFile, fn_val: *Value.Fn) (error{OutOfMemory}!?llvm.ValueRef) {
132 pub fn render(base: *Inst, ofile: *ObjectFile, fn_val: *Value.Fn) (error{OutOfMemory}!?*llvm.Value) {
133133 switch (base.id) {
134134 Id.Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val),
135135 Id.Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val),
......@@ -313,10 +313,10 @@ pub const Inst = struct {
313313 return new_inst;
314314 }
315315
316 pub fn render(self: *Call, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef {
316 pub fn render(self: *Call, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value {
317317 const fn_ref = self.params.fn_ref.llvm_value.?;
318318
319 const args = try ofile.arena.alloc(llvm.ValueRef, self.params.args.len);
319 const args = try ofile.arena.alloc(*llvm.Value, self.params.args.len);
320320 for (self.params.args) |arg, i| {
321321 args[i] = arg.llvm_value.?;
322322 }
......@@ -360,7 +360,7 @@ pub const Inst = struct {
360360 return new_inst;
361361 }
362362
363 pub fn render(self: *Const, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef {
363 pub fn render(self: *Const, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value {
364364 return self.base.val.KnownValue.getLlvmConst(ofile);
365365 }
366366 };
......@@ -392,7 +392,7 @@ pub const Inst = struct {
392392 return ira.irb.build(Return, self.base.scope, self.base.span, Params{ .return_value = casted_value });
393393 }
394394
395 pub fn render(self: *Return, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef {
395 pub fn render(self: *Return, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value {
396396 const value = self.params.return_value.llvm_value;
397397 const return_type = self.params.return_value.getKnownType();
398398
......@@ -540,7 +540,7 @@ pub const Inst = struct {
540540 }
541541 }
542542
543 pub fn render(self: *VarPtr, ofile: *ObjectFile, fn_val: *Value.Fn) llvm.ValueRef {
543 pub fn render(self: *VarPtr, ofile: *ObjectFile, fn_val: *Value.Fn) *llvm.Value {
544544 switch (self.params.var_scope.data) {
545545 Scope.Var.Data.Const => unreachable, // turned into Inst.Const in analyze pass
546546 Scope.Var.Data.Param => |param| return param.llvm_value,
......@@ -596,7 +596,7 @@ pub const Inst = struct {
596596 return new_inst;
597597 }
598598
599 pub fn render(self: *LoadPtr, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef {
599 pub fn render(self: *LoadPtr, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value {
600600 const child_type = self.base.getKnownType();
601601 if (!child_type.hasBits()) {
602602 return null;
......@@ -935,8 +935,8 @@ pub const BasicBlock = struct {
935935 ref_instruction: ?*Inst,
936936
937937 /// for codegen
938 llvm_block: llvm.BasicBlockRef,
939 llvm_exit_block: llvm.BasicBlockRef,
938 llvm_block: *llvm.BasicBlock,
939 llvm_exit_block: *llvm.BasicBlock,
940940
941941 /// the basic block that is derived from this one in analysis
942942 child: ?*BasicBlock,
src-self-hosted/libc_installation.zig+10-10
......@@ -154,8 +154,8 @@ pub const LibCInstallation = struct {
154154 c.ZigFindWindowsSdkError.None => {
155155 windows_sdk = sdk;
156156
157 if (sdk.msvc_lib_dir_ptr) |ptr| {
158 self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, ptr[0..sdk.msvc_lib_dir_len]);
157 if (sdk.msvc_lib_dir_ptr != 0) {
158 self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, sdk.msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]);
159159 }
160160 try group.call(findNativeKernel32LibDir, self, loop, sdk);
161161 try group.call(findNativeIncludeDirWindows, self, loop, sdk);
......@@ -437,20 +437,20 @@ const Search = struct {
437437
438438fn fillSearch(search_buf: *[2]Search, sdk: *c.ZigWindowsSDK) []Search {
439439 var search_end: usize = 0;
440 if (sdk.path10_ptr) |path10_ptr| {
441 if (sdk.version10_ptr) |ver10_ptr| {
440 if (sdk.path10_ptr != 0) {
441 if (sdk.version10_ptr != 0) {
442442 search_buf[search_end] = Search{
443 .path = path10_ptr[0..sdk.path10_len],
444 .version = ver10_ptr[0..sdk.version10_len],
443 .path = sdk.path10_ptr[0..sdk.path10_len],
444 .version = sdk.version10_ptr[0..sdk.version10_len],
445445 };
446446 search_end += 1;
447447 }
448448 }
449 if (sdk.path81_ptr) |path81_ptr| {
450 if (sdk.version81_ptr) |ver81_ptr| {
449 if (sdk.path81_ptr != 0) {
450 if (sdk.version81_ptr != 0) {
451451 search_buf[search_end] = Search{
452 .path = path81_ptr[0..sdk.path81_len],
453 .version = ver81_ptr[0..sdk.version81_len],
452 .path = sdk.path81_ptr[0..sdk.path81_len],
453 .version = sdk.version81_ptr[0..sdk.version81_len],
454454 };
455455 search_end += 1;
456456 }
src-self-hosted/llvm.zig+129-52
......@@ -11,45 +11,31 @@ const assert = @import("std").debug.assert;
1111pub const AttributeIndex = c_uint;
1212pub const Bool = c_int;
1313
14pub const BuilderRef = removeNullability(c.LLVMBuilderRef);
15pub const ContextRef = removeNullability(c.LLVMContextRef);
16pub const ModuleRef = removeNullability(c.LLVMModuleRef);
17pub const ValueRef = removeNullability(c.LLVMValueRef);
18pub const TypeRef = removeNullability(c.LLVMTypeRef);
19pub const BasicBlockRef = removeNullability(c.LLVMBasicBlockRef);
20pub const AttributeRef = removeNullability(c.LLVMAttributeRef);
21pub const TargetRef = removeNullability(c.LLVMTargetRef);
22pub const TargetMachineRef = removeNullability(c.LLVMTargetMachineRef);
23pub const TargetDataRef = removeNullability(c.LLVMTargetDataRef);
14pub const Builder = c.LLVMBuilderRef.Child.Child;
15pub const Context = c.LLVMContextRef.Child.Child;
16pub const Module = c.LLVMModuleRef.Child.Child;
17pub const Value = c.LLVMValueRef.Child.Child;
18pub const Type = c.LLVMTypeRef.Child.Child;
19pub const BasicBlock = c.LLVMBasicBlockRef.Child.Child;
20pub const Attribute = c.LLVMAttributeRef.Child.Child;
21pub const Target = c.LLVMTargetRef.Child.Child;
22pub const TargetMachine = c.LLVMTargetMachineRef.Child.Child;
23pub const TargetData = c.LLVMTargetDataRef.Child.Child;
2424pub const DIBuilder = c.ZigLLVMDIBuilder;
25pub const DIFile = c.ZigLLVMDIFile;
26pub const DICompileUnit = c.ZigLLVMDICompileUnit;
2527
2628pub const ABIAlignmentOfType = c.LLVMABIAlignmentOfType;
2729pub const AddAttributeAtIndex = c.LLVMAddAttributeAtIndex;
28pub const AddFunction = c.LLVMAddFunction;
29pub const AddGlobal = c.LLVMAddGlobal;
3030pub const AddModuleCodeViewFlag = c.ZigLLVMAddModuleCodeViewFlag;
3131pub const AddModuleDebugInfoFlag = c.ZigLLVMAddModuleDebugInfoFlag;
32pub const ArrayType = c.LLVMArrayType;
33pub const BuildLoad = c.LLVMBuildLoad;
3432pub const ClearCurrentDebugLocation = c.ZigLLVMClearCurrentDebugLocation;
3533pub const ConstAllOnes = c.LLVMConstAllOnes;
3634pub const ConstArray = c.LLVMConstArray;
3735pub const ConstBitCast = c.LLVMConstBitCast;
38pub const ConstInt = c.LLVMConstInt;
3936pub const ConstIntOfArbitraryPrecision = c.LLVMConstIntOfArbitraryPrecision;
4037pub const ConstNeg = c.LLVMConstNeg;
41pub const ConstNull = c.LLVMConstNull;
42pub const ConstStringInContext = c.LLVMConstStringInContext;
4338pub const ConstStructInContext = c.LLVMConstStructInContext;
44pub const CopyStringRepOfTargetData = c.LLVMCopyStringRepOfTargetData;
45pub const CreateBuilderInContext = c.LLVMCreateBuilderInContext;
46pub const CreateCompileUnit = c.ZigLLVMCreateCompileUnit;
47pub const CreateDIBuilder = c.ZigLLVMCreateDIBuilder;
48pub const CreateEnumAttribute = c.LLVMCreateEnumAttribute;
49pub const CreateFile = c.ZigLLVMCreateFile;
50pub const CreateStringAttribute = c.LLVMCreateStringAttribute;
51pub const CreateTargetDataLayout = c.LLVMCreateTargetDataLayout;
52pub const CreateTargetMachine = c.LLVMCreateTargetMachine;
5339pub const DIBuilderFinalize = c.ZigLLVMDIBuilderFinalize;
5440pub const DisposeBuilder = c.LLVMDisposeBuilder;
5541pub const DisposeDIBuilder = c.ZigLLVMDisposeDIBuilder;
......@@ -62,9 +48,7 @@ pub const DumpModule = c.LLVMDumpModule;
6248pub const FP128TypeInContext = c.LLVMFP128TypeInContext;
6349pub const FloatTypeInContext = c.LLVMFloatTypeInContext;
6450pub const GetEnumAttributeKindForName = c.LLVMGetEnumAttributeKindForName;
65pub const GetHostCPUName = c.ZigLLVMGetHostCPUName;
6651pub const GetMDKindIDInContext = c.LLVMGetMDKindIDInContext;
67pub const GetNativeFeatures = c.ZigLLVMGetNativeFeatures;
6852pub const GetUndef = c.LLVMGetUndef;
6953pub const HalfTypeInContext = c.LLVMHalfTypeInContext;
7054pub const InitializeAllAsmParsers = c.LLVMInitializeAllAsmParsers;
......@@ -81,14 +65,11 @@ pub const Int64TypeInContext = c.LLVMInt64TypeInContext;
8165pub const Int8TypeInContext = c.LLVMInt8TypeInContext;
8266pub const IntPtrTypeForASInContext = c.LLVMIntPtrTypeForASInContext;
8367pub const IntPtrTypeInContext = c.LLVMIntPtrTypeInContext;
84pub const IntTypeInContext = c.LLVMIntTypeInContext;
8568pub const LabelTypeInContext = c.LLVMLabelTypeInContext;
8669pub const MDNodeInContext = c.LLVMMDNodeInContext;
8770pub const MDStringInContext = c.LLVMMDStringInContext;
8871pub const MetadataTypeInContext = c.LLVMMetadataTypeInContext;
89pub const ModuleCreateWithNameInContext = c.LLVMModuleCreateWithNameInContext;
9072pub const PPCFP128TypeInContext = c.LLVMPPCFP128TypeInContext;
91pub const PointerType = c.LLVMPointerType;
9273pub const SetAlignment = c.LLVMSetAlignment;
9374pub const SetDataLayout = c.LLVMSetDataLayout;
9475pub const SetGlobalConstant = c.LLVMSetGlobalConstant;
......@@ -99,50 +80,146 @@ pub const SetUnnamedAddr = c.LLVMSetUnnamedAddr;
9980pub const SetVolatile = c.LLVMSetVolatile;
10081pub const StructTypeInContext = c.LLVMStructTypeInContext;
10182pub const TokenTypeInContext = c.LLVMTokenTypeInContext;
102pub const VoidTypeInContext = c.LLVMVoidTypeInContext;
10383pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext;
10484pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext;
10585
86pub const AddGlobal = LLVMAddGlobal;
87extern fn LLVMAddGlobal(M: *Module, Ty: *Type, Name: [*]const u8) ?*Value;
88
89pub const ConstStringInContext = LLVMConstStringInContext;
90extern fn LLVMConstStringInContext(C: *Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: Bool) ?*Value;
91
92pub const ConstInt = LLVMConstInt;
93extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) ?*Value;
94
95pub const BuildLoad = LLVMBuildLoad;
96extern fn LLVMBuildLoad(arg0: *Builder, PointerVal: *Value, Name: [*]const u8) ?*Value;
97
98pub const ConstNull = LLVMConstNull;
99extern fn LLVMConstNull(Ty: *Type) ?*Value;
100
101pub const CreateStringAttribute = LLVMCreateStringAttribute;
102extern fn LLVMCreateStringAttribute(
103 C: *Context,
104 K: [*]const u8,
105 KLength: c_uint,
106 V: [*]const u8,
107 VLength: c_uint,
108) ?*Attribute;
109
110pub const CreateEnumAttribute = LLVMCreateEnumAttribute;
111extern fn LLVMCreateEnumAttribute(C: *Context, KindID: c_uint, Val: u64) ?*Attribute;
112
113pub const AddFunction = LLVMAddFunction;
114extern fn LLVMAddFunction(M: *Module, Name: [*]const u8, FunctionTy: *Type) ?*Value;
115
116pub const CreateCompileUnit = ZigLLVMCreateCompileUnit;
117extern fn ZigLLVMCreateCompileUnit(
118 dibuilder: *DIBuilder,
119 lang: c_uint,
120 difile: *DIFile,
121 producer: [*]const u8,
122 is_optimized: bool,
123 flags: [*]const u8,
124 runtime_version: c_uint,
125 split_name: [*]const u8,
126 dwo_id: u64,
127 emit_debug_info: bool,
128) ?*DICompileUnit;
129
130pub const CreateFile = ZigLLVMCreateFile;
131extern fn ZigLLVMCreateFile(dibuilder: *DIBuilder, filename: [*]const u8, directory: [*]const u8) ?*DIFile;
132
133pub const ArrayType = LLVMArrayType;
134extern fn LLVMArrayType(ElementType: *Type, ElementCount: c_uint) ?*Type;
135
136pub const CreateDIBuilder = ZigLLVMCreateDIBuilder;
137extern fn ZigLLVMCreateDIBuilder(module: *Module, allow_unresolved: bool) ?*DIBuilder;
138
139pub const PointerType = LLVMPointerType;
140extern fn LLVMPointerType(ElementType: *Type, AddressSpace: c_uint) ?*Type;
141
142pub const CreateBuilderInContext = LLVMCreateBuilderInContext;
143extern fn LLVMCreateBuilderInContext(C: *Context) ?*Builder;
144
145pub const IntTypeInContext = LLVMIntTypeInContext;
146extern fn LLVMIntTypeInContext(C: *Context, NumBits: c_uint) ?*Type;
147
148pub const ModuleCreateWithNameInContext = LLVMModuleCreateWithNameInContext;
149extern fn LLVMModuleCreateWithNameInContext(ModuleID: [*]const u8, C: *Context) ?*Module;
150
151pub const VoidTypeInContext = LLVMVoidTypeInContext;
152extern fn LLVMVoidTypeInContext(C: *Context) ?*Type;
153
154pub const ContextCreate = LLVMContextCreate;
155extern fn LLVMContextCreate() ?*Context;
156
157pub const ContextDispose = LLVMContextDispose;
158extern fn LLVMContextDispose(C: *Context) void;
159
160pub const CopyStringRepOfTargetData = LLVMCopyStringRepOfTargetData;
161extern fn LLVMCopyStringRepOfTargetData(TD: *TargetData) ?[*]u8;
162
163pub const CreateTargetDataLayout = LLVMCreateTargetDataLayout;
164extern fn LLVMCreateTargetDataLayout(T: *TargetMachine) ?*TargetData;
165
166pub const CreateTargetMachine = LLVMCreateTargetMachine;
167extern fn LLVMCreateTargetMachine(
168 T: *Target,
169 Triple: [*]const u8,
170 CPU: [*]const u8,
171 Features: [*]const u8,
172 Level: CodeGenOptLevel,
173 Reloc: RelocMode,
174 CodeModel: CodeModel,
175) ?*TargetMachine;
176
177pub const GetHostCPUName = LLVMGetHostCPUName;
178extern fn LLVMGetHostCPUName() ?[*]u8;
179
180pub const GetNativeFeatures = ZigLLVMGetNativeFeatures;
181extern fn ZigLLVMGetNativeFeatures() ?[*]u8;
182
106183pub const GetElementType = LLVMGetElementType;
107extern fn LLVMGetElementType(Ty: TypeRef) TypeRef;
184extern fn LLVMGetElementType(Ty: *Type) *Type;
108185
109186pub const TypeOf = LLVMTypeOf;
110extern fn LLVMTypeOf(Val: ValueRef) TypeRef;
187extern fn LLVMTypeOf(Val: *Value) *Type;
111188
112189pub const BuildStore = LLVMBuildStore;
113extern fn LLVMBuildStore(arg0: BuilderRef, Val: ValueRef, Ptr: ValueRef) ?ValueRef;
190extern fn LLVMBuildStore(arg0: *Builder, Val: *Value, Ptr: *Value) ?*Value;
114191
115192pub const BuildAlloca = LLVMBuildAlloca;
116extern fn LLVMBuildAlloca(arg0: BuilderRef, Ty: TypeRef, Name: ?[*]const u8) ?ValueRef;
193extern fn LLVMBuildAlloca(arg0: *Builder, Ty: *Type, Name: ?[*]const u8) ?*Value;
117194
118195pub const ConstInBoundsGEP = LLVMConstInBoundsGEP;
119pub extern fn LLVMConstInBoundsGEP(ConstantVal: ValueRef, ConstantIndices: [*]ValueRef, NumIndices: c_uint) ?ValueRef;
196pub extern fn LLVMConstInBoundsGEP(ConstantVal: *Value, ConstantIndices: [*]*Value, NumIndices: c_uint) ?*Value;
120197
121198pub const GetTargetFromTriple = LLVMGetTargetFromTriple;
122extern fn LLVMGetTargetFromTriple(Triple: [*]const u8, T: *TargetRef, ErrorMessage: ?*[*]u8) Bool;
199extern fn LLVMGetTargetFromTriple(Triple: [*]const u8, T: **Target, ErrorMessage: ?*[*]u8) Bool;
123200
124201pub const VerifyModule = LLVMVerifyModule;
125extern fn LLVMVerifyModule(M: ModuleRef, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool;
202extern fn LLVMVerifyModule(M: *Module, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool;
126203
127204pub const GetInsertBlock = LLVMGetInsertBlock;
128extern fn LLVMGetInsertBlock(Builder: BuilderRef) BasicBlockRef;
205extern fn LLVMGetInsertBlock(Builder: *Builder) *BasicBlock;
129206
130207pub const FunctionType = LLVMFunctionType;
131208extern fn LLVMFunctionType(
132 ReturnType: TypeRef,
133 ParamTypes: [*]TypeRef,
209 ReturnType: *Type,
210 ParamTypes: [*]*Type,
134211 ParamCount: c_uint,
135212 IsVarArg: Bool,
136) ?TypeRef;
213) ?*Type;
137214
138215pub const GetParam = LLVMGetParam;
139extern fn LLVMGetParam(Fn: ValueRef, Index: c_uint) ValueRef;
216extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;
140217
141218pub const AppendBasicBlockInContext = LLVMAppendBasicBlockInContext;
142extern fn LLVMAppendBasicBlockInContext(C: ContextRef, Fn: ValueRef, Name: [*]const u8) ?BasicBlockRef;
219extern fn LLVMAppendBasicBlockInContext(C: *Context, Fn: *Value, Name: [*]const u8) ?*BasicBlock;
143220
144221pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd;
145extern fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef) void;
222extern fn LLVMPositionBuilderAtEnd(Builder: *Builder, Block: *BasicBlock) void;
146223
147224pub const AbortProcessAction = VerifierFailureAction.LLVMAbortProcessAction;
148225pub const PrintMessageAction = VerifierFailureAction.LLVMPrintMessageAction;
......@@ -190,17 +267,17 @@ pub const FnInline = extern enum {
190267};
191268
192269fn removeNullability(comptime T: type) type {
193 comptime assert(@typeId(T) == builtin.TypeId.Optional);
194 return T.Child;
270 comptime assert(@typeInfo(T).Pointer.size == @import("builtin").TypeInfo.Pointer.Size.C);
271 return *T.Child;
195272}
196273
197274pub const BuildRet = LLVMBuildRet;
198extern fn LLVMBuildRet(arg0: BuilderRef, V: ?ValueRef) ?ValueRef;
275extern fn LLVMBuildRet(arg0: *Builder, V: ?*Value) ?*Value;
199276
200277pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile;
201278extern fn ZigLLVMTargetMachineEmitToFile(
202 targ_machine_ref: TargetMachineRef,
203 module_ref: ModuleRef,
279 targ_machine_ref: *TargetMachine,
280 module_ref: *Module,
204281 filename: [*]const u8,
205282 output_type: EmitOutputType,
206283 error_message: *[*]u8,
......@@ -209,6 +286,6 @@ extern fn ZigLLVMTargetMachineEmitToFile(
209286) bool;
210287
211288pub const BuildCall = ZigLLVMBuildCall;
212extern fn ZigLLVMBuildCall(B: BuilderRef, Fn: ValueRef, Args: [*]ValueRef, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*]const u8) ?ValueRef;
289extern fn ZigLLVMBuildCall(B: *Builder, Fn: *Value, Args: [*]*Value, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*]const u8) ?*Value;
213290
214291pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage;
src-self-hosted/scope.zig+1-1
......@@ -362,7 +362,7 @@ pub const Scope = struct {
362362 pub const Param = struct {
363363 index: usize,
364364 typ: *Type,
365 llvm_value: llvm.ValueRef,
365 llvm_value: *llvm.Value,
366366 };
367367
368368 pub fn createParam(
src-self-hosted/target.zig+2-2
......@@ -457,8 +457,8 @@ pub const Target = union(enum) {
457457 }
458458 }
459459
460 pub fn llvmTargetFromTriple(triple: std.Buffer) !llvm.TargetRef {
461 var result: llvm.TargetRef = undefined;
460 pub fn llvmTargetFromTriple(triple: std.Buffer) !*llvm.Target {
461 var result: *llvm.Target = undefined;
462462 var err_msg: [*]u8 = undefined;
463463 if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) {
464464 std.debug.warn("triple: {s} error: {s}\n", triple.ptr(), err_msg);
src-self-hosted/type.zig+23-21
......@@ -51,8 +51,8 @@ pub const Type = struct {
5151 pub fn getLlvmType(
5252 base: *Type,
5353 allocator: *Allocator,
54 llvm_context: llvm.ContextRef,
55 ) (error{OutOfMemory}!llvm.TypeRef) {
54 llvm_context: *llvm.Context,
55 ) (error{OutOfMemory}!*llvm.Type) {
5656 switch (base.id) {
5757 Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context),
5858 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context),
......@@ -196,7 +196,7 @@ pub const Type = struct {
196196 }
197197
198198 /// If you have an llvm conext handy, you can use it here.
199 pub async fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: llvm.ContextRef) !u32 {
199 pub async fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {
200200 if (await (async base.abi_alignment.start() catch unreachable)) |ptr| return ptr.*;
201201
202202 base.abi_alignment.data = await (async base.resolveAbiAlignment(comp, llvm_context) catch unreachable);
......@@ -205,7 +205,7 @@ pub const Type = struct {
205205 }
206206
207207 /// Lower level function that does the work. See getAbiAlignment.
208 async fn resolveAbiAlignment(base: *Type, comp: *Compilation, llvm_context: llvm.ContextRef) !u32 {
208 async fn resolveAbiAlignment(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {
209209 const llvm_type = try base.getLlvmType(comp.gpa(), llvm_context);
210210 return @intCast(u32, llvm.ABIAlignmentOfType(comp.target_data_ref, llvm_type));
211211 }
......@@ -218,7 +218,7 @@ pub const Type = struct {
218218 comp.gpa().destroy(self);
219219 }
220220
221 pub fn getLlvmType(self: *Struct, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
221 pub fn getLlvmType(self: *Struct, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
222222 @panic("TODO");
223223 }
224224 };
......@@ -496,13 +496,13 @@ pub const Type = struct {
496496 comp.gpa().destroy(self);
497497 }
498498
499 pub fn getLlvmType(self: *Fn, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef {
499 pub fn getLlvmType(self: *Fn, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {
500500 const normal = &self.key.data.Normal;
501501 const llvm_return_type = switch (normal.return_type.id) {
502502 Type.Id.Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory,
503503 else => try normal.return_type.getLlvmType(allocator, llvm_context),
504504 };
505 const llvm_param_types = try allocator.alloc(llvm.TypeRef, normal.params.len);
505 const llvm_param_types = try allocator.alloc(*llvm.Type, normal.params.len);
506506 defer allocator.free(llvm_param_types);
507507 for (llvm_param_types) |*llvm_param_type, i| {
508508 llvm_param_type.* = try normal.params[i].typ.getLlvmType(allocator, llvm_context);
......@@ -559,7 +559,7 @@ pub const Type = struct {
559559 comp.gpa().destroy(self);
560560 }
561561
562 pub fn getLlvmType(self: *Bool, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
562 pub fn getLlvmType(self: *Bool, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
563563 @panic("TODO");
564564 }
565565 };
......@@ -658,7 +658,7 @@ pub const Type = struct {
658658 comp.gpa().destroy(self);
659659 }
660660
661 pub fn getLlvmType(self: *Int, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef {
661 pub fn getLlvmType(self: *Int, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {
662662 return llvm.IntTypeInContext(llvm_context, self.key.bit_count) orelse return error.OutOfMemory;
663663 }
664664 };
......@@ -670,7 +670,7 @@ pub const Type = struct {
670670 comp.gpa().destroy(self);
671671 }
672672
673 pub fn getLlvmType(self: *Float, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
673 pub fn getLlvmType(self: *Float, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
674674 @panic("TODO");
675675 }
676676 };
......@@ -794,6 +794,7 @@ pub const Type = struct {
794794 Size.One => "*",
795795 Size.Many => "[*]",
796796 Size.Slice => "[]",
797 Size.C => "[*c]",
797798 };
798799 const mut_str = switch (self.key.mut) {
799800 Mut.Const => "const ",
......@@ -835,7 +836,7 @@ pub const Type = struct {
835836 return self;
836837 }
837838
838 pub fn getLlvmType(self: *Pointer, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef {
839 pub fn getLlvmType(self: *Pointer, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {
839840 const elem_llvm_type = try self.key.child_type.getLlvmType(allocator, llvm_context);
840841 return llvm.PointerType(elem_llvm_type, 0) orelse return error.OutOfMemory;
841842 }
......@@ -903,7 +904,7 @@ pub const Type = struct {
903904 return self;
904905 }
905906
906 pub fn getLlvmType(self: *Array, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef {
907 pub fn getLlvmType(self: *Array, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {
907908 const elem_llvm_type = try self.key.elem_type.getLlvmType(allocator, llvm_context);
908909 return llvm.ArrayType(elem_llvm_type, @intCast(c_uint, self.key.len)) orelse return error.OutOfMemory;
909910 }
......@@ -916,7 +917,7 @@ pub const Type = struct {
916917 comp.gpa().destroy(self);
917918 }
918919
919 pub fn getLlvmType(self: *Vector, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
920 pub fn getLlvmType(self: *Vector, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
920921 @panic("TODO");
921922 }
922923 };
......@@ -966,7 +967,7 @@ pub const Type = struct {
966967 comp.gpa().destroy(self);
967968 }
968969
969 pub fn getLlvmType(self: *Optional, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
970 pub fn getLlvmType(self: *Optional, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
970971 @panic("TODO");
971972 }
972973 };
......@@ -978,7 +979,7 @@ pub const Type = struct {
978979 comp.gpa().destroy(self);
979980 }
980981
981 pub fn getLlvmType(self: *ErrorUnion, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
982 pub fn getLlvmType(self: *ErrorUnion, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
982983 @panic("TODO");
983984 }
984985 };
......@@ -990,7 +991,7 @@ pub const Type = struct {
990991 comp.gpa().destroy(self);
991992 }
992993
993 pub fn getLlvmType(self: *ErrorSet, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
994 pub fn getLlvmType(self: *ErrorSet, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
994995 @panic("TODO");
995996 }
996997 };
......@@ -1002,7 +1003,7 @@ pub const Type = struct {
10021003 comp.gpa().destroy(self);
10031004 }
10041005
1005 pub fn getLlvmType(self: *Enum, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
1006 pub fn getLlvmType(self: *Enum, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
10061007 @panic("TODO");
10071008 }
10081009 };
......@@ -1014,7 +1015,7 @@ pub const Type = struct {
10141015 comp.gpa().destroy(self);
10151016 }
10161017
1017 pub fn getLlvmType(self: *Union, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
1018 pub fn getLlvmType(self: *Union, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
10181019 @panic("TODO");
10191020 }
10201021 };
......@@ -1034,7 +1035,7 @@ pub const Type = struct {
10341035 comp.gpa().destroy(self);
10351036 }
10361037
1037 pub fn getLlvmType(self: *BoundFn, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
1038 pub fn getLlvmType(self: *BoundFn, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
10381039 @panic("TODO");
10391040 }
10401041 };
......@@ -1054,7 +1055,7 @@ pub const Type = struct {
10541055 comp.gpa().destroy(self);
10551056 }
10561057
1057 pub fn getLlvmType(self: *Opaque, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
1058 pub fn getLlvmType(self: *Opaque, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
10581059 @panic("TODO");
10591060 }
10601061 };
......@@ -1066,7 +1067,7 @@ pub const Type = struct {
10661067 comp.gpa().destroy(self);
10671068 }
10681069
1069 pub fn getLlvmType(self: *Promise, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
1070 pub fn getLlvmType(self: *Promise, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
10701071 @panic("TODO");
10711072 }
10721073 };
......@@ -1088,6 +1089,7 @@ fn hashAny(x: var, comptime seed: u64) u32 {
10881089 builtin.TypeInfo.Pointer.Size.One => return hashAny(@ptrToInt(x), seed),
10891090 builtin.TypeInfo.Pointer.Size.Many => @compileError("implement hash function"),
10901091 builtin.TypeInfo.Pointer.Size.Slice => @compileError("implement hash function"),
1092 builtin.TypeInfo.Pointer.Size.C => unreachable,
10911093 }
10921094 },
10931095 builtin.TypeId.Enum => return hashAny(@enumToInt(x), seed),
src-self-hosted/value.zig+9-9
......@@ -57,7 +57,7 @@ pub const Value = struct {
5757 std.debug.warn("{}", @tagName(base.id));
5858 }
5959
60 pub fn getLlvmConst(base: *Value, ofile: *ObjectFile) (error{OutOfMemory}!?llvm.ValueRef) {
60 pub fn getLlvmConst(base: *Value, ofile: *ObjectFile) (error{OutOfMemory}!?*llvm.Value) {
6161 switch (base.id) {
6262 Id.Type => unreachable,
6363 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile),
......@@ -153,7 +153,7 @@ pub const Value = struct {
153153 comp.gpa().destroy(self);
154154 }
155155
156 pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?llvm.ValueRef {
156 pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?*llvm.Value {
157157 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
158158 const llvm_fn = llvm.AddFunction(
159159 ofile.module,
......@@ -238,7 +238,7 @@ pub const Value = struct {
238238 /// We know that the function definition will end up in an .o file somewhere.
239239 /// Here, all we have to do is generate a global prototype.
240240 /// TODO cache the prototype per ObjectFile
241 pub fn getLlvmConst(self: *Fn, ofile: *ObjectFile) !?llvm.ValueRef {
241 pub fn getLlvmConst(self: *Fn, ofile: *ObjectFile) !?*llvm.Value {
242242 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
243243 const llvm_fn = llvm.AddFunction(
244244 ofile.module,
......@@ -283,8 +283,8 @@ pub const Value = struct {
283283 comp.gpa().destroy(self);
284284 }
285285
286 pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) ?llvm.ValueRef {
287 const llvm_type = llvm.Int1TypeInContext(ofile.context);
286 pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) !?*llvm.Value {
287 const llvm_type = llvm.Int1TypeInContext(ofile.context) orelse return error.OutOfMemory;
288288 if (self.x) {
289289 return llvm.ConstAllOnes(llvm_type);
290290 } else {
......@@ -381,7 +381,7 @@ pub const Value = struct {
381381 comp.gpa().destroy(self);
382382 }
383383
384 pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?llvm.ValueRef {
384 pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?*llvm.Value {
385385 const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context);
386386 // TODO carefully port the logic from codegen.cpp:gen_const_val_ptr
387387 switch (self.special) {
......@@ -391,7 +391,7 @@ pub const Value = struct {
391391 const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;
392392 const ptr_bit_count = ofile.comp.target_ptr_bits;
393393 const usize_llvm_type = llvm.IntTypeInContext(ofile.context, ptr_bit_count) orelse return error.OutOfMemory;
394 const indices = []llvm.ValueRef{
394 const indices = []*llvm.Value{
395395 llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory,
396396 llvm.ConstInt(usize_llvm_type, base_array.elem_index, 0) orelse return error.OutOfMemory,
397397 };
......@@ -459,7 +459,7 @@ pub const Value = struct {
459459 comp.gpa().destroy(self);
460460 }
461461
462 pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?llvm.ValueRef {
462 pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?*llvm.Value {
463463 switch (self.special) {
464464 Special.Undefined => {
465465 const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
......@@ -534,7 +534,7 @@ pub const Value = struct {
534534 return self;
535535 }
536536
537 pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?llvm.ValueRef {
537 pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?*llvm.Value {
538538 switch (self.base.typ.id) {
539539 Type.Id.Int => {
540540 const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
src/all_types.hpp+13-3
......@@ -691,15 +691,17 @@ struct AstNodePointerType {
691691 AstNode *align_expr;
692692 BigInt *bit_offset_start;
693693 BigInt *host_int_bytes;
694 AstNode *op_expr;
695 Token *allow_zero_token;
694696 bool is_const;
695697 bool is_volatile;
696 AstNode *op_expr;
697698};
698699
699700struct AstNodeArrayType {
700701 AstNode *size;
701702 AstNode *child_type;
702703 AstNode *align_expr;
704 Token *allow_zero_token;
703705 bool is_const;
704706 bool is_volatile;
705707};
......@@ -1038,6 +1040,7 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
10381040enum PtrLen {
10391041 PtrLenUnknown,
10401042 PtrLenSingle,
1043 PtrLenC,
10411044};
10421045
10431046struct ZigTypePointer {
......@@ -1049,6 +1052,7 @@ struct ZigTypePointer {
10491052 uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned
10501053 bool is_const;
10511054 bool is_volatile;
1055 bool allow_zero;
10521056};
10531057
10541058struct ZigTypeInt {
......@@ -1484,6 +1488,7 @@ enum PanicMsgId {
14841488 PanicMsgIdBadUnionField,
14851489 PanicMsgIdBadEnumValue,
14861490 PanicMsgIdFloatToInt,
1491 PanicMsgIdPtrCastNull,
14871492
14881493 PanicMsgIdCount,
14891494};
......@@ -1498,11 +1503,12 @@ struct TypeId {
14981503 struct {
14991504 ZigType *child_type;
15001505 PtrLen ptr_len;
1501 bool is_const;
1502 bool is_volatile;
15031506 uint32_t alignment;
15041507 uint32_t bit_offset_in_host;
15051508 uint32_t host_int_bytes;
1509 bool is_const;
1510 bool is_volatile;
1511 bool allow_zero;
15061512 } pointer;
15071513 struct {
15081514 ZigType *child_type;
......@@ -2591,6 +2597,7 @@ struct IrInstructionPtrType {
25912597 PtrLen ptr_len;
25922598 bool is_const;
25932599 bool is_volatile;
2600 bool allow_zero;
25942601};
25952602
25962603struct IrInstructionPromiseType {
......@@ -2606,6 +2613,7 @@ struct IrInstructionSliceType {
26062613 IrInstruction *child_type;
26072614 bool is_const;
26082615 bool is_volatile;
2616 bool allow_zero;
26092617};
26102618
26112619struct IrInstructionAsm {
......@@ -2994,12 +3002,14 @@ struct IrInstructionPtrCastSrc {
29943002
29953003 IrInstruction *dest_type;
29963004 IrInstruction *ptr;
3005 bool safety_check_on;
29973006};
29983007
29993008struct IrInstructionPtrCastGen {
30003009 IrInstruction base;
30013010
30023011 IrInstruction *ptr;
3012 bool safety_check_on;
30033013};
30043014
30053015struct IrInstructionBitCast {
src/analyze.cpp+83-14
......@@ -417,10 +417,25 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {
417417 return entry;
418418}
419419
420static const char *ptr_len_to_star_str(PtrLen ptr_len) {
421 switch (ptr_len) {
422 case PtrLenSingle:
423 return "*";
424 case PtrLenUnknown:
425 return "[*]";
426 case PtrLenC:
427 return "[*c]";
428 }
429 zig_unreachable();
430}
431
420432ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
421433 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
422434 uint32_t bit_offset_in_host, uint32_t host_int_bytes)
423435{
436 // TODO when implementing https://github.com/ziglang/zig/issues/1953
437 // move this to a parameter
438 bool allow_zero = (ptr_len == PtrLenC);
424439 assert(!type_is_invalid(child_type));
425440 assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);
426441
......@@ -440,7 +455,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
440455
441456 TypeId type_id = {};
442457 ZigType **parent_pointer = nullptr;
443 if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) {
458 if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || allow_zero) {
444459 type_id.id = ZigTypeIdPointer;
445460 type_id.data.pointer.child_type = child_type;
446461 type_id.data.pointer.is_const = is_const;
......@@ -449,6 +464,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
449464 type_id.data.pointer.bit_offset_in_host = bit_offset_in_host;
450465 type_id.data.pointer.host_int_bytes = host_int_bytes;
451466 type_id.data.pointer.ptr_len = ptr_len;
467 type_id.data.pointer.allow_zero = allow_zero;
452468
453469 auto existing_entry = g->type_table.maybe_get(type_id);
454470 if (existing_entry)
......@@ -466,21 +482,31 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
466482
467483 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
468484
469 const char *star_str = ptr_len == PtrLenSingle ? "*" : "[*]";
485 const char *star_str = ptr_len_to_star_str(ptr_len);
470486 const char *const_str = is_const ? "const " : "";
471487 const char *volatile_str = is_volatile ? "volatile " : "";
488 const char *allow_zero_str;
489 if (ptr_len == PtrLenC) {
490 assert(allow_zero);
491 allow_zero_str = "";
492 } else {
493 allow_zero_str = allow_zero ? "allowzero " : "";
494 }
472495 buf_resize(&entry->name, 0);
473496 if (host_int_bytes == 0 && byte_alignment == 0) {
474 buf_appendf(&entry->name, "%s%s%s%s", star_str, const_str, volatile_str, buf_ptr(&child_type->name));
497 buf_appendf(&entry->name, "%s%s%s%s%s",
498 star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
475499 } else if (host_int_bytes == 0) {
476 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment,
477 const_str, volatile_str, buf_ptr(&child_type->name));
500 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
501 const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
478502 } else if (byte_alignment == 0) {
479 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str,
480 bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));
503 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str,
504 bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
505 buf_ptr(&child_type->name));
481506 } else {
482 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment,
483 bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));
507 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
508 bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
509 buf_ptr(&child_type->name));
484510 }
485511
486512 assert(child_type->id != ZigTypeIdInvalid);
......@@ -488,7 +514,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
488514 entry->zero_bits = !type_has_bits(child_type);
489515
490516 if (!entry->zero_bits) {
491 if (is_const || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || bit_offset_in_host != 0) {
517 if (is_const || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle ||
518 bit_offset_in_host != 0 || allow_zero)
519 {
492520 ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false,
493521 PtrLenSingle, 0, 0, host_int_bytes);
494522 entry->type_ref = peer_type->type_ref;
......@@ -522,6 +550,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
522550 entry->data.pointer.explicit_alignment = byte_alignment;
523551 entry->data.pointer.bit_offset_in_host = bit_offset_in_host;
524552 entry->data.pointer.host_int_bytes = host_int_bytes;
553 entry->data.pointer.allow_zero = allow_zero;
525554
526555 if (parent_pointer) {
527556 *parent_pointer = entry;
......@@ -838,7 +867,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
838867
839868 ZigType *child_type = ptr_type->data.pointer.child_type;
840869 if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile ||
841 ptr_type->data.pointer.explicit_alignment != 0)
870 ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.allow_zero)
842871 {
843872 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
844873 PtrLenUnknown, 0, 0, 0);
......@@ -861,7 +890,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
861890 ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry;
862891 assert(child_ptr_type->id == ZigTypeIdPointer);
863892 if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile ||
864 child_ptr_type->data.pointer.explicit_alignment != 0)
893 child_ptr_type->data.pointer.explicit_alignment != 0 || child_ptr_type->data.pointer.allow_zero)
865894 {
866895 ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
867896 ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false,
......@@ -1457,7 +1486,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {
14571486 zig_unreachable();
14581487}
14591488
1460static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
1489bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
14611490 switch (type_entry->id) {
14621491 case ZigTypeIdInvalid:
14631492 zig_unreachable();
......@@ -2650,6 +2679,13 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
26502679 buf_sprintf("enums, not structs, support field assignment"));
26512680 }
26522681
2682 if (field_type->id == ZigTypeIdOpaque) {
2683 add_node_error(g, field_node->data.struct_field.type,
2684 buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs"));
2685 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2686 continue;
2687 }
2688
26532689 switch (type_requires_comptime(g, field_type)) {
26542690 case ReqCompTimeYes:
26552691 struct_type->data.structure.requires_comptime = true;
......@@ -2934,6 +2970,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
29342970 }
29352971 union_field->type_entry = field_type;
29362972
2973 if (field_type->id == ZigTypeIdOpaque) {
2974 add_node_error(g, field_node->data.struct_field.type,
2975 buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in unions"));
2976 union_type->data.unionation.is_invalid = true;
2977 continue;
2978 }
2979
29372980 switch (type_requires_comptime(g, field_type)) {
29382981 case ReqCompTimeInvalid:
29392982 union_type->data.unionation.is_invalid = true;
......@@ -4041,7 +4084,9 @@ ZigType *get_src_ptr_type(ZigType *type) {
40414084 if (type->id == ZigTypeIdFn) return type;
40424085 if (type->id == ZigTypeIdPromise) return type;
40434086 if (type->id == ZigTypeIdOptional) {
4044 if (type->data.maybe.child_type->id == ZigTypeIdPointer) return type->data.maybe.child_type;
4087 if (type->data.maybe.child_type->id == ZigTypeIdPointer) {
4088 return type->data.maybe.child_type->data.pointer.allow_zero ? nullptr : type->data.maybe.child_type;
4089 }
40454090 if (type->data.maybe.child_type->id == ZigTypeIdFn) return type->data.maybe.child_type;
40464091 if (type->data.maybe.child_type->id == ZigTypeIdPromise) return type->data.maybe.child_type;
40474092 }
......@@ -4055,6 +4100,10 @@ ZigType *get_codegen_ptr_type(ZigType *type) {
40554100 return ty;
40564101}
40574102
4103bool type_is_nonnull_ptr(ZigType *type) {
4104 return type_is_codegen_pointer(type) && !ptr_allows_addr_zero(type);
4105}
4106
40584107bool type_is_codegen_pointer(ZigType *type) {
40594108 return get_codegen_ptr_type(type) == type;
40604109}
......@@ -6300,6 +6349,7 @@ uint32_t type_id_hash(TypeId x) {
63006349 ((x.data.pointer.ptr_len == PtrLenSingle) ? (uint32_t)1120226602 : (uint32_t)3200913342) +
63016350 (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +
63026351 (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) +
6352 (x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) +
63036353 (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +
63046354 (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +
63056355 (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);
......@@ -6350,6 +6400,7 @@ bool type_id_eql(TypeId a, TypeId b) {
63506400 a.data.pointer.ptr_len == b.data.pointer.ptr_len &&
63516401 a.data.pointer.is_const == b.data.pointer.is_const &&
63526402 a.data.pointer.is_volatile == b.data.pointer.is_volatile &&
6403 a.data.pointer.allow_zero == b.data.pointer.allow_zero &&
63536404 a.data.pointer.alignment == b.data.pointer.alignment &&
63546405 a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&
63556406 a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes;
......@@ -6883,3 +6934,21 @@ Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_no
68836934
68846935 return ErrorNone;
68856936}
6937
6938const char *container_string(ContainerKind kind) {
6939 switch (kind) {
6940 case ContainerKindEnum: return "enum";
6941 case ContainerKindStruct: return "struct";
6942 case ContainerKindUnion: return "union";
6943 }
6944 zig_unreachable();
6945}
6946
6947bool ptr_allows_addr_zero(ZigType *ptr_type) {
6948 if (ptr_type->id == ZigTypeIdPointer) {
6949 return ptr_type->data.pointer.allow_zero;
6950 } else if (ptr_type->id == ZigTypeIdOptional) {
6951 return true;
6952 }
6953 return false;
6954}
src/analyze.hpp+4-1
......@@ -44,7 +44,9 @@ void find_libc_include_path(CodeGen *g);
4444void find_libc_lib_path(CodeGen *g);
4545
4646bool type_has_bits(ZigType *type_entry);
47
47bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry);
48bool ptr_allows_addr_zero(ZigType *ptr_type);
49bool type_is_nonnull_ptr(ZigType *type);
4850
4951ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);
5052
......@@ -215,6 +217,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);
215217X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty);
216218bool type_is_c_abi_int(CodeGen *g, ZigType *ty);
217219bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id);
220const char *container_string(ContainerKind kind);
218221
219222uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field);
220223
src/ast_render.cpp+14-13
......@@ -136,13 +136,19 @@ static const char *thread_local_string(Token *tok) {
136136 return (tok == nullptr) ? "" : "threadlocal ";
137137}
138138
139const char *container_string(ContainerKind kind) {
140 switch (kind) {
141 case ContainerKindEnum: return "enum";
142 case ContainerKindStruct: return "struct";
143 case ContainerKindUnion: return "union";
139static const char *token_to_ptr_len_str(Token *tok) {
140 assert(tok != nullptr);
141 switch (tok->id) {
142 case TokenIdStar:
143 case TokenIdStarStar:
144 return "*";
145 case TokenIdBracketStarBracket:
146 return "[*]";
147 case TokenIdBracketStarCBracket:
148 return "[*c]";
149 default:
150 zig_unreachable();
144151 }
145 zig_unreachable();
146152}
147153
148154static const char *node_type_str(NodeType node_type) {
......@@ -644,13 +650,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
644650 case NodeTypePointerType:
645651 {
646652 if (!grouped) fprintf(ar->f, "(");
647 const char *star = "[*]";
648 if (node->data.pointer_type.star_token != nullptr &&
649 (node->data.pointer_type.star_token->id == TokenIdStar || node->data.pointer_type.star_token->id == TokenIdStarStar))
650 {
651 star = "*";
652 }
653 fprintf(ar->f, "%s", star);
653 const char *ptr_len_str = token_to_ptr_len_str(node->data.pointer_type.star_token);
654 fprintf(ar->f, "%s", ptr_len_str);
654655 if (node->data.pointer_type.align_expr != nullptr) {
655656 fprintf(ar->f, "align(");
656657 render_node_grouped(ar, node->data.pointer_type.align_expr);
src/ast_render.hpp-3
......@@ -17,7 +17,4 @@ void ast_print(FILE *f, AstNode *node, int indent);
1717
1818void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size);
1919
20const char *container_string(ContainerKind kind);
21
2220#endif
23
src/codegen.cpp+37-6
......@@ -617,9 +617,10 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
617617 unsigned init_gen_i = 0;
618618 if (!type_has_bits(return_type)) {
619619 // nothing to do
620 } else if (type_is_codegen_pointer(return_type)) {
620 } else if (type_is_nonnull_ptr(return_type)) {
621621 addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
622622 } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {
623 // Sret pointers must not be address 0
623624 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");
624625 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
625626 if (cc_want_sret_attr(cc)) {
......@@ -637,6 +638,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
637638
638639 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
639640 if (err_ret_trace_arg_index != UINT32_MAX) {
641 // Error return trace memory is in the stack, which is impossible to be at address 0
642 // on any architecture.
640643 addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull");
641644 }
642645
......@@ -950,6 +953,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
950953 return buf_create_from_str("invalid enum value");
951954 case PanicMsgIdFloatToInt:
952955 return buf_create_from_str("integer part of floating point value out of bounds");
956 case PanicMsgIdPtrCastNull:
957 return buf_create_from_str("cast causes pointer to be null");
953958 }
954959 zig_unreachable();
955960}
......@@ -1244,6 +1249,8 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {
12441249 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
12451250 addLLVMFnAttr(fn_val, "nounwind");
12461251 add_uwtable_attr(g, fn_val);
1252 // Error return trace memory is in the stack, which is impossible to be at address 0
1253 // on any architecture.
12471254 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
12481255 if (g->build_mode == BuildModeDebug) {
12491256 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");
......@@ -1318,9 +1325,13 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
13181325 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
13191326 addLLVMFnAttr(fn_val, "nounwind");
13201327 add_uwtable_attr(g, fn_val);
1328 // Error return trace memory is in the stack, which is impossible to be at address 0
1329 // on any architecture.
13211330 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
13221331 addLLVMArgAttr(fn_val, (unsigned)0, "noalias");
13231332 addLLVMArgAttr(fn_val, (unsigned)0, "writeonly");
1333 // Error return trace memory is in the stack, which is impossible to be at address 0
1334 // on any architecture.
13241335 addLLVMArgAttr(fn_val, (unsigned)1, "nonnull");
13251336 addLLVMArgAttr(fn_val, (unsigned)1, "noalias");
13261337 addLLVMArgAttr(fn_val, (unsigned)1, "readonly");
......@@ -1448,6 +1459,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
14481459 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
14491460 addLLVMFnAttr(fn_val, "nounwind");
14501461 add_uwtable_attr(g, fn_val);
1462 // Error return trace memory is in the stack, which is impossible to be at address 0
1463 // on any architecture.
14511464 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
14521465 if (g->build_mode == BuildModeDebug) {
14531466 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");
......@@ -2049,7 +2062,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
20492062 case FnWalkIdAttrs: {
20502063 ZigType *ptr_type = get_codegen_ptr_type(ty);
20512064 if (ptr_type != nullptr) {
2052 if (ty->id != ZigTypeIdOptional) {
2065 if (type_is_nonnull_ptr(ty)) {
20532066 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
20542067 }
20552068 if (ptr_type->data.pointer.is_const) {
......@@ -2093,6 +2106,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
20932106 assert(handle_is_ptr(ty));
20942107 switch (fn_walk->id) {
20952108 case FnWalkIdAttrs:
2109 // arrays passed to C ABI functions may not be at address 0
20962110 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
20972111 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
20982112 fn_walk->data.attrs.gen_i += 1;
......@@ -2132,6 +2146,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
21322146 case FnWalkIdAttrs:
21332147 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "byval");
21342148 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
2149 // Byvalue parameters must not have address 0
21352150 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
21362151 fn_walk->data.attrs.gen_i += 1;
21372152 break;
......@@ -2264,7 +2279,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
22642279 if ((param_type->id == ZigTypeIdPointer && param_type->data.pointer.is_const) || is_byval) {
22652280 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "readonly");
22662281 }
2267 if (param_type->id == ZigTypeIdPointer) {
2282 if (type_is_nonnull_ptr(param_type)) {
22682283 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "nonnull");
22692284 }
22702285 break;
......@@ -2657,7 +2672,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
26572672 (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) ||
26582673 (op1->value.type->id == ZigTypeIdPointer &&
26592674 (op_id == IrBinOpAdd || op_id == IrBinOpSub) &&
2660 op1->value.type->data.pointer.ptr_len == PtrLenUnknown)
2675 op1->value.type->data.pointer.ptr_len != PtrLenSingle)
26612676 );
26622677 ZigType *operand_type = op1->value.type;
26632678 ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;
......@@ -2716,7 +2731,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
27162731 AddSubMulMul;
27172732
27182733 if (scalar_type->id == ZigTypeIdPointer) {
2719 assert(scalar_type->data.pointer.ptr_len == PtrLenUnknown);
2734 assert(scalar_type->data.pointer.ptr_len != PtrLenSingle);
27202735 LLVMValueRef subscript_value;
27212736 if (operand_type->id == ZigTypeIdVector)
27222737 zig_panic("TODO: Implement vector operations on pointers.");
......@@ -3028,7 +3043,22 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
30283043 return nullptr;
30293044 }
30303045 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
3031 return LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, "");
3046 LLVMValueRef result_ptr = LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, "");
3047 bool want_safety_check = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base);
3048 if (!want_safety_check || ptr_allows_addr_zero(wanted_type))
3049 return result_ptr;
3050
3051 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(result_ptr));
3052 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntNE, result_ptr, zero, "");
3053 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrCastFail");
3054 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrCastOk");
3055 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
3056
3057 LLVMPositionBuilderAtEnd(g->builder, fail_block);
3058 gen_safety_crash(g, PanicMsgIdPtrCastNull);
3059
3060 LLVMPositionBuilderAtEnd(g->builder, ok_block);
3061 return result_ptr;
30323062}
30333063
30343064static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,
......@@ -7294,6 +7324,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
72947324 " One,\n"
72957325 " Many,\n"
72967326 " Slice,\n"
7327 " C,\n"
72977328 " };\n"
72987329 " };\n"
72997330 "\n"
src/ir.cpp+450-167
......@@ -61,7 +61,7 @@ enum ConstCastResultId {
6161 ConstCastResultIdType,
6262 ConstCastResultIdUnresolvedInferredErrSet,
6363 ConstCastResultIdAsyncAllocatorType,
64 ConstCastResultIdNullWrapPtr
64 ConstCastResultIdBadAllowsZero,
6565};
6666
6767struct ConstCastOnly;
......@@ -83,6 +83,7 @@ struct ConstCastErrUnionErrSetMismatch;
8383struct ConstCastErrUnionPayloadMismatch;
8484struct ConstCastErrSetMismatch;
8585struct ConstCastTypeMismatch;
86struct ConstCastBadAllowsZero;
8687
8788struct ConstCastOnly {
8889 ConstCastResultId id;
......@@ -99,6 +100,7 @@ struct ConstCastOnly {
99100 ConstCastOnly *null_wrap_ptr_child;
100101 ConstCastArg fn_arg;
101102 ConstCastArgNoAlias arg_no_alias;
103 ConstCastBadAllowsZero *bad_allows_zero;
102104 } data;
103105};
104106
......@@ -141,6 +143,12 @@ struct ConstCastErrSetMismatch {
141143 ZigList<ErrorTableEntry *> missing_errors;
142144};
143145
146struct ConstCastBadAllowsZero {
147 ZigType *wanted_type;
148 ZigType *actual_type;
149};
150
151
144152enum UndefAllowed {
145153 UndefOk,
146154 UndefBad,
......@@ -164,11 +172,15 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
164172static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
165173 ConstExprValue *out_val, ConstExprValue *ptr_val);
166174static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,
167 ZigType *dest_type, IrInstruction *dest_type_src);
175 ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on);
168176static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
169177static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);
170178static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
171179static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry);
180static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
181 ZigType *ptr_type);
182static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
183 ZigType *dest_type);
172184
173185static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
174186 assert(get_src_ptr_type(const_val->type) != nullptr);
......@@ -2190,12 +2202,13 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo
21902202}
21912203
21922204static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
2193 IrInstruction *dest_type, IrInstruction *ptr)
2205 IrInstruction *dest_type, IrInstruction *ptr, bool safety_check_on)
21942206{
21952207 IrInstructionPtrCastSrc *instruction = ir_build_instruction<IrInstructionPtrCastSrc>(
21962208 irb, scope, source_node);
21972209 instruction->dest_type = dest_type;
21982210 instruction->ptr = ptr;
2211 instruction->safety_check_on = safety_check_on;
21992212
22002213 ir_ref_instruction(dest_type, irb->current_basic_block);
22012214 ir_ref_instruction(ptr, irb->current_basic_block);
......@@ -2204,12 +2217,13 @@ static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNod
22042217}
22052218
22062219static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction,
2207 ZigType *ptr_type, IrInstruction *ptr)
2220 ZigType *ptr_type, IrInstruction *ptr, bool safety_check_on)
22082221{
22092222 IrInstructionPtrCastGen *instruction = ir_build_instruction<IrInstructionPtrCastGen>(
22102223 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
22112224 instruction->base.value.type = ptr_type;
22122225 instruction->ptr = ptr;
2226 instruction->safety_check_on = safety_check_on;
22132227
22142228 ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
22152229
......@@ -2458,7 +2472,7 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode *
24582472
24592473 ir_ref_instruction(type_value, irb->current_basic_block);
24602474
2461 return &instruction->base;
2475 return &instruction->base;
24622476}
24632477
24642478static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node,
......@@ -4493,7 +4507,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
44934507 if (arg1_value == irb->codegen->invalid_instruction)
44944508 return arg1_value;
44954509
4496 IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value);
4510 IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value, true);
44974511 return ir_lval_wrap(irb, scope, ptr_cast, lval);
44984512 }
44994513 case BuiltinFnIdBitCast:
......@@ -5019,10 +5033,23 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *
50195033 return ir_build_ref(irb, scope, value->source_node, value, false, false);
50205034}
50215035
5036static PtrLen star_token_to_ptr_len(TokenId token_id) {
5037 switch (token_id) {
5038 case TokenIdStar:
5039 case TokenIdStarStar:
5040 return PtrLenSingle;
5041 case TokenIdBracketStarBracket:
5042 return PtrLenUnknown;
5043 case TokenIdBracketStarCBracket:
5044 return PtrLenC;
5045 default:
5046 zig_unreachable();
5047 }
5048}
5049
50225050static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) {
50235051 assert(node->type == NodeTypePointerType);
5024 PtrLen ptr_len = (node->data.pointer_type.star_token->id == TokenIdStar ||
5025 node->data.pointer_type.star_token->id == TokenIdStarStar) ? PtrLenSingle : PtrLenUnknown;
5052 PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id);
50265053 bool is_const = node->data.pointer_type.is_const;
50275054 bool is_volatile = node->data.pointer_type.is_volatile;
50285055 AstNode *expr_node = node->data.pointer_type.op_expr;
......@@ -6715,14 +6742,15 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode
67156742 IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010
67166743
67176744 // TODO relies on Zig not re-ordering fields
6718 IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst);
6745 IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst,
6746 false);
67196747 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
67206748 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
67216749 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
67226750 atomic_state_field_name);
67236751
67246752 // set the is_canceled bit
6725 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
6753 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
67266754 usize_type_val, atomic_state_ptr, nullptr, is_canceled_mask, nullptr,
67276755 AtomicRmwOp_or, AtomicOrderSeqCst);
67286756
......@@ -6793,14 +6821,15 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode
67936821 get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));
67946822
67956823 // TODO relies on Zig not re-ordering fields
6796 IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst);
6824 IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst,
6825 false);
67976826 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
67986827 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
67996828 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
68006829 atomic_state_field_name);
68016830
68026831 // clear the is_suspended bit
6803 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
6832 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
68046833 usize_type_val, atomic_state_ptr, nullptr, and_mask, nullptr,
68056834 AtomicRmwOp_and, AtomicOrderSeqCst);
68066835
......@@ -6916,7 +6945,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
69166945
69176946 IrInstruction *coro_handle_addr = ir_build_ptr_to_int(irb, scope, node, irb->exec->coro_handle);
69186947 IrInstruction *mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, coro_handle_addr, await_mask, false);
6919 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
6948 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
69206949 usize_type_val, atomic_state_ptr, nullptr, mask_bits, nullptr,
69216950 AtomicRmwOp_or, AtomicOrderSeqCst);
69226951
......@@ -6959,7 +6988,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
69596988
69606989
69616990 ir_set_cursor_at_end_and_append_block(irb, yes_suspend_block);
6962 IrInstruction *my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
6991 IrInstruction *my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
69636992 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, is_suspended_mask, nullptr,
69646993 AtomicRmwOp_or, AtomicOrderSeqCst);
69656994 IrInstruction *my_is_suspended_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, my_prev_atomic_value, is_suspended_mask, false);
......@@ -6991,7 +7020,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
69917020
69927021 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
69937022 IrInstruction *my_mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, ptr_mask, is_canceled_mask, false);
6994 IrInstruction *b_my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
7023 IrInstruction *b_my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
69957024 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, my_mask_bits, nullptr,
69967025 AtomicRmwOp_or, AtomicOrderSeqCst);
69977026 IrInstruction *my_await_handle_addr = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, b_my_prev_atomic_value, ptr_mask, false);
......@@ -7338,7 +7367,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
73387367
73397368 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,
73407369 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));
7341 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, coro_promise_ptr);
7370 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type,
7371 coro_promise_ptr, false);
73427372 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);
73437373 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
73447374 IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);
......@@ -7362,7 +7392,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
73627392 ir_build_return(irb, coro_scope, node, undef);
73637393
73647394 ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);
7365 IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr);
7395 IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr,
7396 false);
73667397 irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);
73677398
73687399 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
......@@ -7440,9 +7471,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
74407471 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
74417472 false, false, PtrLenUnknown, 0, 0, 0));
74427473 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);
7443 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, result_ptr);
7444 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
7445 irb->exec->coro_result_field_ptr);
7474 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
7475 result_ptr, false);
7476 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node,
7477 u8_ptr_type_unknown_len, irb->exec->coro_result_field_ptr, false);
74467478 IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,
74477479 fn_entry->type_entry->data.fn.fn_type_id.return_type);
74487480 IrInstruction *size_of_ret_val = ir_build_size_of(irb, scope, node, return_type_inst);
......@@ -7492,7 +7524,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
74927524 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
74937525 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
74947526 false, false, PtrLenUnknown, 0, 0, 0));
7495 IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe);
7527 IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
7528 coro_mem_ptr_maybe, false);
74967529 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
74977530 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
74987531 IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);
......@@ -8619,7 +8652,6 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp
86198652 return err_set_type;
86208653}
86218654
8622
86238655static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted_type,
86248656 ZigType *actual_type, AstNode *source_node, bool wanted_is_mutable)
86258657{
......@@ -8632,53 +8664,63 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
86328664 if (wanted_type == actual_type)
86338665 return result;
86348666
8635 // *T and [*]T may const-cast-only to ?*U and ?[*]U, respectively
8636 // but not if we want a mutable pointer
8637 // and not if the actual pointer has zero bits
8638 if (!wanted_is_mutable && wanted_type->id == ZigTypeIdOptional &&
8639 wanted_type->data.maybe.child_type->id == ZigTypeIdPointer &&
8640 actual_type->id == ZigTypeIdPointer && type_has_bits(actual_type))
8641 {
8642 ConstCastOnly child = types_match_const_cast_only(ira,
8643 wanted_type->data.maybe.child_type, actual_type, source_node, wanted_is_mutable);
8644 if (child.id == ConstCastResultIdInvalid)
8645 return child;
8646 if (child.id != ConstCastResultIdOk) {
8647 result.id = ConstCastResultIdNullWrapPtr;
8648 result.data.null_wrap_ptr_child = allocate_nonzero<ConstCastOnly>(1);
8649 *result.data.null_wrap_ptr_child = child;
8650 }
8651 return result;
8652 }
8653
8654 // pointer const
8655 if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) {
8656 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
8657 actual_type->data.pointer.child_type, source_node, !wanted_type->data.pointer.is_const);
8667 // If pointers have the same representation in memory, they can be "const-casted".
8668 // `const` attribute can be gained
8669 // `volatile` attribute can be gained
8670 // `allowzero` attribute can be gained (whether from explicit attribute, C pointer, or optional pointer)
8671 // but only if !wanted_is_mutable
8672 // alignment can be decreased
8673 // bit offset attributes must match exactly
8674 // PtrLenSingle/PtrLenUnknown must match exactly, but PtrLenC matches either one
8675 ZigType *wanted_ptr_type = get_src_ptr_type(wanted_type);
8676 ZigType *actual_ptr_type = get_src_ptr_type(actual_type);
8677 bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type);
8678 bool actual_allows_zero = ptr_allows_addr_zero(actual_type);
8679 bool wanted_is_c_ptr = wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC;
8680 bool actual_is_c_ptr = actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenC;
8681 bool wanted_opt_or_ptr = wanted_ptr_type != nullptr &&
8682 (wanted_type->id == ZigTypeIdPointer || wanted_type->id == ZigTypeIdOptional);
8683 bool actual_opt_or_ptr = actual_ptr_type != nullptr &&
8684 (actual_type->id == ZigTypeIdPointer || actual_type->id == ZigTypeIdOptional);
8685 if (wanted_opt_or_ptr && actual_opt_or_ptr) {
8686 ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type,
8687 actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const);
86588688 if (child.id == ConstCastResultIdInvalid)
86598689 return child;
86608690 if (child.id != ConstCastResultIdOk) {
86618691 result.id = ConstCastResultIdPointerChild;
86628692 result.data.pointer_mismatch = allocate_nonzero<ConstCastPointerMismatch>(1);
86638693 result.data.pointer_mismatch->child = child;
8664 result.data.pointer_mismatch->wanted_child = wanted_type->data.pointer.child_type;
8665 result.data.pointer_mismatch->actual_child = actual_type->data.pointer.child_type;
8694 result.data.pointer_mismatch->wanted_child = wanted_ptr_type->data.pointer.child_type;
8695 result.data.pointer_mismatch->actual_child = actual_ptr_type->data.pointer.child_type;
8696 return result;
8697 }
8698 bool ok_allows_zero = (wanted_allows_zero &&
8699 (actual_allows_zero || !wanted_is_mutable)) ||
8700 (!wanted_allows_zero && !actual_allows_zero);
8701 if (!ok_allows_zero) {
8702 result.id = ConstCastResultIdBadAllowsZero;
8703 result.data.bad_allows_zero = allocate_nonzero<ConstCastBadAllowsZero>(1);
8704 result.data.bad_allows_zero->wanted_type = wanted_type;
8705 result.data.bad_allows_zero->actual_type = actual_type;
86668706 return result;
86678707 }
8668 if ((err = type_resolve(g, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
8708 if ((err = type_resolve(g, actual_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
86698709 result.id = ConstCastResultIdInvalid;
86708710 return result;
86718711 }
8672 if ((err = type_resolve(g, wanted_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
8712 if ((err = type_resolve(g, wanted_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
86738713 result.id = ConstCastResultIdInvalid;
86748714 return result;
86758715 }
8676 if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) &&
8677 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
8678 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) &&
8679 actual_type->data.pointer.bit_offset_in_host == wanted_type->data.pointer.bit_offset_in_host &&
8680 actual_type->data.pointer.host_int_bytes == wanted_type->data.pointer.host_int_bytes &&
8681 get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type))
8716 bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
8717 if ((ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr) &&
8718 type_has_bits(wanted_type) == type_has_bits(actual_type) &&
8719 (!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) &&
8720 (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) &&
8721 actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host &&
8722 actual_ptr_type->data.pointer.host_int_bytes == wanted_ptr_type->data.pointer.host_int_bytes &&
8723 get_ptr_align(ira->codegen, actual_ptr_type) >= get_ptr_align(ira->codegen, wanted_ptr_type))
86828724 {
86838725 return result;
86848726 }
......@@ -8912,7 +8954,9 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t *
89128954 *errors = reallocate(*errors, old_errors_count, *errors_count);
89138955}
89148956
8915static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type, IrInstruction **instructions, size_t instruction_count) {
8957static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type,
8958 IrInstruction **instructions, size_t instruction_count)
8959{
89168960 Error err;
89178961 assert(instruction_count >= 1);
89188962 IrInstruction *prev_inst = instructions[0];
......@@ -9229,6 +9273,37 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
92299273 continue;
92309274 }
92319275
9276 if (prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenC &&
9277 (cur_type->id == ZigTypeIdComptimeInt || cur_type->id == ZigTypeIdInt))
9278 {
9279 continue;
9280 }
9281
9282 if (cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenC &&
9283 (prev_type->id == ZigTypeIdComptimeInt || prev_type->id == ZigTypeIdInt))
9284 {
9285 prev_inst = cur_inst;
9286 continue;
9287 }
9288
9289 if (prev_type->id == ZigTypeIdPointer && cur_type->id == ZigTypeIdPointer) {
9290 if (prev_type->data.pointer.ptr_len == PtrLenC &&
9291 types_match_const_cast_only(ira, prev_type->data.pointer.child_type,
9292 cur_type->data.pointer.child_type, source_node,
9293 !prev_type->data.pointer.is_const).id == ConstCastResultIdOk)
9294 {
9295 continue;
9296 }
9297 if (cur_type->data.pointer.ptr_len == PtrLenC &&
9298 types_match_const_cast_only(ira, cur_type->data.pointer.child_type,
9299 prev_type->data.pointer.child_type, source_node,
9300 !cur_type->data.pointer.is_const).id == ConstCastResultIdOk)
9301 {
9302 prev_inst = cur_inst;
9303 continue;
9304 }
9305 }
9306
92329307 if (types_match_const_cast_only(ira, prev_type, cur_type, source_node, false).id == ConstCastResultIdOk) {
92339308 continue;
92349309 }
......@@ -9864,7 +9939,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
98649939 if (undef_allowed == UndefOk) {
98659940 return &value->value;
98669941 } else {
9867 ir_add_error(ira, value, buf_sprintf("use of undefined value"));
9942 ir_add_error(ira, value, buf_sprintf("use of undefined value here causes undefined behavior"));
98689943 return nullptr;
98699944 }
98709945 }
......@@ -10770,6 +10845,24 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
1077010845 report_recursive_error(ira, source_node, cast_result->data.fn_arg.child, msg);
1077110846 break;
1077210847 }
10848 case ConstCastResultIdBadAllowsZero: {
10849 ZigType *wanted_type = cast_result->data.bad_allows_zero->wanted_type;
10850 ZigType *actual_type = cast_result->data.bad_allows_zero->actual_type;
10851 bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type);
10852 bool actual_allows_zero = ptr_allows_addr_zero(actual_type);
10853 if (actual_allows_zero && !wanted_allows_zero) {
10854 add_error_note(ira->codegen, parent_msg, source_node,
10855 buf_sprintf("'%s' could have null values which are illegal in type '%s'",
10856 buf_ptr(&actual_type->name),
10857 buf_ptr(&wanted_type->name)));
10858 } else {
10859 add_error_note(ira->codegen, parent_msg, source_node,
10860 buf_sprintf("mutable '%s' allows illegal null values stored to type '%s'",
10861 buf_ptr(&wanted_type->name),
10862 buf_ptr(&actual_type->name)));
10863 }
10864 break;
10865 }
1077310866 case ConstCastResultIdFnAlign: // TODO
1077410867 case ConstCastResultIdFnCC: // TODO
1077510868 case ConstCastResultIdFnVarArgs: // TODO
......@@ -10780,7 +10873,6 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
1078010873 case ConstCastResultIdFnArgNoAlias: // TODO
1078110874 case ConstCastResultIdUnresolvedInferredErrSet: // TODO
1078210875 case ConstCastResultIdAsyncAllocatorType: // TODO
10783 case ConstCastResultIdNullWrapPtr: // TODO
1078410876 break;
1078510877 }
1078610878}
......@@ -10811,6 +10903,39 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *
1081110903 return ir_build_vector_to_array(ira, source_instr, vector, array_type);
1081210904}
1081310905
10906static IrInstruction *ir_analyze_int_to_c_ptr(IrAnalyze *ira, IrInstruction *source_instr,
10907 IrInstruction *integer, ZigType *dest_type)
10908{
10909 IrInstruction *unsigned_integer;
10910 if (instr_is_comptime(integer)) {
10911 unsigned_integer = integer;
10912 } else {
10913 assert(integer->value.type->id == ZigTypeIdInt);
10914
10915 if (integer->value.type->data.integral.bit_count >
10916 ira->codegen->builtin_types.entry_usize->data.integral.bit_count)
10917 {
10918 ir_add_error(ira, source_instr,
10919 buf_sprintf("integer type '%s' too big for implicit @intToPtr to type '%s'",
10920 buf_ptr(&integer->value.type->name),
10921 buf_ptr(&dest_type->name)));
10922 return ira->codegen->invalid_instruction;
10923 }
10924
10925 if (integer->value.type->data.integral.is_signed) {
10926 ZigType *unsigned_int_type = get_int_type(ira->codegen, false,
10927 integer->value.type->data.integral.bit_count);
10928 unsigned_integer = ir_analyze_bit_cast(ira, source_instr, integer, unsigned_int_type);
10929 if (type_is_invalid(unsigned_integer->value.type))
10930 return ira->codegen->invalid_instruction;
10931 } else {
10932 unsigned_integer = integer;
10933 }
10934 }
10935
10936 return ir_analyze_int_to_ptr(ira, source_instr, unsigned_integer, dest_type);
10937}
10938
1081410939static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
1081510940 ZigType *wanted_type, IrInstruction *value)
1081610941{
......@@ -11182,7 +11307,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1118211307 actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes &&
1118311308 get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type))
1118411309 {
11185 return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr);
11310 return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr, true);
1118611311 }
1118711312 }
1118811313
......@@ -11217,6 +11342,23 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1121711342 return ir_analyze_array_to_vector(ira, source_instr, value, wanted_type);
1121811343 }
1121911344
11345 // casting between C pointers and normal pointers
11346 if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer &&
11347 (wanted_type->data.pointer.ptr_len == PtrLenC || actual_type->data.pointer.ptr_len == PtrLenC) &&
11348 types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
11349 actual_type->data.pointer.child_type, source_node,
11350 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
11351 {
11352 return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr, true);
11353 }
11354
11355 // cast from integer to C pointer
11356 if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC &&
11357 (actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt))
11358 {
11359 return ir_analyze_int_to_c_ptr(ira, source_instr, value, wanted_type);
11360 }
11361
1122011362 // cast from undefined to anything
1122111363 if (actual_type->id == ZigTypeIdUndefined) {
1122211364 return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type);
......@@ -11588,28 +11730,34 @@ static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
1158811730}
1158911731
1159011732static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {
11591 if (op_id == IrBinOpCmpEq) {
11592 return cmp == CmpEQ;
11593 } else if (op_id == IrBinOpCmpNotEq) {
11594 return cmp != CmpEQ;
11595 } else if (op_id == IrBinOpCmpLessThan) {
11596 return cmp == CmpLT;
11597 } else if (op_id == IrBinOpCmpGreaterThan) {
11598 return cmp == CmpGT;
11599 } else if (op_id == IrBinOpCmpLessOrEq) {
11600 return cmp != CmpGT;
11601 } else if (op_id == IrBinOpCmpGreaterOrEq) {
11602 return cmp != CmpLT;
11603 } else {
11604 zig_unreachable();
11733 switch (op_id) {
11734 case IrBinOpCmpEq:
11735 return cmp == CmpEQ;
11736 case IrBinOpCmpNotEq:
11737 return cmp != CmpEQ;
11738 case IrBinOpCmpLessThan:
11739 return cmp == CmpLT;
11740 case IrBinOpCmpGreaterThan:
11741 return cmp == CmpGT;
11742 case IrBinOpCmpLessOrEq:
11743 return cmp != CmpGT;
11744 case IrBinOpCmpGreaterOrEq:
11745 return cmp != CmpLT;
11746 default:
11747 zig_unreachable();
1160511748 }
1160611749}
1160711750
1160811751static bool optional_value_is_null(ConstExprValue *val) {
1160911752 assert(val->special == ConstValSpecialStatic);
1161011753 if (get_codegen_ptr_type(val->type) != nullptr) {
11611 return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
11612 val->data.x_ptr.data.hard_coded_addr.addr == 0;
11754 if (val->data.x_ptr.special == ConstPtrSpecialNull) {
11755 return true;
11756 } else if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
11757 return val->data.x_ptr.data.hard_coded_addr.addr == 0;
11758 } else {
11759 return false;
11760 }
1161311761 } else if (is_opt_err_set(val->type)) {
1161411762 return val->data.x_err_set == nullptr;
1161511763 } else {
......@@ -11773,7 +11921,6 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1177311921 case ZigTypeIdBool:
1177411922 case ZigTypeIdMetaType:
1177511923 case ZigTypeIdVoid:
11776 case ZigTypeIdPointer:
1177711924 case ZigTypeIdErrorSet:
1177811925 case ZigTypeIdFn:
1177911926 case ZigTypeIdOpaque:
......@@ -11785,6 +11932,10 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1178511932 operator_allowed = is_equality_cmp;
1178611933 break;
1178711934
11935 case ZigTypeIdPointer:
11936 operator_allowed = is_equality_cmp || (resolved_type->data.pointer.ptr_len == PtrLenC);
11937 break;
11938
1178811939 case ZigTypeIdUnreachable:
1178911940 case ZigTypeIdArray:
1179011941 case ZigTypeIdStruct:
......@@ -11832,15 +11983,38 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1183211983 if (op2_val == nullptr)
1183311984 return ira->codegen->invalid_instruction;
1183411985
11835 bool answer;
1183611986 if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) {
1183711987 Cmp cmp_result = float_cmp(op1_val, op2_val);
11838 answer = resolve_cmp_op_id(op_id, cmp_result);
11988 bool answer = resolve_cmp_op_id(op_id, cmp_result);
11989 return ir_const_bool(ira, &bin_op_instruction->base, answer);
1183911990 } else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) {
1184011991 Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint);
11841 answer = resolve_cmp_op_id(op_id, cmp_result);
11992 bool answer = resolve_cmp_op_id(op_id, cmp_result);
11993 return ir_const_bool(ira, &bin_op_instruction->base, answer);
11994 } else if (resolved_type->id == ZigTypeIdPointer && op_id != IrBinOpCmpEq && op_id != IrBinOpCmpNotEq) {
11995 if ((op1_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
11996 op1_val->data.x_ptr.special == ConstPtrSpecialNull) &&
11997 (op2_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
11998 op2_val->data.x_ptr.special == ConstPtrSpecialNull))
11999 {
12000 uint64_t op1_addr = op1_val->data.x_ptr.special == ConstPtrSpecialNull ?
12001 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr;
12002 uint64_t op2_addr = op2_val->data.x_ptr.special == ConstPtrSpecialNull ?
12003 0 : op2_val->data.x_ptr.data.hard_coded_addr.addr;
12004 Cmp cmp_result;
12005 if (op1_addr > op2_addr) {
12006 cmp_result = CmpGT;
12007 } else if (op1_addr < op2_addr) {
12008 cmp_result = CmpLT;
12009 } else {
12010 cmp_result = CmpEQ;
12011 }
12012 bool answer = resolve_cmp_op_id(op_id, cmp_result);
12013 return ir_const_bool(ira, &bin_op_instruction->base, answer);
12014 }
1184212015 } else {
1184312016 bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val);
12017 bool answer;
1184412018 if (op_id == IrBinOpCmpEq) {
1184512019 answer = are_equal;
1184612020 } else if (op_id == IrBinOpCmpNotEq) {
......@@ -11848,9 +12022,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1184812022 } else {
1184912023 zig_unreachable();
1185012024 }
12025 return ir_const_bool(ira, &bin_op_instruction->base, answer);
1185112026 }
11852
11853 return ir_const_bool(ira, &bin_op_instruction->base, answer);
1185412027 }
1185512028
1185612029 // some comparisons with unsigned numbers can be evaluated
......@@ -12245,7 +12418,29 @@ static bool ok_float_op(IrBinOp op) {
1224512418 zig_unreachable();
1224612419}
1224712420
12421static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) {
12422 if (lhs_type->id != ZigTypeIdPointer)
12423 return false;
12424 switch (op) {
12425 case IrBinOpAdd:
12426 case IrBinOpSub:
12427 break;
12428 default:
12429 return false;
12430 }
12431 switch (lhs_type->data.pointer.ptr_len) {
12432 case PtrLenSingle:
12433 return false;
12434 case PtrLenUnknown:
12435 case PtrLenC:
12436 break;
12437 }
12438 return true;
12439}
12440
1224812441static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) {
12442 Error err;
12443
1224912444 IrInstruction *op1 = instruction->op1->child;
1225012445 if (type_is_invalid(op1->value.type))
1225112446 return ira->codegen->invalid_instruction;
......@@ -12257,13 +12452,44 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
1225712452 IrBinOp op_id = instruction->op_id;
1225812453
1225912454 // look for pointer math
12260 if (op1->value.type->id == ZigTypeIdPointer && op1->value.type->data.pointer.ptr_len == PtrLenUnknown &&
12261 (op_id == IrBinOpAdd || op_id == IrBinOpSub))
12262 {
12455 if (is_pointer_arithmetic_allowed(op1->value.type, op_id)) {
1226312456 IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize);
12264 if (casted_op2 == ira->codegen->invalid_instruction)
12457 if (type_is_invalid(casted_op2->value.type))
1226512458 return ira->codegen->invalid_instruction;
1226612459
12460 if (op1->value.special == ConstValSpecialUndef || casted_op2->value.special == ConstValSpecialUndef) {
12461 IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type);
12462 result->value.special = ConstValSpecialUndef;
12463 return result;
12464 }
12465 if (casted_op2->value.special == ConstValSpecialStatic && op1->value.special == ConstValSpecialStatic &&
12466 (op1->value.data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
12467 op1->value.data.x_ptr.special == ConstPtrSpecialNull))
12468 {
12469 uint64_t start_addr = (op1->value.data.x_ptr.special == ConstPtrSpecialNull) ?
12470 0 : op1->value.data.x_ptr.data.hard_coded_addr.addr;
12471 uint64_t elem_offset;
12472 if (!ir_resolve_usize(ira, casted_op2, &elem_offset))
12473 return ira->codegen->invalid_instruction;
12474 ZigType *elem_type = op1->value.type->data.pointer.child_type;
12475 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
12476 return ira->codegen->invalid_instruction;
12477 uint64_t byte_offset = type_size(ira->codegen, elem_type) * elem_offset;
12478 uint64_t new_addr;
12479 if (op_id == IrBinOpAdd) {
12480 new_addr = start_addr + byte_offset;
12481 } else if (op_id == IrBinOpSub) {
12482 new_addr = start_addr - byte_offset;
12483 } else {
12484 zig_unreachable();
12485 }
12486 IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type);
12487 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
12488 result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
12489 result->value.data.x_ptr.data.hard_coded_addr.addr = new_addr;
12490 return result;
12491 }
12492
1226712493 IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,
1226812494 instruction->base.source_node, op_id, op1, casted_op2, true);
1226912495 result->value.type = op1->value.type;
......@@ -16366,7 +16592,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1636616592 pointee_val = const_ptr_pointee(ira, ira->codegen, &target_value_ptr->value, target_value_ptr->source_node);
1636716593 if (pointee_val == nullptr)
1636816594 return ira->codegen->invalid_instruction;
16369
16595
1637016596 if (pointee_val->special == ConstValSpecialRuntime)
1637116597 pointee_val = nullptr;
1637216598 }
......@@ -17116,7 +17342,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
1711617342static TypeStructField *validate_byte_offset(IrAnalyze *ira,
1711717343 IrInstruction *type_value,
1711817344 IrInstruction *field_name_value,
17119 size_t *byte_offset)
17345 size_t *byte_offset)
1712017346{
1712117347 ZigType *container_type = ir_resolve_type(ira, type_value);
1712217348 if (type_is_invalid(container_type))
......@@ -17290,7 +17516,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
1729017516
1729117517 // Loop through the definitions and generate info.
1729217518 decl_it = decls_scope->decl_table.entry_iterator();
17293 curr_entry = nullptr;
17519 curr_entry = nullptr;
1729417520 int definition_index = 0;
1729517521 while ((curr_entry = decl_it.next()) != nullptr) {
1729617522 // Skip comptime blocks and test functions.
......@@ -17469,6 +17695,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
1746917695 return ErrorNone;
1747017696}
1747117697
17698static uint32_t ptr_len_to_size_enum_index(PtrLen ptr_len) {
17699 switch (ptr_len) {
17700 case PtrLenSingle:
17701 return 0;
17702 case PtrLenUnknown:
17703 return 1;
17704 case PtrLenC:
17705 return 3;
17706 }
17707 zig_unreachable();
17708}
17709
1747217710static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) {
1747317711 Error err;
1747417712 ZigType *attrs_type;
......@@ -17478,7 +17716,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
1747817716 size_enum_index = 2;
1747917717 } else if (ptr_type_entry->id == ZigTypeIdPointer) {
1748017718 attrs_type = ptr_type_entry;
17481 size_enum_index = (ptr_type_entry->data.pointer.ptr_len == PtrLenSingle) ? 0 : 1;
17719 size_enum_index = ptr_len_to_size_enum_index(ptr_type_entry->data.pointer.ptr_len);
1748217720 } else {
1748317721 zig_unreachable();
1748417722 }
......@@ -20236,7 +20474,7 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
2023620474 } else {
2023720475 seenFalse += 1;
2023820476 }
20239
20477
2024020478 if ((seenTrue > 1) || (seenFalse > 1)) {
2024120479 ir_add_error(ira, value, buf_sprintf("duplicate switch value"));
2024220480 return ira->codegen->invalid_instruction;
......@@ -20369,7 +20607,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
2036920607}
2037020608
2037120609static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,
20372 ZigType *dest_type, IrInstruction *dest_type_src)
20610 ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on)
2037320611{
2037420612 Error err;
2037520613
......@@ -20379,12 +20617,14 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
2037920617 // We have a check for zero bits later so we use get_src_ptr_type to
2038020618 // validate src_type and dest_type.
2038120619
20382 if (get_src_ptr_type(src_type) == nullptr) {
20620 ZigType *src_ptr_type = get_src_ptr_type(src_type);
20621 if (src_ptr_type == nullptr) {
2038320622 ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));
2038420623 return ira->codegen->invalid_instruction;
2038520624 }
2038620625
20387 if (get_src_ptr_type(dest_type) == nullptr) {
20626 ZigType *dest_ptr_type = get_src_ptr_type(dest_type);
20627 if (dest_ptr_type == nullptr) {
2038820628 ir_add_error(ira, dest_type_src,
2038920629 buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
2039020630 return ira->codegen->invalid_instruction;
......@@ -20396,10 +20636,23 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
2039620636 }
2039720637
2039820638 if (instr_is_comptime(ptr)) {
20399 ConstExprValue *val = ir_resolve_const(ira, ptr, UndefOk);
20639 bool dest_allows_addr_zero = ptr_allows_addr_zero(dest_type);
20640 UndefAllowed is_undef_allowed = dest_allows_addr_zero ? UndefOk : UndefBad;
20641 ConstExprValue *val = ir_resolve_const(ira, ptr, is_undef_allowed);
2040020642 if (!val)
2040120643 return ira->codegen->invalid_instruction;
2040220644
20645 if (val->special == ConstValSpecialStatic) {
20646 bool is_addr_zero = val->data.x_ptr.special == ConstPtrSpecialNull ||
20647 (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
20648 val->data.x_ptr.data.hard_coded_addr.addr == 0);
20649 if (is_addr_zero && !dest_allows_addr_zero) {
20650 ir_add_error(ira, source_instr,
20651 buf_sprintf("null pointer casted to type '%s'", buf_ptr(&dest_type->name)));
20652 return ira->codegen->invalid_instruction;
20653 }
20654 }
20655
2040320656 IrInstruction *result = ir_const(ira, source_instr, dest_type);
2040420657 copy_const_val(&result->value, val, false);
2040520658 result->value.type = dest_type;
......@@ -20423,7 +20676,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
2042320676 return ira->codegen->invalid_instruction;
2042420677 }
2042520678
20426 IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr);
20679 IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on);
2042720680
2042820681 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
2042920682 ErrorMsg *msg = ir_add_error(ira, source_instr,
......@@ -20460,7 +20713,8 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct
2046020713 if (type_is_invalid(src_type))
2046120714 return ira->codegen->invalid_instruction;
2046220715
20463 return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value);
20716 return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value,
20717 instruction->safety_check_on);
2046420718}
2046520719
2046620720static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ConstExprValue *val, size_t len) {
......@@ -20668,32 +20922,10 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
2066820922 zig_unreachable();
2066920923}
2067020924
20671static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
20672 Error err;
20673 IrInstruction *dest_type_value = instruction->dest_type->child;
20674 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
20675 if (type_is_invalid(dest_type))
20676 return ira->codegen->invalid_instruction;
20677
20678 IrInstruction *value = instruction->value->child;
20679 ZigType *src_type = value->value.type;
20680 if (type_is_invalid(src_type))
20681 return ira->codegen->invalid_instruction;
20682
20683 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown)))
20684 return ira->codegen->invalid_instruction;
20685
20686 if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown)))
20687 return ira->codegen->invalid_instruction;
20688
20689 if (get_codegen_ptr_type(src_type) != nullptr) {
20690 ir_add_error(ira, value,
20691 buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name)));
20692 return ira->codegen->invalid_instruction;
20693 }
20694
20695 switch (src_type->id) {
20925static bool type_can_bit_cast(ZigType *t) {
20926 switch (t->id) {
2069620927 case ZigTypeIdInvalid:
20928 zig_unreachable();
2069720929 case ZigTypeIdMetaType:
2069820930 case ZigTypeIdOpaque:
2069920931 case ZigTypeIdBoundFn:
......@@ -20704,42 +20936,36 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
2070420936 case ZigTypeIdComptimeInt:
2070520937 case ZigTypeIdUndefined:
2070620938 case ZigTypeIdNull:
20707 ir_add_error(ira, dest_type_value,
20708 buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
20709 return ira->codegen->invalid_instruction;
20939 case ZigTypeIdPointer:
20940 return false;
2071020941 default:
20711 break;
20942 // TODO list these types out explicitly, there are probably some other invalid ones here
20943 return true;
2071220944 }
20945}
2071320946
20714 if (get_codegen_ptr_type(dest_type) != nullptr) {
20715 ir_add_error(ira, dest_type_value,
20716 buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));
20947static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
20948 ZigType *dest_type)
20949{
20950 Error err;
20951
20952 ZigType *src_type = value->value.type;
20953 assert(get_codegen_ptr_type(src_type) == nullptr);
20954 assert(type_can_bit_cast(src_type));
20955 assert(get_codegen_ptr_type(dest_type) == nullptr);
20956 assert(type_can_bit_cast(dest_type));
20957
20958 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown)))
20959 return ira->codegen->invalid_instruction;
20960
20961 if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown)))
2071720962 return ira->codegen->invalid_instruction;
20718 }
2071920963
20720 switch (dest_type->id) {
20721 case ZigTypeIdInvalid:
20722 case ZigTypeIdMetaType:
20723 case ZigTypeIdOpaque:
20724 case ZigTypeIdBoundFn:
20725 case ZigTypeIdArgTuple:
20726 case ZigTypeIdNamespace:
20727 case ZigTypeIdUnreachable:
20728 case ZigTypeIdComptimeFloat:
20729 case ZigTypeIdComptimeInt:
20730 case ZigTypeIdUndefined:
20731 case ZigTypeIdNull:
20732 ir_add_error(ira, dest_type_value,
20733 buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
20734 return ira->codegen->invalid_instruction;
20735 default:
20736 break;
20737 }
2073820964
2073920965 uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);
2074020966 uint64_t src_size_bytes = type_size(ira->codegen, src_type);
2074120967 if (dest_size_bytes != src_size_bytes) {
20742 ir_add_error(ira, &instruction->base,
20968 ir_add_error(ira, source_instr,
2074320969 buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,
2074420970 buf_ptr(&dest_type->name), dest_size_bytes,
2074520971 buf_ptr(&src_type->name), src_size_bytes));
......@@ -20749,7 +20975,7 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
2074920975 uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type);
2075020976 uint64_t src_size_bits = type_size_bits(ira->codegen, src_type);
2075120977 if (dest_size_bits != src_size_bits) {
20752 ir_add_error(ira, &instruction->base,
20978 ir_add_error(ira, source_instr,
2075320979 buf_sprintf("destination type '%s' has %" ZIG_PRI_u64 " bits but source type '%s' has %" ZIG_PRI_u64 " bits",
2075420980 buf_ptr(&dest_type->name), dest_size_bits,
2075520981 buf_ptr(&src_type->name), src_size_bits));
......@@ -20761,44 +20987,63 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
2076120987 if (!val)
2076220988 return ira->codegen->invalid_instruction;
2076320989
20764 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
20990 IrInstruction *result = ir_const(ira, source_instr, dest_type);
2076520991 uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);
2076620992 buf_write_value_bytes(ira->codegen, buf, val);
20767 if ((err = buf_read_value_bytes(ira, ira->codegen, instruction->base.source_node, buf, &result->value)))
20993 if ((err = buf_read_value_bytes(ira, ira->codegen, source_instr->source_node, buf, &result->value)))
2076820994 return ira->codegen->invalid_instruction;
2076920995 return result;
2077020996 }
2077120997
20772 IrInstruction *result = ir_build_bit_cast(&ira->new_irb, instruction->base.scope,
20773 instruction->base.source_node, nullptr, value);
20998 IrInstruction *result = ir_build_bit_cast(&ira->new_irb, source_instr->scope,
20999 source_instr->source_node, nullptr, value);
2077421000 result->value.type = dest_type;
2077521001 return result;
2077621002}
2077721003
20778static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) {
20779 Error err;
21004static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
2078021005 IrInstruction *dest_type_value = instruction->dest_type->child;
2078121006 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
2078221007 if (type_is_invalid(dest_type))
2078321008 return ira->codegen->invalid_instruction;
2078421009
20785 // We explicitly check for the size, so we can use get_src_ptr_type
20786 if (get_src_ptr_type(dest_type) == nullptr) {
20787 ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
21010 IrInstruction *value = instruction->value->child;
21011 ZigType *src_type = value->value.type;
21012 if (type_is_invalid(src_type))
21013 return ira->codegen->invalid_instruction;
21014
21015 if (get_codegen_ptr_type(src_type) != nullptr) {
21016 ir_add_error(ira, value,
21017 buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name)));
2078821018 return ira->codegen->invalid_instruction;
2078921019 }
2079021020
20791 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
21021 if (!type_can_bit_cast(src_type)) {
21022 ir_add_error(ira, dest_type_value,
21023 buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
2079221024 return ira->codegen->invalid_instruction;
20793 if (!type_has_bits(dest_type)) {
21025 }
21026
21027 if (get_codegen_ptr_type(dest_type) != nullptr) {
2079421028 ir_add_error(ira, dest_type_value,
20795 buf_sprintf("type '%s' has 0 bits and cannot store information", buf_ptr(&dest_type->name)));
21029 buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));
2079621030 return ira->codegen->invalid_instruction;
2079721031 }
2079821032
20799 IrInstruction *target = instruction->target->child;
20800 if (type_is_invalid(target->value.type))
21033 if (!type_can_bit_cast(dest_type)) {
21034 ir_add_error(ira, dest_type_value,
21035 buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
2080121036 return ira->codegen->invalid_instruction;
21037 }
21038
21039 return ir_analyze_bit_cast(ira, &instruction->base, value, dest_type);
21040}
21041
21042static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
21043 ZigType *ptr_type)
21044{
21045 assert(get_src_ptr_type(ptr_type) != nullptr);
21046 assert(type_has_bits(ptr_type));
2080221047
2080321048 IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);
2080421049 if (type_is_invalid(casted_int->value.type))
......@@ -20809,19 +21054,48 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru
2080921054 if (!val)
2081021055 return ira->codegen->invalid_instruction;
2081121056
20812 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
21057 IrInstruction *result = ir_const(ira, source_instr, ptr_type);
2081321058 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
2081421059 result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
2081521060 result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);
2081621061 return result;
2081721062 }
2081821063
20819 IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, instruction->base.scope,
20820 instruction->base.source_node, nullptr, casted_int);
20821 result->value.type = dest_type;
21064 IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, source_instr->scope,
21065 source_instr->source_node, nullptr, casted_int);
21066 result->value.type = ptr_type;
2082221067 return result;
2082321068}
2082421069
21070static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) {
21071 Error err;
21072 IrInstruction *dest_type_value = instruction->dest_type->child;
21073 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
21074 if (type_is_invalid(dest_type))
21075 return ira->codegen->invalid_instruction;
21076
21077 // We explicitly check for the size, so we can use get_src_ptr_type
21078 if (get_src_ptr_type(dest_type) == nullptr) {
21079 ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
21080 return ira->codegen->invalid_instruction;
21081 }
21082
21083 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
21084 return ira->codegen->invalid_instruction;
21085 if (!type_has_bits(dest_type)) {
21086 ir_add_error(ira, dest_type_value,
21087 buf_sprintf("type '%s' has 0 bits and cannot store information", buf_ptr(&dest_type->name)));
21088 return ira->codegen->invalid_instruction;
21089 }
21090
21091
21092 IrInstruction *target = instruction->target->child;
21093 if (type_is_invalid(target->value.type))
21094 return ira->codegen->invalid_instruction;
21095
21096 return ir_analyze_int_to_ptr(ira, &instruction->base, target, dest_type);
21097}
21098
2082521099static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
2082621100 IrInstructionDeclRef *instruction)
2082721101{
......@@ -20925,6 +21199,15 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
2092521199 } else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) {
2092621200 ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque"));
2092721201 return ira->codegen->invalid_instruction;
21202 } else if (instruction->ptr_len == PtrLenC) {
21203 if (!type_allowed_in_extern(ira->codegen, child_type)) {
21204 ir_add_error(ira, &instruction->base,
21205 buf_sprintf("C pointers cannot point to non-C-ABI-compatible type '%s'", buf_ptr(&child_type->name)));
21206 return ira->codegen->invalid_instruction;
21207 } else if (child_type->id == ZigTypeIdOpaque) {
21208 ir_add_error(ira, &instruction->base, buf_sprintf("C pointers cannot point opaque types"));
21209 return ira->codegen->invalid_instruction;
21210 }
2092821211 }
2092921212
2093021213 uint32_t align_bytes;
src/parser.cpp+9-1
......@@ -2778,7 +2778,8 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {
27782778// PtrTypeStart
27792779// <- ASTERISK
27802780// / ASTERISK2
2781// / LBRACKET ASTERISK RBRACKET
2781// / PTRUNKNOWN
2782// / PTRC
27822783static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
27832784 Token *asterisk = eat_token_if(pc, TokenIdStar);
27842785 if (asterisk != nullptr) {
......@@ -2804,6 +2805,13 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
28042805 return res;
28052806 }
28062807
2808 Token *cptr = eat_token_if(pc, TokenIdBracketStarCBracket);
2809 if (cptr != nullptr) {
2810 AstNode *res = ast_create_node(pc, NodeTypePointerType, cptr);
2811 res->data.pointer_type.star_token = cptr;
2812 return res;
2813 }
2814
28072815 return nullptr;
28082816}
28092817
src/target.cpp+4
......@@ -807,6 +807,10 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
807807 zig_unreachable();
808808}
809809
810bool target_allows_addr_zero(const ZigTarget *target) {
811 return target->os == OsFreestanding;
812}
813
810814const char *target_o_file_ext(ZigTarget *target) {
811815 if (target->env_type == ZigLLVM_MSVC || target->os == OsWindows || target->os == OsUefi) {
812816 return ".obj";
src/target.hpp+1
......@@ -135,5 +135,6 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target
135135ZigLLVM_OSType get_llvm_os_type(Os os_type);
136136
137137bool target_is_arm(const ZigTarget *target);
138bool target_allows_addr_zero(const ZigTarget *target);
138139
139140#endif
src/tokenizer.cpp+18-1
......@@ -221,6 +221,7 @@ enum TokenizeState {
221221 TokenizeStateError,
222222 TokenizeStateLBracket,
223223 TokenizeStateLBracketStar,
224 TokenizeStateLBracketStarC,
224225};
225226
226227
......@@ -846,7 +847,6 @@ void tokenize(Buf *buf, Tokenization *out) {
846847 switch (c) {
847848 case '*':
848849 t.state = TokenizeStateLBracketStar;
849 set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket);
850850 break;
851851 default:
852852 // reinterpret as just an lbracket
......@@ -857,6 +857,21 @@ void tokenize(Buf *buf, Tokenization *out) {
857857 }
858858 break;
859859 case TokenizeStateLBracketStar:
860 switch (c) {
861 case 'c':
862 t.state = TokenizeStateLBracketStarC;
863 set_token_id(&t, t.cur_tok, TokenIdBracketStarCBracket);
864 break;
865 case ']':
866 set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket);
867 end_token(&t);
868 t.state = TokenizeStateStart;
869 break;
870 default:
871 invalid_char_error(&t, c);
872 }
873 break;
874 case TokenizeStateLBracketStarC:
860875 switch (c) {
861876 case ']':
862877 end_token(&t);
......@@ -1491,6 +1506,7 @@ void tokenize(Buf *buf, Tokenization *out) {
14911506 case TokenizeStateLineStringContinue:
14921507 case TokenizeStateLineStringContinueC:
14931508 case TokenizeStateLBracketStar:
1509 case TokenizeStateLBracketStarC:
14941510 tokenize_error(&t, "unexpected EOF");
14951511 break;
14961512 case TokenizeStateLineComment:
......@@ -1528,6 +1544,7 @@ const char * token_name(TokenId id) {
15281544 case TokenIdBitShiftRightEq: return ">>=";
15291545 case TokenIdBitXorEq: return "^=";
15301546 case TokenIdBracketStarBracket: return "[*]";
1547 case TokenIdBracketStarCBracket: return "[*c]";
15311548 case TokenIdCharLiteral: return "CharLiteral";
15321549 case TokenIdCmpEq: return "==";
15331550 case TokenIdCmpGreaterOrEq: return ">=";
src/tokenizer.hpp+1
......@@ -29,6 +29,7 @@ enum TokenId {
2929 TokenIdBitShiftRightEq,
3030 TokenIdBitXorEq,
3131 TokenIdBracketStarBracket,
32 TokenIdBracketStarCBracket,
3233 TokenIdCharLiteral,
3334 TokenIdCmpEq,
3435 TokenIdCmpGreaterOrEq,
src/translate_c.cpp+28-12
......@@ -291,11 +291,22 @@ static AstNode *maybe_suppress_result(Context *c, ResultUsed result_used, AstNod
291291 node);
292292}
293293
294static TokenId ptr_len_to_token_id(PtrLen ptr_len) {
295 switch (ptr_len) {
296 case PtrLenSingle:
297 return TokenIdStar;
298 case PtrLenUnknown:
299 return TokenIdBracketStarBracket;
300 case PtrLenC:
301 return TokenIdBracketStarCBracket;
302 }
303 zig_unreachable();
304}
305
294306static AstNode *trans_create_node_ptr_type(Context *c, bool is_const, bool is_volatile, AstNode *child_node, PtrLen ptr_len) {
295307 AstNode *node = trans_create_node(c, NodeTypePointerType);
296308 node->data.pointer_type.star_token = allocate<ZigToken>(1);
297 node->data.pointer_type.star_token->id = (ptr_len == PtrLenSingle) ? TokenIdStar: TokenIdBracketStarBracket;
298 node->data.pointer_type.is_const = is_const;
309 node->data.pointer_type.star_token->id = ptr_len_to_token_id(ptr_len);
299310 node->data.pointer_type.is_const = is_const;
300311 node->data.pointer_type.is_volatile = is_volatile;
301312 node->data.pointer_type.op_expr = child_node;
......@@ -925,11 +936,14 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
925936 return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
926937 }
927938
928 PtrLen ptr_len = type_is_opaque(c, child_qt.getTypePtr(), source_loc) ? PtrLenSingle : PtrLenUnknown;
929
930 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
931 child_qt.isVolatileQualified(), child_node, ptr_len);
932 return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);
939 if (type_is_opaque(c, child_qt.getTypePtr(), source_loc)) {
940 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
941 child_qt.isVolatileQualified(), child_node, PtrLenSingle);
942 return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);
943 } else {
944 return trans_create_node_ptr_type(c, child_qt.isConstQualified(),
945 child_qt.isVolatileQualified(), child_node, PtrLenC);
946 }
933947 }
934948 case Type::Typedef:
935949 {
......@@ -1113,7 +1127,7 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
11131127 return nullptr;
11141128 }
11151129 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
1116 child_qt.isVolatileQualified(), child_type_node, PtrLenUnknown);
1130 child_qt.isVolatileQualified(), child_type_node, PtrLenC);
11171131 return pointer_node;
11181132 }
11191133 case Type::BlockPointer:
......@@ -1693,7 +1707,7 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im
16931707 return node;
16941708 }
16951709 case CK_NullToPointer:
1696 return trans_create_node(c, NodeTypeNullLiteral);
1710 return trans_create_node_unsigned(c, 0);
16971711 case CK_Dependent:
16981712 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dependent");
16991713 return nullptr;
......@@ -2425,7 +2439,8 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
24252439 case BuiltinType::Float16:
24262440 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));
24272441 case BuiltinType::NullPtr:
2428 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));
2442 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq,
2443 trans_create_node_unsigned(c, 0));
24292444
24302445 case BuiltinType::Void:
24312446 case BuiltinType::Half:
......@@ -2510,7 +2525,8 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
25102525 break;
25112526 }
25122527 case Type::Pointer:
2513 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));
2528 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq,
2529 trans_create_node_unsigned(c, 0));
25142530
25152531 case Type::Typedef:
25162532 {
......@@ -4568,7 +4584,7 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t
45684584 } else if (first_tok->id == CTokIdAsterisk) {
45694585 *tok_i += 1;
45704586
4571 node = trans_create_node_ptr_type(c, false, false, node, PtrLenUnknown);
4587 node = trans_create_node_ptr_type(c, false, false, node, PtrLenC);
45724588 } else {
45734589 return node;
45744590 }
std/fmt/index.zig+3
......@@ -236,6 +236,9 @@ pub fn formatType(
236236 const casted_value = ([]const u8)(value);
237237 return output(context, casted_value);
238238 },
239 builtin.TypeInfo.Pointer.Size.C => {
240 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
241 },
239242 },
240243 builtin.TypeId.Array => |info| {
241244 if (info.child == u8) {
std/hash_map.zig+2
......@@ -496,6 +496,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type
496496 builtin.TypeId.Pointer => |info| switch (info.size) {
497497 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto hash for single item pointers"),
498498 builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto hash for many item pointers"),
499 builtin.TypeInfo.Pointer.Size.C => @compileError("TODO auto hash C pointers"),
499500 builtin.TypeInfo.Pointer.Size.Slice => {
500501 const interval = std.math.max(1, key.len / 256);
501502 var i: usize = 0;
......@@ -543,6 +544,7 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {
543544 builtin.TypeId.Pointer => |info| switch (info.size) {
544545 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto eql for single item pointers"),
545546 builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto eql for many item pointers"),
547 builtin.TypeInfo.Pointer.Size.C => @compileError("TODO auto eql for C pointers"),
546548 builtin.TypeInfo.Pointer.Size.Slice => {
547549 if (a.len != b.len) return false;
548550 for (a) |a_item, i| {
std/meta/index.zig+6-3
......@@ -463,13 +463,16 @@ pub fn eql(a: var, b: @typeOf(a)) bool {
463463 builtin.TypeId.Pointer => {
464464 const info = @typeInfo(T).Pointer;
465465 switch (info.size) {
466 builtin.TypeInfo.Pointer.Size.One, builtin.TypeInfo.Pointer.Size.Many => return a == b,
466 builtin.TypeInfo.Pointer.Size.One,
467 builtin.TypeInfo.Pointer.Size.Many,
468 builtin.TypeInfo.Pointer.Size.C,
469 => return a == b,
467470 builtin.TypeInfo.Pointer.Size.Slice => return a.ptr == b.ptr and a.len == b.len,
468471 }
469472 },
470473 builtin.TypeId.Optional => {
471 if(a == null and b == null) return true;
472 if(a == null or b == null) return false;
474 if (a == null and b == null) return true;
475 if (a == null or b == null) return false;
473476 return eql(a.?, b.?);
474477 },
475478 else => return a == b,
std/os/darwin.zig+1-1
......@@ -665,7 +665,7 @@ pub fn pwrite(fd: i32, buf: [*]const u8, nbyte: usize, offset: u64) usize {
665665
666666pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
667667 const ptr_result = c.mmap(
668 @ptrCast(*c_void, address),
668 @ptrCast(?*c_void, address),
669669 length,
670670 @bitCast(c_int, @intCast(c_uint, prot)),
671671 @bitCast(c_int, c_uint(flags)),
std/testing.zig+1-2
......@@ -65,7 +65,7 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {
6565 }
6666 },
6767
68 builtin.TypeInfo.Pointer.Size.Slice => {
68 builtin.TypeInfo.Pointer.Size.Slice => {
6969 if (actual.ptr != expected.ptr) {
7070 std.debug.panic("expected slice ptr {}, found {}", expected.ptr, actual.ptr);
7171 }
......@@ -118,7 +118,6 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {
118118 }
119119 }
120120 },
121
122121 }
123122}
124123
std/zig/parse.zig+6-1
......@@ -3525,7 +3525,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {
35253525 Token.Id.Minus => ast.Node.PrefixOp.Op{ .Negation = void{} },
35263526 Token.Id.MinusPercent => ast.Node.PrefixOp.Op{ .NegationWrap = void{} },
35273527 Token.Id.Ampersand => ast.Node.PrefixOp.Op{ .AddressOf = void{} },
3528 Token.Id.Asterisk, Token.Id.AsteriskAsterisk, Token.Id.BracketStarBracket => ast.Node.PrefixOp.Op{
3528
3529 Token.Id.Asterisk,
3530 Token.Id.AsteriskAsterisk,
3531 Token.Id.BracketStarBracket,
3532 Token.Id.BracketStarCBracket,
3533 => ast.Node.PrefixOp.Op{
35293534 .PtrType = ast.Node.PrefixOp.PtrInfo{
35303535 .align_info = null,
35313536 .const_token = null,
std/zig/parser_test.zig+7
......@@ -1,3 +1,10 @@
1test "zig fmt: C pointers" {
2 try testCanonical(
3 \\const Ptr = [*c]i32;
4 \\
5 );
6}
7
18test "zig fmt: threadlocal" {
29 try testCanonical(
310 \\threadlocal var x: i32 = 1234;
std/zig/tokenizer.zig+22-1
......@@ -141,6 +141,7 @@ pub const Token = struct {
141141 LineComment,
142142 DocComment,
143143 BracketStarBracket,
144 BracketStarCBracket,
144145 ShebangLine,
145146 Keyword_align,
146147 Keyword_and,
......@@ -279,6 +280,7 @@ pub const Tokenizer = struct {
279280 SawAtSign,
280281 LBracket,
281282 LBracketStar,
283 LBracketStarC,
282284 };
283285
284286 pub fn next(self: *Tokenizer) Token {
......@@ -456,6 +458,9 @@ pub const Tokenizer = struct {
456458 },
457459
458460 State.LBracketStar => switch (c) {
461 'c' => {
462 state = State.LBracketStarC;
463 },
459464 ']' => {
460465 result.id = Token.Id.BracketStarBracket;
461466 self.index += 1;
......@@ -467,6 +472,18 @@ pub const Tokenizer = struct {
467472 },
468473 },
469474
475 State.LBracketStarC => switch (c) {
476 ']' => {
477 result.id = Token.Id.BracketStarCBracket;
478 self.index += 1;
479 break;
480 },
481 else => {
482 result.id = Token.Id.Invalid;
483 break;
484 },
485 },
486
470487 State.Ampersand => switch (c) {
471488 '=' => {
472489 result.id = Token.Id.AmpersandEqual;
......@@ -1035,6 +1052,7 @@ pub const Tokenizer = struct {
10351052 State.CharLiteralEnd,
10361053 State.StringLiteralBackslash,
10371054 State.LBracketStar,
1055 State.LBracketStarC,
10381056 => {
10391057 result.id = Token.Id.Invalid;
10401058 },
......@@ -1169,12 +1187,15 @@ test "tokenizer" {
11691187 testTokenize("test", []Token.Id{Token.Id.Keyword_test});
11701188}
11711189
1172test "tokenizer - unknown length pointer" {
1190test "tokenizer - unknown length pointer and then c pointer" {
11731191 testTokenize(
11741192 \\[*]u8
1193 \\[*c]u8
11751194 , []Token.Id{
11761195 Token.Id.BracketStarBracket,
11771196 Token.Id.Identifier,
1197 Token.Id.BracketStarCBracket,
1198 Token.Id.Identifier,
11781199 });
11791200}
11801201
test/compile_errors.zig+181-45
......@@ -1,13 +1,149 @@
11const tests = @import("tests.zig");
22
33pub fn addCases(cases: *tests.CompileErrorContext) void {
4 cases.addTest(
5 "C pointer to c_void",
6 \\export fn a() void {
7 \\ var x: *c_void = undefined;
8 \\ var y: [*c]c_void = x;
9 \\}
10 ,
11 ".tmp_source.zig:3:12: error: C pointers cannot point opaque types",
12 );
13
14 cases.addTest(
15 "directly embedding opaque type in struct and union",
16 \\const O = @OpaqueType();
17 \\const Foo = struct {
18 \\ o: O,
19 \\};
20 \\const Bar = union {
21 \\ One: i32,
22 \\ Two: O,
23 \\};
24 \\export fn a() void {
25 \\ var foo: Foo = undefined;
26 \\}
27 \\export fn b() void {
28 \\ var bar: Bar = undefined;
29 \\}
30 ,
31 ".tmp_source.zig:3:8: error: opaque types have unknown size and therefore cannot be directly embedded in structs",
32 ".tmp_source.zig:7:10: error: opaque types have unknown size and therefore cannot be directly embedded in unions",
33 );
34
35 cases.addTest(
36 "implicit cast between C pointer and Zig pointer - bad const/align/child",
37 \\export fn a() void {
38 \\ var x: [*c]u8 = undefined;
39 \\ var y: *align(4) u8 = x;
40 \\}
41 \\export fn b() void {
42 \\ var x: [*c]const u8 = undefined;
43 \\ var y: *u8 = x;
44 \\}
45 \\export fn c() void {
46 \\ var x: [*c]u8 = undefined;
47 \\ var y: *u32 = x;
48 \\}
49 \\export fn d() void {
50 \\ var y: *align(1) u32 = undefined;
51 \\ var x: [*c]u32 = y;
52 \\}
53 \\export fn e() void {
54 \\ var y: *const u8 = undefined;
55 \\ var x: [*c]u8 = y;
56 \\}
57 \\export fn f() void {
58 \\ var y: *u8 = undefined;
59 \\ var x: [*c]u32 = y;
60 \\}
61 ,
62 ".tmp_source.zig:3:27: error: cast increases pointer alignment",
63 ".tmp_source.zig:7:18: error: cast discards const qualifier",
64 ".tmp_source.zig:11:19: error: expected type '*u32', found '[*c]u8'",
65 ".tmp_source.zig:11:19: note: pointer type child 'u8' cannot cast into pointer type child 'u32'",
66 ".tmp_source.zig:15:22: error: cast increases pointer alignment",
67 ".tmp_source.zig:19:21: error: cast discards const qualifier",
68 ".tmp_source.zig:23:22: error: expected type '[*c]u32', found '*u8'",
69 );
70
71 cases.addTest(
72 "implicit casting null c pointer to zig pointer",
73 \\comptime {
74 \\ var c_ptr: [*c]u8 = 0;
75 \\ var zig_ptr: *u8 = c_ptr;
76 \\}
77 ,
78 ".tmp_source.zig:3:24: error: null pointer casted to type '*u8'",
79 );
80
81 cases.addTest(
82 "implicit casting undefined c pointer to zig pointer",
83 \\comptime {
84 \\ var c_ptr: [*c]u8 = undefined;
85 \\ var zig_ptr: *u8 = c_ptr;
86 \\}
87 ,
88 ".tmp_source.zig:3:24: error: use of undefined value here causes undefined behavior",
89 );
90
91 cases.addTest(
92 "implicit casting C pointers which would mess up null semantics",
93 \\export fn entry() void {
94 \\ var slice: []const u8 = "aoeu";
95 \\ const opt_many_ptr: [*]const u8 = slice.ptr;
96 \\ var ptr_opt_many_ptr = &opt_many_ptr;
97 \\ var c_ptr: [*c]const [*c]const u8 = ptr_opt_many_ptr;
98 \\ ptr_opt_many_ptr = c_ptr;
99 \\}
100 \\export fn entry2() void {
101 \\ var buf: [4]u8 = "aoeu";
102 \\ var slice: []u8 = &buf;
103 \\ var opt_many_ptr: [*]u8 = slice.ptr;
104 \\ var ptr_opt_many_ptr = &opt_many_ptr;
105 \\ var c_ptr: [*c][*c]const u8 = ptr_opt_many_ptr;
106 \\}
107 ,
108 ".tmp_source.zig:6:24: error: expected type '*const [*]const u8', found '[*c]const [*c]const u8'",
109 ".tmp_source.zig:6:24: note: pointer type child '[*c]const u8' cannot cast into pointer type child '[*]const u8'",
110 ".tmp_source.zig:6:24: note: '[*c]const u8' could have null values which are illegal in type '[*]const u8'",
111 ".tmp_source.zig:13:35: error: expected type '[*c][*c]const u8', found '*[*]u8'",
112 ".tmp_source.zig:13:35: note: pointer type child '[*]u8' cannot cast into pointer type child '[*c]const u8'",
113 ".tmp_source.zig:13:35: note: mutable '[*c]const u8' allows illegal null values stored to type '[*]u8'",
114 );
115
116 cases.addTest(
117 "implicit casting too big integers to C pointers",
118 \\export fn a() void {
119 \\ var ptr: [*c]u8 = (1 << 64) + 1;
120 \\}
121 \\export fn b() void {
122 \\ var x: @IntType(false, 65) = 0x1234;
123 \\ var ptr: [*c]u8 = x;
124 \\}
125 ,
126 ".tmp_source.zig:2:33: error: integer value 71615590737044764481 cannot be implicitly casted to type 'usize'",
127 ".tmp_source.zig:6:23: error: integer type 'u65' too big for implicit @intToPtr to type '[*c]u8'",
128 );
129
130 cases.addTest(
131 "C pointer pointing to non C ABI compatible type or has align attr",
132 \\const Foo = struct {};
133 \\export fn a() void {
134 \\ const T = [*c]Foo;
135 \\}
136 ,
137 ".tmp_source.zig:3:15: error: C pointers cannot point to non-C-ABI-compatible type 'Foo'",
138 );
139
4140 cases.addTest(
5141 "@truncate undefined value",
6142 \\export fn entry() void {
7143 \\ var z = @truncate(u8, u16(undefined));
8144 \\}
9145 ,
10 ".tmp_source.zig:2:30: error: use of undefined value",
146 ".tmp_source.zig:2:30: error: use of undefined value here causes undefined behavior",
11147 );
12148
13149 cases.addTest(
......@@ -368,7 +504,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
368504 \\ f(i32);
369505 \\}
370506 ,
371 ".tmp_source.zig:4:5: error: use of undefined value",
507 ".tmp_source.zig:4:5: error: use of undefined value here causes undefined behavior",
372508 );
373509
374510 cases.add(
......@@ -768,7 +904,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
768904 \\ command.exec();
769905 \\}
770906 ,
771 ".tmp_source.zig:6:12: error: use of undefined value",
907 ".tmp_source.zig:6:12: error: use of undefined value here causes undefined behavior",
772908 );
773909
774910 cases.add(
......@@ -781,7 +917,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
781917 \\ command.exec();
782918 \\}
783919 ,
784 ".tmp_source.zig:6:12: error: use of undefined value",
920 ".tmp_source.zig:6:12: error: use of undefined value here causes undefined behavior",
785921 );
786922
787923 cases.add(
......@@ -2752,7 +2888,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27522888 \\
27532889 \\export fn entry() usize { return @sizeOf(@typeOf(x)); }
27542890 ,
2755 ".tmp_source.zig:1:15: error: use of undefined value",
2891 ".tmp_source.zig:1:15: error: use of undefined value here causes undefined behavior",
27562892 );
27572893
27582894 cases.add(
......@@ -2762,7 +2898,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27622898 \\ _ = a / a;
27632899 \\}
27642900 ,
2765 ".tmp_source.zig:3:9: error: use of undefined value",
2901 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
27662902 );
27672903
27682904 cases.add(
......@@ -2772,7 +2908,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27722908 \\ a /= a;
27732909 \\}
27742910 ,
2775 ".tmp_source.zig:3:5: error: use of undefined value",
2911 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
27762912 );
27772913
27782914 cases.add(
......@@ -2782,7 +2918,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27822918 \\ _ = a % a;
27832919 \\}
27842920 ,
2785 ".tmp_source.zig:3:9: error: use of undefined value",
2921 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
27862922 );
27872923
27882924 cases.add(
......@@ -2792,7 +2928,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27922928 \\ a %= a;
27932929 \\}
27942930 ,
2795 ".tmp_source.zig:3:5: error: use of undefined value",
2931 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
27962932 );
27972933
27982934 cases.add(
......@@ -2802,7 +2938,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28022938 \\ _ = a + a;
28032939 \\}
28042940 ,
2805 ".tmp_source.zig:3:9: error: use of undefined value",
2941 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
28062942 );
28072943
28082944 cases.add(
......@@ -2812,7 +2948,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28122948 \\ a += a;
28132949 \\}
28142950 ,
2815 ".tmp_source.zig:3:5: error: use of undefined value",
2951 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
28162952 );
28172953
28182954 cases.add(
......@@ -2822,7 +2958,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28222958 \\ _ = a +% a;
28232959 \\}
28242960 ,
2825 ".tmp_source.zig:3:9: error: use of undefined value",
2961 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
28262962 );
28272963
28282964 cases.add(
......@@ -2832,7 +2968,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28322968 \\ a +%= a;
28332969 \\}
28342970 ,
2835 ".tmp_source.zig:3:5: error: use of undefined value",
2971 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
28362972 );
28372973
28382974 cases.add(
......@@ -2842,7 +2978,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28422978 \\ _ = a - a;
28432979 \\}
28442980 ,
2845 ".tmp_source.zig:3:9: error: use of undefined value",
2981 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
28462982 );
28472983
28482984 cases.add(
......@@ -2852,7 +2988,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28522988 \\ a -= a;
28532989 \\}
28542990 ,
2855 ".tmp_source.zig:3:5: error: use of undefined value",
2991 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
28562992 );
28572993
28582994 cases.add(
......@@ -2862,7 +2998,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28622998 \\ _ = a -% a;
28632999 \\}
28643000 ,
2865 ".tmp_source.zig:3:9: error: use of undefined value",
3001 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
28663002 );
28673003
28683004 cases.add(
......@@ -2872,7 +3008,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28723008 \\ a -%= a;
28733009 \\}
28743010 ,
2875 ".tmp_source.zig:3:5: error: use of undefined value",
3011 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
28763012 );
28773013
28783014 cases.add(
......@@ -2882,7 +3018,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28823018 \\ _ = a * a;
28833019 \\}
28843020 ,
2885 ".tmp_source.zig:3:9: error: use of undefined value",
3021 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
28863022 );
28873023
28883024 cases.add(
......@@ -2892,7 +3028,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28923028 \\ a *= a;
28933029 \\}
28943030 ,
2895 ".tmp_source.zig:3:5: error: use of undefined value",
3031 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
28963032 );
28973033
28983034 cases.add(
......@@ -2902,7 +3038,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29023038 \\ _ = a *% a;
29033039 \\}
29043040 ,
2905 ".tmp_source.zig:3:9: error: use of undefined value",
3041 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
29063042 );
29073043
29083044 cases.add(
......@@ -2912,7 +3048,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29123048 \\ a *%= a;
29133049 \\}
29143050 ,
2915 ".tmp_source.zig:3:5: error: use of undefined value",
3051 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
29163052 );
29173053
29183054 cases.add(
......@@ -2922,7 +3058,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29223058 \\ _ = a << 2;
29233059 \\}
29243060 ,
2925 ".tmp_source.zig:3:9: error: use of undefined value",
3061 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
29263062 );
29273063
29283064 cases.add(
......@@ -2932,7 +3068,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29323068 \\ a <<= 2;
29333069 \\}
29343070 ,
2935 ".tmp_source.zig:3:5: error: use of undefined value",
3071 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
29363072 );
29373073
29383074 cases.add(
......@@ -2942,7 +3078,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29423078 \\ _ = a >> 2;
29433079 \\}
29443080 ,
2945 ".tmp_source.zig:3:9: error: use of undefined value",
3081 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
29463082 );
29473083
29483084 cases.add(
......@@ -2952,7 +3088,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29523088 \\ a >>= 2;
29533089 \\}
29543090 ,
2955 ".tmp_source.zig:3:5: error: use of undefined value",
3091 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
29563092 );
29573093
29583094 cases.add(
......@@ -2962,7 +3098,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29623098 \\ _ = a & a;
29633099 \\}
29643100 ,
2965 ".tmp_source.zig:3:9: error: use of undefined value",
3101 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
29663102 );
29673103
29683104 cases.add(
......@@ -2972,7 +3108,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29723108 \\ a &= a;
29733109 \\}
29743110 ,
2975 ".tmp_source.zig:3:5: error: use of undefined value",
3111 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
29763112 );
29773113
29783114 cases.add(
......@@ -2982,7 +3118,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29823118 \\ _ = a | a;
29833119 \\}
29843120 ,
2985 ".tmp_source.zig:3:9: error: use of undefined value",
3121 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
29863122 );
29873123
29883124 cases.add(
......@@ -2992,7 +3128,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29923128 \\ a |= a;
29933129 \\}
29943130 ,
2995 ".tmp_source.zig:3:5: error: use of undefined value",
3131 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
29963132 );
29973133
29983134 cases.add(
......@@ -3002,7 +3138,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30023138 \\ _ = a ^ a;
30033139 \\}
30043140 ,
3005 ".tmp_source.zig:3:9: error: use of undefined value",
3141 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
30063142 );
30073143
30083144 cases.add(
......@@ -3012,7 +3148,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30123148 \\ a ^= a;
30133149 \\}
30143150 ,
3015 ".tmp_source.zig:3:5: error: use of undefined value",
3151 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
30163152 );
30173153
30183154 cases.add(
......@@ -3022,7 +3158,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30223158 \\ _ = a == a;
30233159 \\}
30243160 ,
3025 ".tmp_source.zig:3:9: error: use of undefined value",
3161 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
30263162 );
30273163
30283164 cases.add(
......@@ -3032,7 +3168,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30323168 \\ _ = a != a;
30333169 \\}
30343170 ,
3035 ".tmp_source.zig:3:9: error: use of undefined value",
3171 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
30363172 );
30373173
30383174 cases.add(
......@@ -3042,7 +3178,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30423178 \\ _ = a > a;
30433179 \\}
30443180 ,
3045 ".tmp_source.zig:3:9: error: use of undefined value",
3181 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
30463182 );
30473183
30483184 cases.add(
......@@ -3052,7 +3188,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30523188 \\ _ = a >= a;
30533189 \\}
30543190 ,
3055 ".tmp_source.zig:3:9: error: use of undefined value",
3191 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
30563192 );
30573193
30583194 cases.add(
......@@ -3062,7 +3198,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30623198 \\ _ = a < a;
30633199 \\}
30643200 ,
3065 ".tmp_source.zig:3:9: error: use of undefined value",
3201 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
30663202 );
30673203
30683204 cases.add(
......@@ -3072,7 +3208,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30723208 \\ _ = a <= a;
30733209 \\}
30743210 ,
3075 ".tmp_source.zig:3:9: error: use of undefined value",
3211 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
30763212 );
30773213
30783214 cases.add(
......@@ -3082,7 +3218,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30823218 \\ _ = a and a;
30833219 \\}
30843220 ,
3085 ".tmp_source.zig:3:9: error: use of undefined value",
3221 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
30863222 );
30873223
30883224 cases.add(
......@@ -3092,7 +3228,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30923228 \\ _ = a or a;
30933229 \\}
30943230 ,
3095 ".tmp_source.zig:3:9: error: use of undefined value",
3231 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
30963232 );
30973233
30983234 cases.add(
......@@ -3102,7 +3238,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
31023238 \\ _ = -a;
31033239 \\}
31043240 ,
3105 ".tmp_source.zig:3:10: error: use of undefined value",
3241 ".tmp_source.zig:3:10: error: use of undefined value here causes undefined behavior",
31063242 );
31073243
31083244 cases.add(
......@@ -3112,7 +3248,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
31123248 \\ _ = -%a;
31133249 \\}
31143250 ,
3115 ".tmp_source.zig:3:11: error: use of undefined value",
3251 ".tmp_source.zig:3:11: error: use of undefined value here causes undefined behavior",
31163252 );
31173253
31183254 cases.add(
......@@ -3122,7 +3258,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
31223258 \\ _ = ~a;
31233259 \\}
31243260 ,
3125 ".tmp_source.zig:3:10: error: use of undefined value",
3261 ".tmp_source.zig:3:10: error: use of undefined value here causes undefined behavior",
31263262 );
31273263
31283264 cases.add(
......@@ -3132,7 +3268,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
31323268 \\ _ = !a;
31333269 \\}
31343270 ,
3135 ".tmp_source.zig:3:10: error: use of undefined value",
3271 ".tmp_source.zig:3:10: error: use of undefined value here causes undefined behavior",
31363272 );
31373273
31383274 cases.add(
......@@ -3142,7 +3278,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
31423278 \\ _ = a orelse false;
31433279 \\}
31443280 ,
3145 ".tmp_source.zig:3:11: error: use of undefined value",
3281 ".tmp_source.zig:3:11: error: use of undefined value here causes undefined behavior",
31463282 );
31473283
31483284 cases.add(
......@@ -3152,7 +3288,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
31523288 \\ _ = a catch |err| false;
31533289 \\}
31543290 ,
3155 ".tmp_source.zig:3:11: error: use of undefined value",
3291 ".tmp_source.zig:3:11: error: use of undefined value here causes undefined behavior",
31563292 );
31573293
31583294 cases.add(
test/runtime_safety.zig+10
......@@ -1,6 +1,16 @@
11const tests = @import("tests.zig");
22
33pub fn addCases(cases: *tests.CompareOutputContext) void {
4 cases.addRuntimeSafety("pointer casting null to non-optional pointer",
5 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
6 \\ @import("std").os.exit(126);
7 \\}
8 \\pub fn main() void {
9 \\ var c_ptr: [*c]u8 = 0;
10 \\ var zig_ptr: *u8 = c_ptr;
11 \\}
12 );
13
414 cases.addRuntimeSafety("@intToEnum - no matching tag value",
515 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
616 \\ @import("std").os.exit(126);
test/stage1/behavior/pointers.zig+82
......@@ -1,5 +1,6 @@
11const std = @import("std");
22const expect = std.testing.expect;
3const expectError = std.testing.expectError;
34
45test "dereference pointer" {
56 comptime testDerefPtr();
......@@ -42,3 +43,84 @@ test "double pointer parsing" {
4243fn PtrOf(comptime T: type) type {
4344 return *T;
4445}
46
47test "assigning integer to C pointer" {
48 var x: i32 = 0;
49 var ptr: [*c]u8 = 0;
50 var ptr2: [*c]u8 = x;
51}
52
53test "implicit cast single item pointer to C pointer and back" {
54 var y: u8 = 11;
55 var x: [*c]u8 = &y;
56 var z: *u8 = x;
57 z.* += 1;
58 expect(y == 12);
59}
60
61test "C pointer comparison and arithmetic" {
62 const S = struct {
63 fn doTheTest() void {
64 var one: usize = 1;
65 var ptr1: [*c]u32 = 0;
66 var ptr2 = ptr1 + 10;
67 expect(ptr1 == 0);
68 expect(ptr1 >= 0);
69 expect(ptr1 <= 0);
70 expect(ptr1 < 1);
71 expect(ptr1 < one);
72 expect(1 > ptr1);
73 expect(one > ptr1);
74 expect(ptr1 < ptr2);
75 expect(ptr2 > ptr1);
76 expect(ptr2 >= 40);
77 expect(ptr2 == 40);
78 expect(ptr2 <= 40);
79 ptr2 -= 10;
80 expect(ptr1 == ptr2);
81 }
82 };
83 S.doTheTest();
84 comptime S.doTheTest();
85}
86
87test "peer type resolution with C pointers" {
88 var ptr_one: *u8 = undefined;
89 var ptr_many: [*]u8 = undefined;
90 var ptr_c: [*c]u8 = undefined;
91 var t = true;
92 var x1 = if (t) ptr_one else ptr_c;
93 var x2 = if (t) ptr_many else ptr_c;
94 var x3 = if (t) ptr_c else ptr_one;
95 var x4 = if (t) ptr_c else ptr_many;
96 expect(@typeOf(x1) == [*c]u8);
97 expect(@typeOf(x2) == [*c]u8);
98 expect(@typeOf(x3) == [*c]u8);
99 expect(@typeOf(x4) == [*c]u8);
100}
101
102test "implicit casting between C pointer and optional non-C pointer" {
103 var slice: []const u8 = "aoeu";
104 const opt_many_ptr: ?[*]const u8 = slice.ptr;
105 var ptr_opt_many_ptr = &opt_many_ptr;
106 var c_ptr: [*c]const [*c]const u8 = ptr_opt_many_ptr;
107 expect(c_ptr.*.* == 'a');
108 ptr_opt_many_ptr = c_ptr;
109 expect(ptr_opt_many_ptr.*.?[1] == 'o');
110}
111
112test "implicit cast error unions with non-optional to optional pointer" {
113 const S = struct {
114 fn doTheTest() void {
115 expectError(error.Fail, foo());
116 }
117 fn foo() anyerror!?*u8 {
118 return bar() orelse error.Fail;
119 }
120 fn bar() ?*u8 {
121 return null;
122 }
123 };
124 S.doTheTest();
125 comptime S.doTheTest();
126}
test/stage1/behavior/type_info.zig+15
......@@ -61,6 +61,21 @@ fn testUnknownLenPtr() void {
6161 expect(u32_ptr_info.Pointer.child == f64);
6262}
6363
64test "type info: C pointer type info" {
65 testCPtr();
66 comptime testCPtr();
67}
68
69fn testCPtr() void {
70 const ptr_info = @typeInfo([*c]align(4) const i8);
71 expect(TypeId(ptr_info) == TypeId.Pointer);
72 expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.C);
73 expect(ptr_info.Pointer.is_const);
74 expect(!ptr_info.Pointer.is_volatile);
75 expect(ptr_info.Pointer.alignment == 4);
76 expect(ptr_info.Pointer.child == i8);
77}
78
6479test "type info: slice type info" {
6580 testSlice();
6681 comptime testSlice();
test/translate_c.zig+31-31
......@@ -117,11 +117,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
117117 \\};
118118 ,
119119 \\pub const struct_Foo = extern struct {
120 \\ a: ?[*]Foo,
120 \\ a: [*c]Foo,
121121 \\};
122122 \\pub const Foo = struct_Foo;
123123 \\pub const struct_Bar = extern struct {
124 \\ a: ?[*]Foo,
124 \\ a: [*c]Foo,
125125 \\};
126126 );
127127
......@@ -213,7 +213,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
213213 ,
214214 \\const struct_Foo = extern struct {
215215 \\ x: c_int,
216 \\ y: ?[*]u8,
216 \\ y: [*c]u8,
217217 \\};
218218 ,
219219 \\pub const Foo = struct_Foo;
......@@ -244,7 +244,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
244244 ,
245245 \\pub const BarB = enum_Bar.B;
246246 ,
247 \\pub extern fn func(a: ?[*]struct_Foo, b: ?[*](?[*]enum_Bar)) void;
247 \\pub extern fn func(a: [*c]struct_Foo, b: [*c]([*c]enum_Bar)) void;
248248 ,
249249 \\pub const Foo = struct_Foo;
250250 ,
......@@ -254,7 +254,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
254254 cases.add("constant size array",
255255 \\void func(int array[20]);
256256 ,
257 \\pub extern fn func(array: ?[*]c_int) void;
257 \\pub extern fn func(array: [*c]c_int) void;
258258 );
259259
260260 cases.add("self referential struct with function pointer",
......@@ -263,7 +263,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
263263 \\};
264264 ,
265265 \\pub const struct_Foo = extern struct {
266 \\ derp: ?extern fn(?[*]struct_Foo) void,
266 \\ derp: ?extern fn([*c]struct_Foo) void,
267267 \\};
268268 ,
269269 \\pub const Foo = struct_Foo;
......@@ -322,11 +322,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
322322 \\};
323323 ,
324324 \\pub const struct_Bar = extern struct {
325 \\ next: ?[*]struct_Foo,
325 \\ next: [*c]struct_Foo,
326326 \\};
327327 ,
328328 \\pub const struct_Foo = extern struct {
329 \\ next: ?[*]struct_Bar,
329 \\ next: [*c]struct_Bar,
330330 \\};
331331 );
332332
......@@ -610,11 +610,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
610610 ,
611611 \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
612612 \\ if ((a != 0) and (b != 0)) return 0;
613 \\ if ((b != 0) and (c != null)) return 1;
614 \\ if ((a != 0) and (c != null)) return 2;
613 \\ if ((b != 0) and (c != 0)) return 1;
614 \\ if ((a != 0) and (c != 0)) return 2;
615615 \\ if ((a != 0) or (b != 0)) return 3;
616 \\ if ((b != 0) or (c != null)) return 4;
617 \\ if ((a != 0) or (c != null)) return 5;
616 \\ if ((b != 0) or (c != 0)) return 4;
617 \\ if ((a != 0) or (c != 0)) return 5;
618618 \\ return 6;
619619 \\}
620620 );
......@@ -710,7 +710,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
710710 \\pub const struct_Foo = extern struct {
711711 \\ field: c_int,
712712 \\};
713 \\pub export fn read_field(foo: ?[*]struct_Foo) c_int {
713 \\pub export fn read_field(foo: [*c]struct_Foo) c_int {
714714 \\ return foo.?.field;
715715 \\}
716716 );
......@@ -756,7 +756,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
756756 \\ return x;
757757 \\}
758758 ,
759 \\pub export fn foo(x: ?[*]c_ushort) ?*c_void {
759 \\pub export fn foo(x: [*c]c_ushort) ?*c_void {
760760 \\ return @ptrCast(?*c_void, x);
761761 \\}
762762 );
......@@ -777,8 +777,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
777777 \\ return 0;
778778 \\}
779779 ,
780 \\pub export fn foo() ?[*]c_int {
781 \\ return null;
780 \\pub export fn foo() [*c]c_int {
781 \\ return 0;
782782 \\}
783783 );
784784
......@@ -1086,7 +1086,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
10861086 \\ *x = 1;
10871087 \\}
10881088 ,
1089 \\pub export fn foo(x: ?[*]c_int) void {
1089 \\pub export fn foo(x: [*c]c_int) void {
10901090 \\ x.?.* = 1;
10911091 \\}
10921092 );
......@@ -1114,7 +1114,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
11141114 ,
11151115 \\pub fn foo() c_int {
11161116 \\ var x: c_int = 1234;
1117 \\ var ptr: ?[*]c_int = &x;
1117 \\ var ptr: [*c]c_int = &x;
11181118 \\ return ptr.?.*;
11191119 \\}
11201120 );
......@@ -1124,7 +1124,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
11241124 \\ return "bar";
11251125 \\}
11261126 ,
1127 \\pub fn foo() ?[*]const u8 {
1127 \\pub fn foo() [*c]const u8 {
11281128 \\ return c"bar";
11291129 \\}
11301130 );
......@@ -1253,8 +1253,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12531253 \\ return (float *)a;
12541254 \\}
12551255 ,
1256 \\fn ptrcast(a: ?[*]c_int) ?[*]f32 {
1257 \\ return @ptrCast(?[*]f32, a);
1256 \\fn ptrcast(a: [*c]c_int) [*c]f32 {
1257 \\ return @ptrCast([*c]f32, a);
12581258 \\}
12591259 );
12601260
......@@ -1280,7 +1280,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12801280 \\ return !(a == 0);
12811281 \\ return !(a != 0);
12821282 \\ return !(b != 0);
1283 \\ return !(c != null);
1283 \\ return !(c != 0);
12841284 \\}
12851285 );
12861286
......@@ -1297,7 +1297,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12971297 cases.add("const ptr initializer",
12981298 \\static const char *v0 = "0.0.0";
12991299 ,
1300 \\pub var v0: ?[*]const u8 = c"0.0.0";
1300 \\pub var v0: [*c]const u8 = c"0.0.0";
13011301 );
13021302
13031303 cases.add("static incomplete array inside function",
......@@ -1306,17 +1306,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13061306 \\}
13071307 ,
13081308 \\pub fn foo() void {
1309 \\ const v2: [*]const u8 = c"2.2.2";
1309 \\ const v2: [*c]const u8 = c"2.2.2";
13101310 \\}
13111311 );
13121312
13131313 cases.add("macro pointer cast",
13141314 \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
13151315 ,
1316 \\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast([*]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr([*]NRF_GPIO_Type, NRF_GPIO_BASE) else ([*]NRF_GPIO_Type)(NRF_GPIO_BASE);
1316 \\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else ([*c]NRF_GPIO_Type)(NRF_GPIO_BASE);
13171317 );
13181318
1319 cases.add("if on none bool",
1319 cases.add("if on non-bool",
13201320 \\enum SomeEnum { A, B, C };
13211321 \\int if_none_bool(int a, float b, void *c, enum SomeEnum d) {
13221322 \\ if (a) return 0;
......@@ -1337,13 +1337,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13371337 \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int {
13381338 \\ if (a != 0) return 0;
13391339 \\ if (b != 0) return 1;
1340 \\ if (c != null) return 2;
1340 \\ if (c != 0) return 2;
13411341 \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3;
13421342 \\ return 4;
13431343 \\}
13441344 );
13451345
1346 cases.add("while on none bool",
1346 cases.add("while on non-bool",
13471347 \\int while_none_bool(int a, float b, void *c) {
13481348 \\ while (a) return 0;
13491349 \\ while (b) return 1;
......@@ -1354,12 +1354,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13541354 \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
13551355 \\ while (a != 0) return 0;
13561356 \\ while (b != 0) return 1;
1357 \\ while (c != null) return 2;
1357 \\ while (c != 0) return 2;
13581358 \\ return 3;
13591359 \\}
13601360 );
13611361
1362 cases.add("for on none bool",
1362 cases.add("for on non-bool",
13631363 \\int for_none_bool(int a, float b, void *c) {
13641364 \\ for (;a;) return 0;
13651365 \\ for (;b;) return 1;
......@@ -1370,7 +1370,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13701370 \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
13711371 \\ while (a != 0) return 0;
13721372 \\ while (b != 0) return 1;
1373 \\ while (c != null) return 2;
1373 \\ while (c != 0) return 2;
13741374 \\ return 3;
13751375 \\}
13761376 );