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...@@ -916,6 +916,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
916 std.zig.Token.Id.AngleBracketAngleBracketRightEqual,916 std.zig.Token.Id.AngleBracketAngleBracketRightEqual,
917 std.zig.Token.Id.Tilde,917 std.zig.Token.Id.Tilde,
918 std.zig.Token.Id.BracketStarBracket,918 std.zig.Token.Id.BracketStarBracket,
919 std.zig.Token.Id.BracketStarCBracket,
919 => try writeEscaped(out, src[token.start..token.end]),920 => try writeEscaped(out, src[token.start..token.end]),
920921
921 std.zig.Token.Id.Invalid => return parseError(922 std.zig.Token.Id.Invalid => return parseError(
doc/langref.html.in+62-5
...@@ -1694,7 +1694,7 @@ test "comptime @intToPtr" {...@@ -1694,7 +1694,7 @@ test "comptime @intToPtr" {
1694 }1694 }
1695}1695}
1696 {#code_end#}1696 {#code_end#}
1697 {#see_also|Optional Pointers#}1697 {#see_also|Optional Pointers|@intToPtr|@ptrToInt#}
1698 {#header_open|volatile#}1698 {#header_open|volatile#}
1699 <p>Loads and stores are assumed to not have side effects. If a given load or store1699 <p>Loads and stores are assumed to not have side effects. If a given load or store
1700 should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}.1700 should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}.
...@@ -1823,7 +1823,9 @@ fn foo(bytes: []u8) u32 {...@@ -1823,7 +1823,9 @@ fn foo(bytes: []u8) u32 {
1823}1823}
1824 {#code_end#}1824 {#code_end#}
1825 {#header_close#}1825 {#header_close#}
1826 {#see_also|C Pointers#}
1826 {#header_close#}1827 {#header_close#}
1828
1827 {#header_open|Slices#}1829 {#header_open|Slices#}
1828 {#code_begin|test_safety|index out of bounds#}1830 {#code_begin|test_safety|index out of bounds#}
1829const assert = @import("std").debug.assert;1831const assert = @import("std").debug.assert;
...@@ -3981,7 +3983,7 @@ test "implicit cast - invoke a type as a function" {...@@ -3981,7 +3983,7 @@ test "implicit cast - invoke a type as a function" {
3981 {#code_end#}3983 {#code_end#}
3982 <p>3984 <p>
3983 Implicit casts are only allowed when it is completely unambiguous how to get from one type to another,3985 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#}.
3985 </p>3987 </p>
3986 {#header_open|Implicit Cast: Stricter Qualification#}3988 {#header_open|Implicit Cast: Stricter Qualification#}
3987 <p>3989 <p>
...@@ -6104,6 +6106,10 @@ test "call foo" {...@@ -6104,6 +6106,10 @@ test "call foo" {
6104 <p>6106 <p>
6105 Converts a pointer of one type to a pointer of another type.6107 Converts a pointer of one type to a pointer of another type.
6106 </p>6108 </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>
6107 {#header_close#}6113 {#header_close#}
61086114
6109 {#header_open|@ptrToInt#}6115 {#header_open|@ptrToInt#}
...@@ -7345,10 +7351,27 @@ fn bar(f: *Foo) void {...@@ -7345,10 +7351,27 @@ fn bar(f: *Foo) void {
7345 {#code_end#}7351 {#code_end#}
7346 {#header_close#}7352 {#header_close#}
73477353
7348 {#header_open|Out of Bounds Float To Integer Cast#}7354 {#header_open|Out of Bounds Float to Integer Cast#}
7349 <p>TODO</p>7355 <p>TODO</p>
7350 {#header_close#}7356 {#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
7352 {#header_close#}7375 {#header_close#}
7353 {#header_open|Memory#}7376 {#header_open|Memory#}
7354 <p>TODO: explain no default allocator in zig</p>7377 <p>TODO: explain no default allocator in zig</p>
...@@ -7439,6 +7462,7 @@ pub fn main() void {...@@ -7439,6 +7462,7 @@ pub fn main() void {
7439 {#code_end#}7462 {#code_end#}
7440 {#see_also|String Literals#}7463 {#see_also|String Literals#}
7441 {#header_close#}7464 {#header_close#}
7465
7442 {#header_open|Import from C Header File#}7466 {#header_open|Import from C Header File#}
7443 <p>7467 <p>
7444 The {#syntax#}@cImport{#endsyntax#} builtin function can be used7468 The {#syntax#}@cImport{#endsyntax#} builtin function can be used
...@@ -7477,6 +7501,36 @@ const c = @cImport({...@@ -7477,6 +7501,36 @@ const c = @cImport({
7477 {#code_end#}7501 {#code_end#}
7478 {#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#}7502 {#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#}
7479 {#header_close#}7503 {#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
7480 {#header_open|Exporting a C Library#}7534 {#header_open|Exporting a C Library#}
7481 <p>7535 <p>
7482 One of the primary use cases for Zig is exporting a library with the C ABI for other programming languages7536 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...@@ -8164,7 +8218,8 @@ ArrayTypeStart &lt;- LBRACKET Expr? RBRACKET
8164PtrTypeStart8218PtrTypeStart
8165 &lt;- ASTERISK8219 &lt;- ASTERISK
8166 / ASTERISK28220 / ASTERISK2
8167 / LBRACKET ASTERISK RBRACKET8221 / PTRUNKNOWN
8222 / PTRC
81688223
8169# ContainerDecl specific8224# ContainerDecl specific
8170ContainerDeclAuto &lt;- ContainerDeclType LBRACE ContainerMembers RBRACE8225ContainerDeclAuto &lt;- ContainerDeclType LBRACE ContainerMembers RBRACE
...@@ -8262,7 +8317,7 @@ LARROW2 &lt;- '&lt;&lt;' ![=] skip...@@ -8262,7 +8317,7 @@ LARROW2 &lt;- '&lt;&lt;' ![=] skip
8262LARROW2EQUAL &lt;- '&lt;&lt;=' skip8317LARROW2EQUAL &lt;- '&lt;&lt;=' skip
8263LARROWEQUAL &lt;- '&lt;=' skip8318LARROWEQUAL &lt;- '&lt;=' skip
8264LBRACE &lt;- '{' skip8319LBRACE &lt;- '{' skip
8265LBRACKET &lt;- '[' skip8320LBRACKET &lt;- '[' ![*] skip
8266LPAREN &lt;- '(' skip8321LPAREN &lt;- '(' skip
8267MINUS &lt;- '-' ![%=&gt;] skip8322MINUS &lt;- '-' ![%=&gt;] skip
8268MINUSEQUAL &lt;- '-=' skip8323MINUSEQUAL &lt;- '-=' skip
...@@ -8279,6 +8334,8 @@ PLUS2 &lt;- '++' skip...@@ -8279,6 +8334,8 @@ PLUS2 &lt;- '++' skip
8279PLUSEQUAL &lt;- '+=' skip8334PLUSEQUAL &lt;- '+=' skip
8280PLUSPERCENT &lt;- '+%' ![=] skip8335PLUSPERCENT &lt;- '+%' ![=] skip
8281PLUSPERCENTEQUAL &lt;- '+%=' skip8336PLUSPERCENTEQUAL &lt;- '+%=' skip
8337PTRC &lt;- '[*c]' skip
8338PTRUNKNOWN &lt;- '[*]' skip
8282QUESTIONMARK &lt;- '?' skip8339QUESTIONMARK &lt;- '?' skip
8283RARROW &lt;- '&gt;' ![&gt;=] skip8340RARROW &lt;- '&gt;' ![&gt;=] skip
8284RARROW2 &lt;- '&gt;&gt;' ![=] skip8341RARROW2 &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)...@@ -137,10 +137,10 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
137137
138pub const ObjectFile = struct {138pub const ObjectFile = struct {
139 comp: *Compilation,139 comp: *Compilation,
140 module: llvm.ModuleRef,140 module: *llvm.Module,
141 builder: llvm.BuilderRef,141 builder: *llvm.Builder,
142 dibuilder: *llvm.DIBuilder,142 dibuilder: *llvm.DIBuilder,
143 context: llvm.ContextRef,143 context: *llvm.Context,
144 lock: event.Lock,144 lock: event.Lock,
145 arena: *std.mem.Allocator,145 arena: *std.mem.Allocator,
146146
...@@ -323,7 +323,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)...@@ -323,7 +323,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
323323
324fn addLLVMAttr(324fn addLLVMAttr(
325 ofile: *ObjectFile,325 ofile: *ObjectFile,
326 val: llvm.ValueRef,326 val: *llvm.Value,
327 attr_index: llvm.AttributeIndex,327 attr_index: llvm.AttributeIndex,
328 attr_name: []const u8,328 attr_name: []const u8,
329) !void {329) !void {
...@@ -335,7 +335,7 @@ fn addLLVMAttr(...@@ -335,7 +335,7 @@ fn addLLVMAttr(
335335
336fn addLLVMAttrStr(336fn addLLVMAttrStr(
337 ofile: *ObjectFile,337 ofile: *ObjectFile,
338 val: llvm.ValueRef,338 val: *llvm.Value,
339 attr_index: llvm.AttributeIndex,339 attr_index: llvm.AttributeIndex,
340 attr_name: []const u8,340 attr_name: []const u8,
341 attr_val: []const u8,341 attr_val: []const u8,
...@@ -351,7 +351,7 @@ fn addLLVMAttrStr(...@@ -351,7 +351,7 @@ fn addLLVMAttrStr(
351}351}
352352
353fn addLLVMAttrInt(353fn addLLVMAttrInt(
354 val: llvm.ValueRef,354 val: *llvm.Value,
355 attr_index: llvm.AttributeIndex,355 attr_index: llvm.AttributeIndex,
356 attr_name: []const u8,356 attr_name: []const u8,
357 attr_val: u64,357 attr_val: u64,
...@@ -362,25 +362,25 @@ fn addLLVMAttrInt(...@@ -362,25 +362,25 @@ fn addLLVMAttrInt(
362 llvm.AddAttributeAtIndex(val, attr_index, llvm_attr);362 llvm.AddAttributeAtIndex(val, attr_index, llvm_attr);
363}363}
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 {
366 return addLLVMAttr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name);366 return addLLVMAttr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name);
367}367}
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 {
370 return addLLVMAttrStr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);370 return addLLVMAttrStr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);
371}371}
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 {
374 return addLLVMAttrInt(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);374 return addLLVMAttrInt(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);
375}375}
376376
377fn renderLoadUntyped(377fn renderLoadUntyped(
378 ofile: *ObjectFile,378 ofile: *ObjectFile,
379 ptr: llvm.ValueRef,379 ptr: *llvm.Value,
380 alignment: Type.Pointer.Align,380 alignment: Type.Pointer.Align,
381 vol: Type.Pointer.Vol,381 vol: Type.Pointer.Vol,
382 name: [*]const u8,382 name: [*]const u8,
383) !llvm.ValueRef {383) !*llvm.Value {
384 const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory;384 const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory;
385 switch (vol) {385 switch (vol) {
386 Type.Pointer.Vol.Non => {},386 Type.Pointer.Vol.Non => {},
...@@ -390,11 +390,11 @@ fn renderLoadUntyped(...@@ -390,11 +390,11 @@ fn renderLoadUntyped(
390 return result;390 return result;
391}391}
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 {
394 return renderLoadUntyped(ofile, ptr, ptr_type.key.alignment, ptr_type.key.vol, name);394 return renderLoadUntyped(ofile, ptr, ptr_type.key.alignment, ptr_type.key.vol, name);
395}395}
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 {
398 const child_type = ptr_type.key.child_type;398 const child_type = ptr_type.key.child_type;
399 if (!child_type.hasBits()) {399 if (!child_type.hasBits()) {
400 return null;400 return null;
...@@ -407,11 +407,11 @@ pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Po...@@ -407,11 +407,11 @@ pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Po
407407
408pub fn renderStoreUntyped(408pub fn renderStoreUntyped(
409 ofile: *ObjectFile,409 ofile: *ObjectFile,
410 value: llvm.ValueRef,410 value: *llvm.Value,
411 ptr: llvm.ValueRef,411 ptr: *llvm.Value,
412 alignment: Type.Pointer.Align,412 alignment: Type.Pointer.Align,
413 vol: Type.Pointer.Vol,413 vol: Type.Pointer.Vol,
414) !llvm.ValueRef {414) !*llvm.Value {
415 const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory;415 const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory;
416 switch (vol) {416 switch (vol) {
417 Type.Pointer.Vol.Non => {},417 Type.Pointer.Vol.Non => {},
...@@ -423,10 +423,10 @@ pub fn renderStoreUntyped(...@@ -423,10 +423,10 @@ pub fn renderStoreUntyped(
423423
424pub fn renderStore(424pub fn renderStore(
425 ofile: *ObjectFile,425 ofile: *ObjectFile,
426 value: llvm.ValueRef,426 value: *llvm.Value,
427 ptr: llvm.ValueRef,427 ptr: *llvm.Value,
428 ptr_type: *Type.Pointer,428 ptr_type: *Type.Pointer,
429) !llvm.ValueRef {429) !*llvm.Value {
430 return renderStoreUntyped(ofile, value, ptr, ptr_type.key.alignment, ptr_type.key.vol);430 return renderStoreUntyped(ofile, value, ptr, ptr_type.key.alignment, ptr_type.key.vol);
431}431}
432432
...@@ -435,7 +435,7 @@ pub fn renderAlloca(...@@ -435,7 +435,7 @@ pub fn renderAlloca(
435 var_type: *Type,435 var_type: *Type,
436 name: []const u8,436 name: []const u8,
437 alignment: Type.Pointer.Align,437 alignment: Type.Pointer.Align,
438) !llvm.ValueRef {438) !*llvm.Value {
439 const llvm_var_type = try var_type.getLlvmType(ofile.arena, ofile.context);439 const llvm_var_type = try var_type.getLlvmType(ofile.arena, ofile.context);
440 const name_with_null = try std.cstr.addNullByte(ofile.arena, name);440 const name_with_null = try std.cstr.addNullByte(ofile.arena, name);
441 const result = llvm.BuildAlloca(ofile.builder, llvm_var_type, name_with_null.ptr) orelse return error.OutOfMemory;441 const result = llvm.BuildAlloca(ofile.builder, llvm_var_type, name_with_null.ptr) orelse return error.OutOfMemory;
...@@ -443,7 +443,7 @@ pub fn renderAlloca(...@@ -443,7 +443,7 @@ pub fn renderAlloca(
443 return result;443 return result;
444}444}
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 {
447 return switch (alignment) {447 return switch (alignment) {
448 Type.Pointer.Align.Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type),448 Type.Pointer.Align.Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type),
449 Type.Pointer.Align.Override => |a| a,449 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...@@ -37,7 +37,7 @@ const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
37/// Data that is local to the event loop.37/// Data that is local to the event loop.
38pub const ZigCompiler = struct {38pub const ZigCompiler = struct {
39 loop: *event.Loop,39 loop: *event.Loop,
40 llvm_handle_pool: std.atomic.Stack(llvm.ContextRef),40 llvm_handle_pool: std.atomic.Stack(*llvm.Context),
41 lld_lock: event.Lock,41 lld_lock: event.Lock,
4242
43 /// TODO pool these so that it doesn't have to lock43 /// TODO pool these so that it doesn't have to lock
...@@ -60,7 +60,7 @@ pub const ZigCompiler = struct {...@@ -60,7 +60,7 @@ pub const ZigCompiler = struct {
60 return ZigCompiler{60 return ZigCompiler{
61 .loop = loop,61 .loop = loop,
62 .lld_lock = event.Lock.init(loop),62 .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(),
64 .prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)),64 .prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)),
65 .native_libc = event.Future(LibCInstallation).init(loop),65 .native_libc = event.Future(LibCInstallation).init(loop),
66 };66 };
...@@ -70,7 +70,7 @@ pub const ZigCompiler = struct {...@@ -70,7 +70,7 @@ pub const ZigCompiler = struct {
70 fn deinit(self: *ZigCompiler) void {70 fn deinit(self: *ZigCompiler) void {
71 self.lld_lock.deinit();71 self.lld_lock.deinit();
72 while (self.llvm_handle_pool.pop()) |node| {72 while (self.llvm_handle_pool.pop()) |node| {
73 c.LLVMContextDispose(node.data);73 llvm.ContextDispose(node.data);
74 self.loop.allocator.destroy(node);74 self.loop.allocator.destroy(node);
75 }75 }
76 }76 }
...@@ -80,11 +80,11 @@ pub const ZigCompiler = struct {...@@ -80,11 +80,11 @@ pub const ZigCompiler = struct {
80 pub fn getAnyLlvmContext(self: *ZigCompiler) !LlvmHandle {80 pub fn getAnyLlvmContext(self: *ZigCompiler) !LlvmHandle {
81 if (self.llvm_handle_pool.pop()) |node| return LlvmHandle{ .node = node };81 if (self.llvm_handle_pool.pop()) |node| return LlvmHandle{ .node = node };
8282
83 const context_ref = c.LLVMContextCreate() orelse return error.OutOfMemory;83 const context_ref = llvm.ContextCreate() orelse return error.OutOfMemory;
84 errdefer c.LLVMContextDispose(context_ref);84 errdefer llvm.ContextDispose(context_ref);
8585
86 const node = try self.loop.allocator.create(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.ContextRef).Node{87 node.* = std.atomic.Stack(*llvm.Context).Node{
88 .next = undefined,88 .next = undefined,
89 .data = context_ref,89 .data = context_ref,
90 };90 };
...@@ -114,7 +114,7 @@ pub const ZigCompiler = struct {...@@ -114,7 +114,7 @@ pub const ZigCompiler = struct {
114};114};
115115
116pub const LlvmHandle = struct {116pub const LlvmHandle = struct {
117 node: *std.atomic.Stack(llvm.ContextRef).Node,117 node: *std.atomic.Stack(*llvm.Context).Node,
118118
119 pub fn release(self: LlvmHandle, zig_compiler: *ZigCompiler) void {119 pub fn release(self: LlvmHandle, zig_compiler: *ZigCompiler) void {
120 zig_compiler.llvm_handle_pool.push(self.node);120 zig_compiler.llvm_handle_pool.push(self.node);
...@@ -128,7 +128,7 @@ pub const Compilation = struct {...@@ -128,7 +128,7 @@ pub const Compilation = struct {
128 llvm_triple: Buffer,128 llvm_triple: Buffer,
129 root_src_path: ?[]const u8,129 root_src_path: ?[]const u8,
130 target: Target,130 target: Target,
131 llvm_target: llvm.TargetRef,131 llvm_target: *llvm.Target,
132 build_mode: builtin.Mode,132 build_mode: builtin.Mode,
133 zig_lib_dir: []const u8,133 zig_lib_dir: []const u8,
134 zig_std_dir: []const u8,134 zig_std_dir: []const u8,
...@@ -212,8 +212,8 @@ pub const Compilation = struct {...@@ -212,8 +212,8 @@ pub const Compilation = struct {
212 false_value: *Value.Bool,212 false_value: *Value.Bool,
213 noreturn_value: *Value.NoReturn,213 noreturn_value: *Value.NoReturn,
214214
215 target_machine: llvm.TargetMachineRef,215 target_machine: *llvm.TargetMachine,
216 target_data_ref: llvm.TargetDataRef,216 target_data_ref: *llvm.TargetData,
217 target_layout_str: [*]u8,217 target_layout_str: [*]u8,
218 target_ptr_bits: u32,218 target_ptr_bits: u32,
219219
src-self-hosted/ir.zig+10-10
...@@ -67,7 +67,7 @@ pub const Inst = struct {...@@ -67,7 +67,7 @@ pub const Inst = struct {
67 parent: ?*Inst,67 parent: ?*Inst,
6868
69 /// populated durign codegen69 /// populated durign codegen
70 llvm_value: ?llvm.ValueRef,70 llvm_value: ?*llvm.Value,
7171
72 pub fn cast(base: *Inst, comptime T: type) ?*T {72 pub fn cast(base: *Inst, comptime T: type) ?*T {
73 if (base.id == comptime typeToId(T)) {73 if (base.id == comptime typeToId(T)) {
...@@ -129,7 +129,7 @@ pub const Inst = struct {...@@ -129,7 +129,7 @@ pub const Inst = struct {
129 }129 }
130 }130 }
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) {
133 switch (base.id) {133 switch (base.id) {
134 Id.Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val),134 Id.Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val),
135 Id.Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val),135 Id.Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val),
...@@ -313,10 +313,10 @@ pub const Inst = struct {...@@ -313,10 +313,10 @@ pub const Inst = struct {
313 return new_inst;313 return new_inst;
314 }314 }
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 {
317 const fn_ref = self.params.fn_ref.llvm_value.?;317 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);
320 for (self.params.args) |arg, i| {320 for (self.params.args) |arg, i| {
321 args[i] = arg.llvm_value.?;321 args[i] = arg.llvm_value.?;
322 }322 }
...@@ -360,7 +360,7 @@ pub const Inst = struct {...@@ -360,7 +360,7 @@ pub const Inst = struct {
360 return new_inst;360 return new_inst;
361 }361 }
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 {
364 return self.base.val.KnownValue.getLlvmConst(ofile);364 return self.base.val.KnownValue.getLlvmConst(ofile);
365 }365 }
366 };366 };
...@@ -392,7 +392,7 @@ pub const Inst = struct {...@@ -392,7 +392,7 @@ pub const Inst = struct {
392 return ira.irb.build(Return, self.base.scope, self.base.span, Params{ .return_value = casted_value });392 return ira.irb.build(Return, self.base.scope, self.base.span, Params{ .return_value = casted_value });
393 }393 }
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 {
396 const value = self.params.return_value.llvm_value;396 const value = self.params.return_value.llvm_value;
397 const return_type = self.params.return_value.getKnownType();397 const return_type = self.params.return_value.getKnownType();
398398
...@@ -540,7 +540,7 @@ pub const Inst = struct {...@@ -540,7 +540,7 @@ pub const Inst = struct {
540 }540 }
541 }541 }
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 {
544 switch (self.params.var_scope.data) {544 switch (self.params.var_scope.data) {
545 Scope.Var.Data.Const => unreachable, // turned into Inst.Const in analyze pass545 Scope.Var.Data.Const => unreachable, // turned into Inst.Const in analyze pass
546 Scope.Var.Data.Param => |param| return param.llvm_value,546 Scope.Var.Data.Param => |param| return param.llvm_value,
...@@ -596,7 +596,7 @@ pub const Inst = struct {...@@ -596,7 +596,7 @@ pub const Inst = struct {
596 return new_inst;596 return new_inst;
597 }597 }
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 {
600 const child_type = self.base.getKnownType();600 const child_type = self.base.getKnownType();
601 if (!child_type.hasBits()) {601 if (!child_type.hasBits()) {
602 return null;602 return null;
...@@ -935,8 +935,8 @@ pub const BasicBlock = struct {...@@ -935,8 +935,8 @@ pub const BasicBlock = struct {
935 ref_instruction: ?*Inst,935 ref_instruction: ?*Inst,
936936
937 /// for codegen937 /// for codegen
938 llvm_block: llvm.BasicBlockRef,938 llvm_block: *llvm.BasicBlock,
939 llvm_exit_block: llvm.BasicBlockRef,939 llvm_exit_block: *llvm.BasicBlock,
940940
941 /// the basic block that is derived from this one in analysis941 /// the basic block that is derived from this one in analysis
942 child: ?*BasicBlock,942 child: ?*BasicBlock,
src-self-hosted/libc_installation.zig+10-10
...@@ -154,8 +154,8 @@ pub const LibCInstallation = struct {...@@ -154,8 +154,8 @@ pub const LibCInstallation = struct {
154 c.ZigFindWindowsSdkError.None => {154 c.ZigFindWindowsSdkError.None => {
155 windows_sdk = sdk;155 windows_sdk = sdk;
156156
157 if (sdk.msvc_lib_dir_ptr) |ptr| {157 if (sdk.msvc_lib_dir_ptr != 0) {
158 self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, ptr[0..sdk.msvc_lib_dir_len]);158 self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, sdk.msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]);
159 }159 }
160 try group.call(findNativeKernel32LibDir, self, loop, sdk);160 try group.call(findNativeKernel32LibDir, self, loop, sdk);
161 try group.call(findNativeIncludeDirWindows, self, loop, sdk);161 try group.call(findNativeIncludeDirWindows, self, loop, sdk);
...@@ -437,20 +437,20 @@ const Search = struct {...@@ -437,20 +437,20 @@ const Search = struct {
437437
438fn fillSearch(search_buf: *[2]Search, sdk: *c.ZigWindowsSDK) []Search {438fn fillSearch(search_buf: *[2]Search, sdk: *c.ZigWindowsSDK) []Search {
439 var search_end: usize = 0;439 var search_end: usize = 0;
440 if (sdk.path10_ptr) |path10_ptr| {440 if (sdk.path10_ptr != 0) {
441 if (sdk.version10_ptr) |ver10_ptr| {441 if (sdk.version10_ptr != 0) {
442 search_buf[search_end] = Search{442 search_buf[search_end] = Search{
443 .path = path10_ptr[0..sdk.path10_len],443 .path = sdk.path10_ptr[0..sdk.path10_len],
444 .version = ver10_ptr[0..sdk.version10_len],444 .version = sdk.version10_ptr[0..sdk.version10_len],
445 };445 };
446 search_end += 1;446 search_end += 1;
447 }447 }
448 }448 }
449 if (sdk.path81_ptr) |path81_ptr| {449 if (sdk.path81_ptr != 0) {
450 if (sdk.version81_ptr) |ver81_ptr| {450 if (sdk.version81_ptr != 0) {
451 search_buf[search_end] = Search{451 search_buf[search_end] = Search{
452 .path = path81_ptr[0..sdk.path81_len],452 .path = sdk.path81_ptr[0..sdk.path81_len],
453 .version = ver81_ptr[0..sdk.version81_len],453 .version = sdk.version81_ptr[0..sdk.version81_len],
454 };454 };
455 search_end += 1;455 search_end += 1;
456 }456 }
src-self-hosted/llvm.zig+129-52
...@@ -11,45 +11,31 @@ const assert = @import("std").debug.assert;...@@ -11,45 +11,31 @@ const assert = @import("std").debug.assert;
11pub const AttributeIndex = c_uint;11pub const AttributeIndex = c_uint;
12pub const Bool = c_int;12pub const Bool = c_int;
1313
14pub const BuilderRef = removeNullability(c.LLVMBuilderRef);14pub const Builder = c.LLVMBuilderRef.Child.Child;
15pub const ContextRef = removeNullability(c.LLVMContextRef);15pub const Context = c.LLVMContextRef.Child.Child;
16pub const ModuleRef = removeNullability(c.LLVMModuleRef);16pub const Module = c.LLVMModuleRef.Child.Child;
17pub const ValueRef = removeNullability(c.LLVMValueRef);17pub const Value = c.LLVMValueRef.Child.Child;
18pub const TypeRef = removeNullability(c.LLVMTypeRef);18pub const Type = c.LLVMTypeRef.Child.Child;
19pub const BasicBlockRef = removeNullability(c.LLVMBasicBlockRef);19pub const BasicBlock = c.LLVMBasicBlockRef.Child.Child;
20pub const AttributeRef = removeNullability(c.LLVMAttributeRef);20pub const Attribute = c.LLVMAttributeRef.Child.Child;
21pub const TargetRef = removeNullability(c.LLVMTargetRef);21pub const Target = c.LLVMTargetRef.Child.Child;
22pub const TargetMachineRef = removeNullability(c.LLVMTargetMachineRef);22pub const TargetMachine = c.LLVMTargetMachineRef.Child.Child;
23pub const TargetDataRef = removeNullability(c.LLVMTargetDataRef);23pub const TargetData = c.LLVMTargetDataRef.Child.Child;
24pub const DIBuilder = c.ZigLLVMDIBuilder;24pub const DIBuilder = c.ZigLLVMDIBuilder;
25pub const DIFile = c.ZigLLVMDIFile;
26pub const DICompileUnit = c.ZigLLVMDICompileUnit;
2527
26pub const ABIAlignmentOfType = c.LLVMABIAlignmentOfType;28pub const ABIAlignmentOfType = c.LLVMABIAlignmentOfType;
27pub const AddAttributeAtIndex = c.LLVMAddAttributeAtIndex;29pub const AddAttributeAtIndex = c.LLVMAddAttributeAtIndex;
28pub const AddFunction = c.LLVMAddFunction;
29pub const AddGlobal = c.LLVMAddGlobal;
30pub const AddModuleCodeViewFlag = c.ZigLLVMAddModuleCodeViewFlag;30pub const AddModuleCodeViewFlag = c.ZigLLVMAddModuleCodeViewFlag;
31pub const AddModuleDebugInfoFlag = c.ZigLLVMAddModuleDebugInfoFlag;31pub const AddModuleDebugInfoFlag = c.ZigLLVMAddModuleDebugInfoFlag;
32pub const ArrayType = c.LLVMArrayType;
33pub const BuildLoad = c.LLVMBuildLoad;
34pub const ClearCurrentDebugLocation = c.ZigLLVMClearCurrentDebugLocation;32pub const ClearCurrentDebugLocation = c.ZigLLVMClearCurrentDebugLocation;
35pub const ConstAllOnes = c.LLVMConstAllOnes;33pub const ConstAllOnes = c.LLVMConstAllOnes;
36pub const ConstArray = c.LLVMConstArray;34pub const ConstArray = c.LLVMConstArray;
37pub const ConstBitCast = c.LLVMConstBitCast;35pub const ConstBitCast = c.LLVMConstBitCast;
38pub const ConstInt = c.LLVMConstInt;
39pub const ConstIntOfArbitraryPrecision = c.LLVMConstIntOfArbitraryPrecision;36pub const ConstIntOfArbitraryPrecision = c.LLVMConstIntOfArbitraryPrecision;
40pub const ConstNeg = c.LLVMConstNeg;37pub const ConstNeg = c.LLVMConstNeg;
41pub const ConstNull = c.LLVMConstNull;
42pub const ConstStringInContext = c.LLVMConstStringInContext;
43pub const ConstStructInContext = c.LLVMConstStructInContext;38pub 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;
53pub const DIBuilderFinalize = c.ZigLLVMDIBuilderFinalize;39pub const DIBuilderFinalize = c.ZigLLVMDIBuilderFinalize;
54pub const DisposeBuilder = c.LLVMDisposeBuilder;40pub const DisposeBuilder = c.LLVMDisposeBuilder;
55pub const DisposeDIBuilder = c.ZigLLVMDisposeDIBuilder;41pub const DisposeDIBuilder = c.ZigLLVMDisposeDIBuilder;
...@@ -62,9 +48,7 @@ pub const DumpModule = c.LLVMDumpModule;...@@ -62,9 +48,7 @@ pub const DumpModule = c.LLVMDumpModule;
62pub const FP128TypeInContext = c.LLVMFP128TypeInContext;48pub const FP128TypeInContext = c.LLVMFP128TypeInContext;
63pub const FloatTypeInContext = c.LLVMFloatTypeInContext;49pub const FloatTypeInContext = c.LLVMFloatTypeInContext;
64pub const GetEnumAttributeKindForName = c.LLVMGetEnumAttributeKindForName;50pub const GetEnumAttributeKindForName = c.LLVMGetEnumAttributeKindForName;
65pub const GetHostCPUName = c.ZigLLVMGetHostCPUName;
66pub const GetMDKindIDInContext = c.LLVMGetMDKindIDInContext;51pub const GetMDKindIDInContext = c.LLVMGetMDKindIDInContext;
67pub const GetNativeFeatures = c.ZigLLVMGetNativeFeatures;
68pub const GetUndef = c.LLVMGetUndef;52pub const GetUndef = c.LLVMGetUndef;
69pub const HalfTypeInContext = c.LLVMHalfTypeInContext;53pub const HalfTypeInContext = c.LLVMHalfTypeInContext;
70pub const InitializeAllAsmParsers = c.LLVMInitializeAllAsmParsers;54pub const InitializeAllAsmParsers = c.LLVMInitializeAllAsmParsers;
...@@ -81,14 +65,11 @@ pub const Int64TypeInContext = c.LLVMInt64TypeInContext;...@@ -81,14 +65,11 @@ pub const Int64TypeInContext = c.LLVMInt64TypeInContext;
81pub const Int8TypeInContext = c.LLVMInt8TypeInContext;65pub const Int8TypeInContext = c.LLVMInt8TypeInContext;
82pub const IntPtrTypeForASInContext = c.LLVMIntPtrTypeForASInContext;66pub const IntPtrTypeForASInContext = c.LLVMIntPtrTypeForASInContext;
83pub const IntPtrTypeInContext = c.LLVMIntPtrTypeInContext;67pub const IntPtrTypeInContext = c.LLVMIntPtrTypeInContext;
84pub const IntTypeInContext = c.LLVMIntTypeInContext;
85pub const LabelTypeInContext = c.LLVMLabelTypeInContext;68pub const LabelTypeInContext = c.LLVMLabelTypeInContext;
86pub const MDNodeInContext = c.LLVMMDNodeInContext;69pub const MDNodeInContext = c.LLVMMDNodeInContext;
87pub const MDStringInContext = c.LLVMMDStringInContext;70pub const MDStringInContext = c.LLVMMDStringInContext;
88pub const MetadataTypeInContext = c.LLVMMetadataTypeInContext;71pub const MetadataTypeInContext = c.LLVMMetadataTypeInContext;
89pub const ModuleCreateWithNameInContext = c.LLVMModuleCreateWithNameInContext;
90pub const PPCFP128TypeInContext = c.LLVMPPCFP128TypeInContext;72pub const PPCFP128TypeInContext = c.LLVMPPCFP128TypeInContext;
91pub const PointerType = c.LLVMPointerType;
92pub const SetAlignment = c.LLVMSetAlignment;73pub const SetAlignment = c.LLVMSetAlignment;
93pub const SetDataLayout = c.LLVMSetDataLayout;74pub const SetDataLayout = c.LLVMSetDataLayout;
94pub const SetGlobalConstant = c.LLVMSetGlobalConstant;75pub const SetGlobalConstant = c.LLVMSetGlobalConstant;
...@@ -99,50 +80,146 @@ pub const SetUnnamedAddr = c.LLVMSetUnnamedAddr;...@@ -99,50 +80,146 @@ pub const SetUnnamedAddr = c.LLVMSetUnnamedAddr;
99pub const SetVolatile = c.LLVMSetVolatile;80pub const SetVolatile = c.LLVMSetVolatile;
100pub const StructTypeInContext = c.LLVMStructTypeInContext;81pub const StructTypeInContext = c.LLVMStructTypeInContext;
101pub const TokenTypeInContext = c.LLVMTokenTypeInContext;82pub const TokenTypeInContext = c.LLVMTokenTypeInContext;
102pub const VoidTypeInContext = c.LLVMVoidTypeInContext;
103pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext;83pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext;
104pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext;84pub 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
106pub const GetElementType = LLVMGetElementType;183pub const GetElementType = LLVMGetElementType;
107extern fn LLVMGetElementType(Ty: TypeRef) TypeRef;184extern fn LLVMGetElementType(Ty: *Type) *Type;
108185
109pub const TypeOf = LLVMTypeOf;186pub const TypeOf = LLVMTypeOf;
110extern fn LLVMTypeOf(Val: ValueRef) TypeRef;187extern fn LLVMTypeOf(Val: *Value) *Type;
111188
112pub const BuildStore = LLVMBuildStore;189pub const BuildStore = LLVMBuildStore;
113extern fn LLVMBuildStore(arg0: BuilderRef, Val: ValueRef, Ptr: ValueRef) ?ValueRef;190extern fn LLVMBuildStore(arg0: *Builder, Val: *Value, Ptr: *Value) ?*Value;
114191
115pub const BuildAlloca = LLVMBuildAlloca;192pub 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
118pub const ConstInBoundsGEP = LLVMConstInBoundsGEP;195pub 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
121pub const GetTargetFromTriple = LLVMGetTargetFromTriple;198pub 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
124pub const VerifyModule = LLVMVerifyModule;201pub const VerifyModule = LLVMVerifyModule;
125extern fn LLVMVerifyModule(M: ModuleRef, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool;202extern fn LLVMVerifyModule(M: *Module, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool;
126203
127pub const GetInsertBlock = LLVMGetInsertBlock;204pub const GetInsertBlock = LLVMGetInsertBlock;
128extern fn LLVMGetInsertBlock(Builder: BuilderRef) BasicBlockRef;205extern fn LLVMGetInsertBlock(Builder: *Builder) *BasicBlock;
129206
130pub const FunctionType = LLVMFunctionType;207pub const FunctionType = LLVMFunctionType;
131extern fn LLVMFunctionType(208extern fn LLVMFunctionType(
132 ReturnType: TypeRef,209 ReturnType: *Type,
133 ParamTypes: [*]TypeRef,210 ParamTypes: [*]*Type,
134 ParamCount: c_uint,211 ParamCount: c_uint,
135 IsVarArg: Bool,212 IsVarArg: Bool,
136) ?TypeRef;213) ?*Type;
137214
138pub const GetParam = LLVMGetParam;215pub const GetParam = LLVMGetParam;
139extern fn LLVMGetParam(Fn: ValueRef, Index: c_uint) ValueRef;216extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;
140217
141pub const AppendBasicBlockInContext = LLVMAppendBasicBlockInContext;218pub 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
144pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd;221pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd;
145extern fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef) void;222extern fn LLVMPositionBuilderAtEnd(Builder: *Builder, Block: *BasicBlock) void;
146223
147pub const AbortProcessAction = VerifierFailureAction.LLVMAbortProcessAction;224pub const AbortProcessAction = VerifierFailureAction.LLVMAbortProcessAction;
148pub const PrintMessageAction = VerifierFailureAction.LLVMPrintMessageAction;225pub const PrintMessageAction = VerifierFailureAction.LLVMPrintMessageAction;
...@@ -190,17 +267,17 @@ pub const FnInline = extern enum {...@@ -190,17 +267,17 @@ pub const FnInline = extern enum {
190};267};
191268
192fn removeNullability(comptime T: type) type {269fn removeNullability(comptime T: type) type {
193 comptime assert(@typeId(T) == builtin.TypeId.Optional);270 comptime assert(@typeInfo(T).Pointer.size == @import("builtin").TypeInfo.Pointer.Size.C);
194 return T.Child;271 return *T.Child;
195}272}
196273
197pub const BuildRet = LLVMBuildRet;274pub const BuildRet = LLVMBuildRet;
198extern fn LLVMBuildRet(arg0: BuilderRef, V: ?ValueRef) ?ValueRef;275extern fn LLVMBuildRet(arg0: *Builder, V: ?*Value) ?*Value;
199276
200pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile;277pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile;
201extern fn ZigLLVMTargetMachineEmitToFile(278extern fn ZigLLVMTargetMachineEmitToFile(
202 targ_machine_ref: TargetMachineRef,279 targ_machine_ref: *TargetMachine,
203 module_ref: ModuleRef,280 module_ref: *Module,
204 filename: [*]const u8,281 filename: [*]const u8,
205 output_type: EmitOutputType,282 output_type: EmitOutputType,
206 error_message: *[*]u8,283 error_message: *[*]u8,
...@@ -209,6 +286,6 @@ extern fn ZigLLVMTargetMachineEmitToFile(...@@ -209,6 +286,6 @@ extern fn ZigLLVMTargetMachineEmitToFile(
209) bool;286) bool;
210287
211pub const BuildCall = ZigLLVMBuildCall;288pub 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
214pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage;291pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage;
src-self-hosted/scope.zig+1-1
...@@ -362,7 +362,7 @@ pub const Scope = struct {...@@ -362,7 +362,7 @@ pub const Scope = struct {
362 pub const Param = struct {362 pub const Param = struct {
363 index: usize,363 index: usize,
364 typ: *Type,364 typ: *Type,
365 llvm_value: llvm.ValueRef,365 llvm_value: *llvm.Value,
366 };366 };
367367
368 pub fn createParam(368 pub fn createParam(
src-self-hosted/target.zig+2-2
...@@ -457,8 +457,8 @@ pub const Target = union(enum) {...@@ -457,8 +457,8 @@ pub const Target = union(enum) {
457 }457 }
458 }458 }
459459
460 pub fn llvmTargetFromTriple(triple: std.Buffer) !llvm.TargetRef {460 pub fn llvmTargetFromTriple(triple: std.Buffer) !*llvm.Target {
461 var result: llvm.TargetRef = undefined;461 var result: *llvm.Target = undefined;
462 var err_msg: [*]u8 = undefined;462 var err_msg: [*]u8 = undefined;
463 if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) {463 if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) {
464 std.debug.warn("triple: {s} error: {s}\n", triple.ptr(), err_msg);464 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 {...@@ -51,8 +51,8 @@ pub const Type = struct {
51 pub fn getLlvmType(51 pub fn getLlvmType(
52 base: *Type,52 base: *Type,
53 allocator: *Allocator,53 allocator: *Allocator,
54 llvm_context: llvm.ContextRef,54 llvm_context: *llvm.Context,
55 ) (error{OutOfMemory}!llvm.TypeRef) {55 ) (error{OutOfMemory}!*llvm.Type) {
56 switch (base.id) {56 switch (base.id) {
57 Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context),57 Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context),
58 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context),58 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context),
...@@ -196,7 +196,7 @@ pub const Type = struct {...@@ -196,7 +196,7 @@ pub const Type = struct {
196 }196 }
197197
198 /// If you have an llvm conext handy, you can use it here.198 /// 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 {
200 if (await (async base.abi_alignment.start() catch unreachable)) |ptr| return ptr.*;200 if (await (async base.abi_alignment.start() catch unreachable)) |ptr| return ptr.*;
201201
202 base.abi_alignment.data = await (async base.resolveAbiAlignment(comp, llvm_context) catch unreachable);202 base.abi_alignment.data = await (async base.resolveAbiAlignment(comp, llvm_context) catch unreachable);
...@@ -205,7 +205,7 @@ pub const Type = struct {...@@ -205,7 +205,7 @@ pub const Type = struct {
205 }205 }
206206
207 /// Lower level function that does the work. See getAbiAlignment.207 /// 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 {
209 const llvm_type = try base.getLlvmType(comp.gpa(), llvm_context);209 const llvm_type = try base.getLlvmType(comp.gpa(), llvm_context);
210 return @intCast(u32, llvm.ABIAlignmentOfType(comp.target_data_ref, llvm_type));210 return @intCast(u32, llvm.ABIAlignmentOfType(comp.target_data_ref, llvm_type));
211 }211 }
...@@ -218,7 +218,7 @@ pub const Type = struct {...@@ -218,7 +218,7 @@ pub const Type = struct {
218 comp.gpa().destroy(self);218 comp.gpa().destroy(self);
219 }219 }
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 {
222 @panic("TODO");222 @panic("TODO");
223 }223 }
224 };224 };
...@@ -496,13 +496,13 @@ pub const Type = struct {...@@ -496,13 +496,13 @@ pub const Type = struct {
496 comp.gpa().destroy(self);496 comp.gpa().destroy(self);
497 }497 }
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 {
500 const normal = &self.key.data.Normal;500 const normal = &self.key.data.Normal;
501 const llvm_return_type = switch (normal.return_type.id) {501 const llvm_return_type = switch (normal.return_type.id) {
502 Type.Id.Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory,502 Type.Id.Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory,
503 else => try normal.return_type.getLlvmType(allocator, llvm_context),503 else => try normal.return_type.getLlvmType(allocator, llvm_context),
504 };504 };
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);
506 defer allocator.free(llvm_param_types);506 defer allocator.free(llvm_param_types);
507 for (llvm_param_types) |*llvm_param_type, i| {507 for (llvm_param_types) |*llvm_param_type, i| {
508 llvm_param_type.* = try normal.params[i].typ.getLlvmType(allocator, llvm_context);508 llvm_param_type.* = try normal.params[i].typ.getLlvmType(allocator, llvm_context);
...@@ -559,7 +559,7 @@ pub const Type = struct {...@@ -559,7 +559,7 @@ pub const Type = struct {
559 comp.gpa().destroy(self);559 comp.gpa().destroy(self);
560 }560 }
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 {
563 @panic("TODO");563 @panic("TODO");
564 }564 }
565 };565 };
...@@ -658,7 +658,7 @@ pub const Type = struct {...@@ -658,7 +658,7 @@ pub const Type = struct {
658 comp.gpa().destroy(self);658 comp.gpa().destroy(self);
659 }659 }
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 {
662 return llvm.IntTypeInContext(llvm_context, self.key.bit_count) orelse return error.OutOfMemory;662 return llvm.IntTypeInContext(llvm_context, self.key.bit_count) orelse return error.OutOfMemory;
663 }663 }
664 };664 };
...@@ -670,7 +670,7 @@ pub const Type = struct {...@@ -670,7 +670,7 @@ pub const Type = struct {
670 comp.gpa().destroy(self);670 comp.gpa().destroy(self);
671 }671 }
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 {
674 @panic("TODO");674 @panic("TODO");
675 }675 }
676 };676 };
...@@ -794,6 +794,7 @@ pub const Type = struct {...@@ -794,6 +794,7 @@ pub const Type = struct {
794 Size.One => "*",794 Size.One => "*",
795 Size.Many => "[*]",795 Size.Many => "[*]",
796 Size.Slice => "[]",796 Size.Slice => "[]",
797 Size.C => "[*c]",
797 };798 };
798 const mut_str = switch (self.key.mut) {799 const mut_str = switch (self.key.mut) {
799 Mut.Const => "const ",800 Mut.Const => "const ",
...@@ -835,7 +836,7 @@ pub const Type = struct {...@@ -835,7 +836,7 @@ pub const Type = struct {
835 return self;836 return self;
836 }837 }
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 {
839 const elem_llvm_type = try self.key.child_type.getLlvmType(allocator, llvm_context);840 const elem_llvm_type = try self.key.child_type.getLlvmType(allocator, llvm_context);
840 return llvm.PointerType(elem_llvm_type, 0) orelse return error.OutOfMemory;841 return llvm.PointerType(elem_llvm_type, 0) orelse return error.OutOfMemory;
841 }842 }
...@@ -903,7 +904,7 @@ pub const Type = struct {...@@ -903,7 +904,7 @@ pub const Type = struct {
903 return self;904 return self;
904 }905 }
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 {
907 const elem_llvm_type = try self.key.elem_type.getLlvmType(allocator, llvm_context);908 const elem_llvm_type = try self.key.elem_type.getLlvmType(allocator, llvm_context);
908 return llvm.ArrayType(elem_llvm_type, @intCast(c_uint, self.key.len)) orelse return error.OutOfMemory;909 return llvm.ArrayType(elem_llvm_type, @intCast(c_uint, self.key.len)) orelse return error.OutOfMemory;
909 }910 }
...@@ -916,7 +917,7 @@ pub const Type = struct {...@@ -916,7 +917,7 @@ pub const Type = struct {
916 comp.gpa().destroy(self);917 comp.gpa().destroy(self);
917 }918 }
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 {
920 @panic("TODO");921 @panic("TODO");
921 }922 }
922 };923 };
...@@ -966,7 +967,7 @@ pub const Type = struct {...@@ -966,7 +967,7 @@ pub const Type = struct {
966 comp.gpa().destroy(self);967 comp.gpa().destroy(self);
967 }968 }
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 {
970 @panic("TODO");971 @panic("TODO");
971 }972 }
972 };973 };
...@@ -978,7 +979,7 @@ pub const Type = struct {...@@ -978,7 +979,7 @@ pub const Type = struct {
978 comp.gpa().destroy(self);979 comp.gpa().destroy(self);
979 }980 }
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 {
982 @panic("TODO");983 @panic("TODO");
983 }984 }
984 };985 };
...@@ -990,7 +991,7 @@ pub const Type = struct {...@@ -990,7 +991,7 @@ pub const Type = struct {
990 comp.gpa().destroy(self);991 comp.gpa().destroy(self);
991 }992 }
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 {
994 @panic("TODO");995 @panic("TODO");
995 }996 }
996 };997 };
...@@ -1002,7 +1003,7 @@ pub const Type = struct {...@@ -1002,7 +1003,7 @@ pub const Type = struct {
1002 comp.gpa().destroy(self);1003 comp.gpa().destroy(self);
1003 }1004 }
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 {
1006 @panic("TODO");1007 @panic("TODO");
1007 }1008 }
1008 };1009 };
...@@ -1014,7 +1015,7 @@ pub const Type = struct {...@@ -1014,7 +1015,7 @@ pub const Type = struct {
1014 comp.gpa().destroy(self);1015 comp.gpa().destroy(self);
1015 }1016 }
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 {
1018 @panic("TODO");1019 @panic("TODO");
1019 }1020 }
1020 };1021 };
...@@ -1034,7 +1035,7 @@ pub const Type = struct {...@@ -1034,7 +1035,7 @@ pub const Type = struct {
1034 comp.gpa().destroy(self);1035 comp.gpa().destroy(self);
1035 }1036 }
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 {
1038 @panic("TODO");1039 @panic("TODO");
1039 }1040 }
1040 };1041 };
...@@ -1054,7 +1055,7 @@ pub const Type = struct {...@@ -1054,7 +1055,7 @@ pub const Type = struct {
1054 comp.gpa().destroy(self);1055 comp.gpa().destroy(self);
1055 }1056 }
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 {
1058 @panic("TODO");1059 @panic("TODO");
1059 }1060 }
1060 };1061 };
...@@ -1066,7 +1067,7 @@ pub const Type = struct {...@@ -1066,7 +1067,7 @@ pub const Type = struct {
1066 comp.gpa().destroy(self);1067 comp.gpa().destroy(self);
1067 }1068 }
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 {
1070 @panic("TODO");1071 @panic("TODO");
1071 }1072 }
1072 };1073 };
...@@ -1088,6 +1089,7 @@ fn hashAny(x: var, comptime seed: u64) u32 {...@@ -1088,6 +1089,7 @@ fn hashAny(x: var, comptime seed: u64) u32 {
1088 builtin.TypeInfo.Pointer.Size.One => return hashAny(@ptrToInt(x), seed),1089 builtin.TypeInfo.Pointer.Size.One => return hashAny(@ptrToInt(x), seed),
1089 builtin.TypeInfo.Pointer.Size.Many => @compileError("implement hash function"),1090 builtin.TypeInfo.Pointer.Size.Many => @compileError("implement hash function"),
1090 builtin.TypeInfo.Pointer.Size.Slice => @compileError("implement hash function"),1091 builtin.TypeInfo.Pointer.Size.Slice => @compileError("implement hash function"),
1092 builtin.TypeInfo.Pointer.Size.C => unreachable,
1091 }1093 }
1092 },1094 },
1093 builtin.TypeId.Enum => return hashAny(@enumToInt(x), seed),1095 builtin.TypeId.Enum => return hashAny(@enumToInt(x), seed),
src-self-hosted/value.zig+9-9
...@@ -57,7 +57,7 @@ pub const Value = struct {...@@ -57,7 +57,7 @@ pub const Value = struct {
57 std.debug.warn("{}", @tagName(base.id));57 std.debug.warn("{}", @tagName(base.id));
58 }58 }
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) {
61 switch (base.id) {61 switch (base.id) {
62 Id.Type => unreachable,62 Id.Type => unreachable,
63 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile),63 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile),
...@@ -153,7 +153,7 @@ pub const Value = struct {...@@ -153,7 +153,7 @@ pub const Value = struct {
153 comp.gpa().destroy(self);153 comp.gpa().destroy(self);
154 }154 }
155155
156 pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?llvm.ValueRef {156 pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?*llvm.Value {
157 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);157 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
158 const llvm_fn = llvm.AddFunction(158 const llvm_fn = llvm.AddFunction(
159 ofile.module,159 ofile.module,
...@@ -238,7 +238,7 @@ pub const Value = struct {...@@ -238,7 +238,7 @@ pub const Value = struct {
238 /// We know that the function definition will end up in an .o file somewhere.238 /// We know that the function definition will end up in an .o file somewhere.
239 /// Here, all we have to do is generate a global prototype.239 /// Here, all we have to do is generate a global prototype.
240 /// TODO cache the prototype per ObjectFile240 /// 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 {
242 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);242 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
243 const llvm_fn = llvm.AddFunction(243 const llvm_fn = llvm.AddFunction(
244 ofile.module,244 ofile.module,
...@@ -283,8 +283,8 @@ pub const Value = struct {...@@ -283,8 +283,8 @@ pub const Value = struct {
283 comp.gpa().destroy(self);283 comp.gpa().destroy(self);
284 }284 }
285285
286 pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) ?llvm.ValueRef {286 pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) !?*llvm.Value {
287 const llvm_type = llvm.Int1TypeInContext(ofile.context);287 const llvm_type = llvm.Int1TypeInContext(ofile.context) orelse return error.OutOfMemory;
288 if (self.x) {288 if (self.x) {
289 return llvm.ConstAllOnes(llvm_type);289 return llvm.ConstAllOnes(llvm_type);
290 } else {290 } else {
...@@ -381,7 +381,7 @@ pub const Value = struct {...@@ -381,7 +381,7 @@ pub const Value = struct {
381 comp.gpa().destroy(self);381 comp.gpa().destroy(self);
382 }382 }
383383
384 pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?llvm.ValueRef {384 pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?*llvm.Value {
385 const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context);385 const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context);
386 // TODO carefully port the logic from codegen.cpp:gen_const_val_ptr386 // TODO carefully port the logic from codegen.cpp:gen_const_val_ptr
387 switch (self.special) {387 switch (self.special) {
...@@ -391,7 +391,7 @@ pub const Value = struct {...@@ -391,7 +391,7 @@ pub const Value = struct {
391 const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;391 const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;
392 const ptr_bit_count = ofile.comp.target_ptr_bits;392 const ptr_bit_count = ofile.comp.target_ptr_bits;
393 const usize_llvm_type = llvm.IntTypeInContext(ofile.context, ptr_bit_count) orelse return error.OutOfMemory;393 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{
395 llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory,395 llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory,
396 llvm.ConstInt(usize_llvm_type, base_array.elem_index, 0) orelse return error.OutOfMemory,396 llvm.ConstInt(usize_llvm_type, base_array.elem_index, 0) orelse return error.OutOfMemory,
397 };397 };
...@@ -459,7 +459,7 @@ pub const Value = struct {...@@ -459,7 +459,7 @@ pub const Value = struct {
459 comp.gpa().destroy(self);459 comp.gpa().destroy(self);
460 }460 }
461461
462 pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?llvm.ValueRef {462 pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?*llvm.Value {
463 switch (self.special) {463 switch (self.special) {
464 Special.Undefined => {464 Special.Undefined => {
465 const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);465 const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
...@@ -534,7 +534,7 @@ pub const Value = struct {...@@ -534,7 +534,7 @@ pub const Value = struct {
534 return self;534 return self;
535 }535 }
536536
537 pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?llvm.ValueRef {537 pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?*llvm.Value {
538 switch (self.base.typ.id) {538 switch (self.base.typ.id) {
539 Type.Id.Int => {539 Type.Id.Int => {
540 const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);540 const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
src/all_types.hpp+13-3
...@@ -691,15 +691,17 @@ struct AstNodePointerType {...@@ -691,15 +691,17 @@ struct AstNodePointerType {
691 AstNode *align_expr;691 AstNode *align_expr;
692 BigInt *bit_offset_start;692 BigInt *bit_offset_start;
693 BigInt *host_int_bytes;693 BigInt *host_int_bytes;
694 AstNode *op_expr;
695 Token *allow_zero_token;
694 bool is_const;696 bool is_const;
695 bool is_volatile;697 bool is_volatile;
696 AstNode *op_expr;
697};698};
698699
699struct AstNodeArrayType {700struct AstNodeArrayType {
700 AstNode *size;701 AstNode *size;
701 AstNode *child_type;702 AstNode *child_type;
702 AstNode *align_expr;703 AstNode *align_expr;
704 Token *allow_zero_token;
703 bool is_const;705 bool is_const;
704 bool is_volatile;706 bool is_volatile;
705};707};
...@@ -1038,6 +1040,7 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);...@@ -1038,6 +1040,7 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
1038enum PtrLen {1040enum PtrLen {
1039 PtrLenUnknown,1041 PtrLenUnknown,
1040 PtrLenSingle,1042 PtrLenSingle,
1043 PtrLenC,
1041};1044};
10421045
1043struct ZigTypePointer {1046struct ZigTypePointer {
...@@ -1049,6 +1052,7 @@ struct ZigTypePointer {...@@ -1049,6 +1052,7 @@ struct ZigTypePointer {
1049 uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned1052 uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned
1050 bool is_const;1053 bool is_const;
1051 bool is_volatile;1054 bool is_volatile;
1055 bool allow_zero;
1052};1056};
10531057
1054struct ZigTypeInt {1058struct ZigTypeInt {
...@@ -1484,6 +1488,7 @@ enum PanicMsgId {...@@ -1484,6 +1488,7 @@ enum PanicMsgId {
1484 PanicMsgIdBadUnionField,1488 PanicMsgIdBadUnionField,
1485 PanicMsgIdBadEnumValue,1489 PanicMsgIdBadEnumValue,
1486 PanicMsgIdFloatToInt,1490 PanicMsgIdFloatToInt,
1491 PanicMsgIdPtrCastNull,
14871492
1488 PanicMsgIdCount,1493 PanicMsgIdCount,
1489};1494};
...@@ -1498,11 +1503,12 @@ struct TypeId {...@@ -1498,11 +1503,12 @@ struct TypeId {
1498 struct {1503 struct {
1499 ZigType *child_type;1504 ZigType *child_type;
1500 PtrLen ptr_len;1505 PtrLen ptr_len;
1501 bool is_const;
1502 bool is_volatile;
1503 uint32_t alignment;1506 uint32_t alignment;
1504 uint32_t bit_offset_in_host;1507 uint32_t bit_offset_in_host;
1505 uint32_t host_int_bytes;1508 uint32_t host_int_bytes;
1509 bool is_const;
1510 bool is_volatile;
1511 bool allow_zero;
1506 } pointer;1512 } pointer;
1507 struct {1513 struct {
1508 ZigType *child_type;1514 ZigType *child_type;
...@@ -2591,6 +2597,7 @@ struct IrInstructionPtrType {...@@ -2591,6 +2597,7 @@ struct IrInstructionPtrType {
2591 PtrLen ptr_len;2597 PtrLen ptr_len;
2592 bool is_const;2598 bool is_const;
2593 bool is_volatile;2599 bool is_volatile;
2600 bool allow_zero;
2594};2601};
25952602
2596struct IrInstructionPromiseType {2603struct IrInstructionPromiseType {
...@@ -2606,6 +2613,7 @@ struct IrInstructionSliceType {...@@ -2606,6 +2613,7 @@ struct IrInstructionSliceType {
2606 IrInstruction *child_type;2613 IrInstruction *child_type;
2607 bool is_const;2614 bool is_const;
2608 bool is_volatile;2615 bool is_volatile;
2616 bool allow_zero;
2609};2617};
26102618
2611struct IrInstructionAsm {2619struct IrInstructionAsm {
...@@ -2994,12 +3002,14 @@ struct IrInstructionPtrCastSrc {...@@ -2994,12 +3002,14 @@ struct IrInstructionPtrCastSrc {
29943002
2995 IrInstruction *dest_type;3003 IrInstruction *dest_type;
2996 IrInstruction *ptr;3004 IrInstruction *ptr;
3005 bool safety_check_on;
2997};3006};
29983007
2999struct IrInstructionPtrCastGen {3008struct IrInstructionPtrCastGen {
3000 IrInstruction base;3009 IrInstruction base;
30013010
3002 IrInstruction *ptr;3011 IrInstruction *ptr;
3012 bool safety_check_on;
3003};3013};
30043014
3005struct IrInstructionBitCast {3015struct IrInstructionBitCast {
src/analyze.cpp+83-14
...@@ -417,10 +417,25 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {...@@ -417,10 +417,25 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {
417 return entry;417 return entry;
418}418}
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
420ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,432ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
421 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,433 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
422 uint32_t bit_offset_in_host, uint32_t host_int_bytes)434 uint32_t bit_offset_in_host, uint32_t host_int_bytes)
423{435{
436 // TODO when implementing https://github.com/ziglang/zig/issues/1953
437 // move this to a parameter
438 bool allow_zero = (ptr_len == PtrLenC);
424 assert(!type_is_invalid(child_type));439 assert(!type_is_invalid(child_type));
425 assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);440 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...@@ -440,7 +455,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
440455
441 TypeId type_id = {};456 TypeId type_id = {};
442 ZigType **parent_pointer = nullptr;457 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) {
444 type_id.id = ZigTypeIdPointer;459 type_id.id = ZigTypeIdPointer;
445 type_id.data.pointer.child_type = child_type;460 type_id.data.pointer.child_type = child_type;
446 type_id.data.pointer.is_const = is_const;461 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...@@ -449,6 +464,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
449 type_id.data.pointer.bit_offset_in_host = bit_offset_in_host;464 type_id.data.pointer.bit_offset_in_host = bit_offset_in_host;
450 type_id.data.pointer.host_int_bytes = host_int_bytes;465 type_id.data.pointer.host_int_bytes = host_int_bytes;
451 type_id.data.pointer.ptr_len = ptr_len;466 type_id.data.pointer.ptr_len = ptr_len;
467 type_id.data.pointer.allow_zero = allow_zero;
452468
453 auto existing_entry = g->type_table.maybe_get(type_id);469 auto existing_entry = g->type_table.maybe_get(type_id);
454 if (existing_entry)470 if (existing_entry)
...@@ -466,21 +482,31 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -466,21 +482,31 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
466482
467 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);483 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);
470 const char *const_str = is_const ? "const " : "";486 const char *const_str = is_const ? "const " : "";
471 const char *volatile_str = is_volatile ? "volatile " : "";487 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 }
472 buf_resize(&entry->name, 0);495 buf_resize(&entry->name, 0);
473 if (host_int_bytes == 0 && byte_alignment == 0) {496 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));
475 } else if (host_int_bytes == 0) {499 } else if (host_int_bytes == 0) {
476 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment,500 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
477 const_str, volatile_str, buf_ptr(&child_type->name));501 const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
478 } else if (byte_alignment == 0) {502 } else if (byte_alignment == 0) {
479 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str,503 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str,
480 bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));504 bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
505 buf_ptr(&child_type->name));
481 } else {506 } else {
482 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment,507 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
483 bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));508 bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
509 buf_ptr(&child_type->name));
484 }510 }
485511
486 assert(child_type->id != ZigTypeIdInvalid);512 assert(child_type->id != ZigTypeIdInvalid);
...@@ -488,7 +514,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -488,7 +514,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
488 entry->zero_bits = !type_has_bits(child_type);514 entry->zero_bits = !type_has_bits(child_type);
489515
490 if (!entry->zero_bits) {516 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 {
492 ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false,520 ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false,
493 PtrLenSingle, 0, 0, host_int_bytes);521 PtrLenSingle, 0, 0, host_int_bytes);
494 entry->type_ref = peer_type->type_ref;522 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...@@ -522,6 +550,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
522 entry->data.pointer.explicit_alignment = byte_alignment;550 entry->data.pointer.explicit_alignment = byte_alignment;
523 entry->data.pointer.bit_offset_in_host = bit_offset_in_host;551 entry->data.pointer.bit_offset_in_host = bit_offset_in_host;
524 entry->data.pointer.host_int_bytes = host_int_bytes;552 entry->data.pointer.host_int_bytes = host_int_bytes;
553 entry->data.pointer.allow_zero = allow_zero;
525554
526 if (parent_pointer) {555 if (parent_pointer) {
527 *parent_pointer = entry;556 *parent_pointer = entry;
...@@ -838,7 +867,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {...@@ -838,7 +867,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
838867
839 ZigType *child_type = ptr_type->data.pointer.child_type;868 ZigType *child_type = ptr_type->data.pointer.child_type;
840 if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile ||869 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)
842 {871 {
843 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,872 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
844 PtrLenUnknown, 0, 0, 0);873 PtrLenUnknown, 0, 0, 0);
...@@ -861,7 +890,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {...@@ -861,7 +890,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
861 ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry;890 ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry;
862 assert(child_ptr_type->id == ZigTypeIdPointer);891 assert(child_ptr_type->id == ZigTypeIdPointer);
863 if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile ||892 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)
865 {894 {
866 ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;895 ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
867 ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false,896 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) {...@@ -1457,7 +1486,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {
1457 zig_unreachable();1486 zig_unreachable();
1458}1487}
14591488
1460static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {1489bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
1461 switch (type_entry->id) {1490 switch (type_entry->id) {
1462 case ZigTypeIdInvalid:1491 case ZigTypeIdInvalid:
1463 zig_unreachable();1492 zig_unreachable();
...@@ -2650,6 +2679,13 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2650,6 +2679,13 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
2650 buf_sprintf("enums, not structs, support field assignment"));2679 buf_sprintf("enums, not structs, support field assignment"));
2651 }2680 }
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
2653 switch (type_requires_comptime(g, field_type)) {2689 switch (type_requires_comptime(g, field_type)) {
2654 case ReqCompTimeYes:2690 case ReqCompTimeYes:
2655 struct_type->data.structure.requires_comptime = true;2691 struct_type->data.structure.requires_comptime = true;
...@@ -2934,6 +2970,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -2934,6 +2970,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
2934 }2970 }
2935 union_field->type_entry = field_type;2971 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
2937 switch (type_requires_comptime(g, field_type)) {2980 switch (type_requires_comptime(g, field_type)) {
2938 case ReqCompTimeInvalid:2981 case ReqCompTimeInvalid:
2939 union_type->data.unionation.is_invalid = true;2982 union_type->data.unionation.is_invalid = true;
...@@ -4041,7 +4084,9 @@ ZigType *get_src_ptr_type(ZigType *type) {...@@ -4041,7 +4084,9 @@ ZigType *get_src_ptr_type(ZigType *type) {
4041 if (type->id == ZigTypeIdFn) return type;4084 if (type->id == ZigTypeIdFn) return type;
4042 if (type->id == ZigTypeIdPromise) return type;4085 if (type->id == ZigTypeIdPromise) return type;
4043 if (type->id == ZigTypeIdOptional) {4086 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 }
4045 if (type->data.maybe.child_type->id == ZigTypeIdFn) return type->data.maybe.child_type;4090 if (type->data.maybe.child_type->id == ZigTypeIdFn) return type->data.maybe.child_type;
4046 if (type->data.maybe.child_type->id == ZigTypeIdPromise) return type->data.maybe.child_type;4091 if (type->data.maybe.child_type->id == ZigTypeIdPromise) return type->data.maybe.child_type;
4047 }4092 }
...@@ -4055,6 +4100,10 @@ ZigType *get_codegen_ptr_type(ZigType *type) {...@@ -4055,6 +4100,10 @@ ZigType *get_codegen_ptr_type(ZigType *type) {
4055 return ty;4100 return ty;
4056}4101}
40574102
4103bool type_is_nonnull_ptr(ZigType *type) {
4104 return type_is_codegen_pointer(type) && !ptr_allows_addr_zero(type);
4105}
4106
4058bool type_is_codegen_pointer(ZigType *type) {4107bool type_is_codegen_pointer(ZigType *type) {
4059 return get_codegen_ptr_type(type) == type;4108 return get_codegen_ptr_type(type) == type;
4060}4109}
...@@ -6300,6 +6349,7 @@ uint32_t type_id_hash(TypeId x) {...@@ -6300,6 +6349,7 @@ uint32_t type_id_hash(TypeId x) {
6300 ((x.data.pointer.ptr_len == PtrLenSingle) ? (uint32_t)1120226602 : (uint32_t)3200913342) +6349 ((x.data.pointer.ptr_len == PtrLenSingle) ? (uint32_t)1120226602 : (uint32_t)3200913342) +
6301 (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +6350 (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +
6302 (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) +6351 (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) +
6352 (x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) +
6303 (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +6353 (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +
6304 (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +6354 (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +
6305 (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);6355 (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);
...@@ -6350,6 +6400,7 @@ bool type_id_eql(TypeId a, TypeId b) {...@@ -6350,6 +6400,7 @@ bool type_id_eql(TypeId a, TypeId b) {
6350 a.data.pointer.ptr_len == b.data.pointer.ptr_len &&6400 a.data.pointer.ptr_len == b.data.pointer.ptr_len &&
6351 a.data.pointer.is_const == b.data.pointer.is_const &&6401 a.data.pointer.is_const == b.data.pointer.is_const &&
6352 a.data.pointer.is_volatile == b.data.pointer.is_volatile &&6402 a.data.pointer.is_volatile == b.data.pointer.is_volatile &&
6403 a.data.pointer.allow_zero == b.data.pointer.allow_zero &&
6353 a.data.pointer.alignment == b.data.pointer.alignment &&6404 a.data.pointer.alignment == b.data.pointer.alignment &&
6354 a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&6405 a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&
6355 a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes;6406 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...@@ -6883,3 +6934,21 @@ Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_no
68836934
6884 return ErrorNone;6935 return ErrorNone;
6885}6936}
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);...@@ -44,7 +44,9 @@ void find_libc_include_path(CodeGen *g);
44void find_libc_lib_path(CodeGen *g);44void find_libc_lib_path(CodeGen *g);
4545
46bool type_has_bits(ZigType *type_entry);46bool type_has_bits(ZigType *type_entry);
4747bool 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
49ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);51ImportTableEntry *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);...@@ -215,6 +217,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);
215X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty);217X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty);
216bool type_is_c_abi_int(CodeGen *g, ZigType *ty);218bool type_is_c_abi_int(CodeGen *g, ZigType *ty);
217bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id);219bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id);
220const char *container_string(ContainerKind kind);
218221
219uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field);222uint32_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) {...@@ -136,13 +136,19 @@ static const char *thread_local_string(Token *tok) {
136 return (tok == nullptr) ? "" : "threadlocal ";136 return (tok == nullptr) ? "" : "threadlocal ";
137}137}
138138
139const char *container_string(ContainerKind kind) {139static const char *token_to_ptr_len_str(Token *tok) {
140 switch (kind) {140 assert(tok != nullptr);
141 case ContainerKindEnum: return "enum";141 switch (tok->id) {
142 case ContainerKindStruct: return "struct";142 case TokenIdStar:
143 case ContainerKindUnion: return "union";143 case TokenIdStarStar:
144 return "*";
145 case TokenIdBracketStarBracket:
146 return "[*]";
147 case TokenIdBracketStarCBracket:
148 return "[*c]";
149 default:
150 zig_unreachable();
144 }151 }
145 zig_unreachable();
146}152}
147153
148static const char *node_type_str(NodeType node_type) {154static const char *node_type_str(NodeType node_type) {
...@@ -644,13 +650,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -644,13 +650,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
644 case NodeTypePointerType:650 case NodeTypePointerType:
645 {651 {
646 if (!grouped) fprintf(ar->f, "(");652 if (!grouped) fprintf(ar->f, "(");
647 const char *star = "[*]";653 const char *ptr_len_str = token_to_ptr_len_str(node->data.pointer_type.star_token);
648 if (node->data.pointer_type.star_token != nullptr &&654 fprintf(ar->f, "%s", ptr_len_str);
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);
654 if (node->data.pointer_type.align_expr != nullptr) {655 if (node->data.pointer_type.align_expr != nullptr) {
655 fprintf(ar->f, "align(");656 fprintf(ar->f, "align(");
656 render_node_grouped(ar, node->data.pointer_type.align_expr);657 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);...@@ -17,7 +17,4 @@ void ast_print(FILE *f, AstNode *node, int indent);
1717
18void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size);18void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size);
1919
20const char *container_string(ContainerKind kind);
21
22#endif20#endif
23
src/codegen.cpp+37-6
...@@ -617,9 +617,10 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {...@@ -617,9 +617,10 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
617 unsigned init_gen_i = 0;617 unsigned init_gen_i = 0;
618 if (!type_has_bits(return_type)) {618 if (!type_has_bits(return_type)) {
619 // nothing to do619 // nothing to do
620 } else if (type_is_codegen_pointer(return_type)) {620 } else if (type_is_nonnull_ptr(return_type)) {
621 addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");621 addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
622 } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {622 } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {
623 // Sret pointers must not be address 0
623 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");624 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");
624 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");625 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
625 if (cc_want_sret_attr(cc)) {626 if (cc_want_sret_attr(cc)) {
...@@ -637,6 +638,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {...@@ -637,6 +638,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
637638
638 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);639 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
639 if (err_ret_trace_arg_index != UINT32_MAX) {640 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.
640 addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull");643 addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull");
641 }644 }
642645
...@@ -950,6 +953,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {...@@ -950,6 +953,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
950 return buf_create_from_str("invalid enum value");953 return buf_create_from_str("invalid enum value");
951 case PanicMsgIdFloatToInt:954 case PanicMsgIdFloatToInt:
952 return buf_create_from_str("integer part of floating point value out of bounds");955 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");
953 }958 }
954 zig_unreachable();959 zig_unreachable();
955}960}
...@@ -1244,6 +1249,8 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {...@@ -1244,6 +1249,8 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {
1244 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));1249 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
1245 addLLVMFnAttr(fn_val, "nounwind");1250 addLLVMFnAttr(fn_val, "nounwind");
1246 add_uwtable_attr(g, fn_val);1251 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.
1247 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");1254 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
1248 if (g->build_mode == BuildModeDebug) {1255 if (g->build_mode == BuildModeDebug) {
1249 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");1256 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");
...@@ -1318,9 +1325,13 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {...@@ -1318,9 +1325,13 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
1318 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));1325 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
1319 addLLVMFnAttr(fn_val, "nounwind");1326 addLLVMFnAttr(fn_val, "nounwind");
1320 add_uwtable_attr(g, fn_val);1327 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.
1321 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");1330 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
1322 addLLVMArgAttr(fn_val, (unsigned)0, "noalias");1331 addLLVMArgAttr(fn_val, (unsigned)0, "noalias");
1323 addLLVMArgAttr(fn_val, (unsigned)0, "writeonly");1332 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.
1324 addLLVMArgAttr(fn_val, (unsigned)1, "nonnull");1335 addLLVMArgAttr(fn_val, (unsigned)1, "nonnull");
1325 addLLVMArgAttr(fn_val, (unsigned)1, "noalias");1336 addLLVMArgAttr(fn_val, (unsigned)1, "noalias");
1326 addLLVMArgAttr(fn_val, (unsigned)1, "readonly");1337 addLLVMArgAttr(fn_val, (unsigned)1, "readonly");
...@@ -1448,6 +1459,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {...@@ -1448,6 +1459,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
1448 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));1459 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
1449 addLLVMFnAttr(fn_val, "nounwind");1460 addLLVMFnAttr(fn_val, "nounwind");
1450 add_uwtable_attr(g, fn_val);1461 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.
1451 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");1464 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
1452 if (g->build_mode == BuildModeDebug) {1465 if (g->build_mode == BuildModeDebug) {
1453 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");1466 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_...@@ -2049,7 +2062,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
2049 case FnWalkIdAttrs: {2062 case FnWalkIdAttrs: {
2050 ZigType *ptr_type = get_codegen_ptr_type(ty);2063 ZigType *ptr_type = get_codegen_ptr_type(ty);
2051 if (ptr_type != nullptr) {2064 if (ptr_type != nullptr) {
2052 if (ty->id != ZigTypeIdOptional) {2065 if (type_is_nonnull_ptr(ty)) {
2053 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");2066 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
2054 }2067 }
2055 if (ptr_type->data.pointer.is_const) {2068 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_...@@ -2093,6 +2106,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
2093 assert(handle_is_ptr(ty));2106 assert(handle_is_ptr(ty));
2094 switch (fn_walk->id) {2107 switch (fn_walk->id) {
2095 case FnWalkIdAttrs:2108 case FnWalkIdAttrs:
2109 // arrays passed to C ABI functions may not be at address 0
2096 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");2110 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
2097 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));2111 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
2098 fn_walk->data.attrs.gen_i += 1;2112 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_...@@ -2132,6 +2146,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
2132 case FnWalkIdAttrs:2146 case FnWalkIdAttrs:
2133 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "byval");2147 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "byval");
2134 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));2148 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
2149 // Byvalue parameters must not have address 0
2135 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");2150 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
2136 fn_walk->data.attrs.gen_i += 1;2151 fn_walk->data.attrs.gen_i += 1;
2137 break;2152 break;
...@@ -2264,7 +2279,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {...@@ -2264,7 +2279,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
2264 if ((param_type->id == ZigTypeIdPointer && param_type->data.pointer.is_const) || is_byval) {2279 if ((param_type->id == ZigTypeIdPointer && param_type->data.pointer.is_const) || is_byval) {
2265 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "readonly");2280 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "readonly");
2266 }2281 }
2267 if (param_type->id == ZigTypeIdPointer) {2282 if (type_is_nonnull_ptr(param_type)) {
2268 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "nonnull");2283 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "nonnull");
2269 }2284 }
2270 break;2285 break;
...@@ -2657,7 +2672,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,...@@ -2657,7 +2672,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
2657 (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) ||2672 (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) ||
2658 (op1->value.type->id == ZigTypeIdPointer &&2673 (op1->value.type->id == ZigTypeIdPointer &&
2659 (op_id == IrBinOpAdd || op_id == IrBinOpSub) &&2674 (op_id == IrBinOpAdd || op_id == IrBinOpSub) &&
2660 op1->value.type->data.pointer.ptr_len == PtrLenUnknown)2675 op1->value.type->data.pointer.ptr_len != PtrLenSingle)
2661 );2676 );
2662 ZigType *operand_type = op1->value.type;2677 ZigType *operand_type = op1->value.type;
2663 ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;2678 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,...@@ -2716,7 +2731,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
2716 AddSubMulMul;2731 AddSubMulMul;
27172732
2718 if (scalar_type->id == ZigTypeIdPointer) {2733 if (scalar_type->id == ZigTypeIdPointer) {
2719 assert(scalar_type->data.pointer.ptr_len == PtrLenUnknown);2734 assert(scalar_type->data.pointer.ptr_len != PtrLenSingle);
2720 LLVMValueRef subscript_value;2735 LLVMValueRef subscript_value;
2721 if (operand_type->id == ZigTypeIdVector)2736 if (operand_type->id == ZigTypeIdVector)
2722 zig_panic("TODO: Implement vector operations on pointers.");2737 zig_panic("TODO: Implement vector operations on pointers.");
...@@ -3028,7 +3043,22 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,...@@ -3028,7 +3043,22 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
3028 return nullptr;3043 return nullptr;
3029 }3044 }
3030 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);3045 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;
3032}3062}
30333063
3034static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,3064static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,
...@@ -7294,6 +7324,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -7294,6 +7324,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
7294 " One,\n"7324 " One,\n"
7295 " Many,\n"7325 " Many,\n"
7296 " Slice,\n"7326 " Slice,\n"
7327 " C,\n"
7297 " };\n"7328 " };\n"
7298 " };\n"7329 " };\n"
7299 "\n"7330 "\n"
src/ir.cpp+450-167
...@@ -61,7 +61,7 @@ enum ConstCastResultId {...@@ -61,7 +61,7 @@ enum ConstCastResultId {
61 ConstCastResultIdType,61 ConstCastResultIdType,
62 ConstCastResultIdUnresolvedInferredErrSet,62 ConstCastResultIdUnresolvedInferredErrSet,
63 ConstCastResultIdAsyncAllocatorType,63 ConstCastResultIdAsyncAllocatorType,
64 ConstCastResultIdNullWrapPtr64 ConstCastResultIdBadAllowsZero,
65};65};
6666
67struct ConstCastOnly;67struct ConstCastOnly;
...@@ -83,6 +83,7 @@ struct ConstCastErrUnionErrSetMismatch;...@@ -83,6 +83,7 @@ struct ConstCastErrUnionErrSetMismatch;
83struct ConstCastErrUnionPayloadMismatch;83struct ConstCastErrUnionPayloadMismatch;
84struct ConstCastErrSetMismatch;84struct ConstCastErrSetMismatch;
85struct ConstCastTypeMismatch;85struct ConstCastTypeMismatch;
86struct ConstCastBadAllowsZero;
8687
87struct ConstCastOnly {88struct ConstCastOnly {
88 ConstCastResultId id;89 ConstCastResultId id;
...@@ -99,6 +100,7 @@ struct ConstCastOnly {...@@ -99,6 +100,7 @@ struct ConstCastOnly {
99 ConstCastOnly *null_wrap_ptr_child;100 ConstCastOnly *null_wrap_ptr_child;
100 ConstCastArg fn_arg;101 ConstCastArg fn_arg;
101 ConstCastArgNoAlias arg_no_alias;102 ConstCastArgNoAlias arg_no_alias;
103 ConstCastBadAllowsZero *bad_allows_zero;
102 } data;104 } data;
103};105};
104106
...@@ -141,6 +143,12 @@ struct ConstCastErrSetMismatch {...@@ -141,6 +143,12 @@ struct ConstCastErrSetMismatch {
141 ZigList<ErrorTableEntry *> missing_errors;143 ZigList<ErrorTableEntry *> missing_errors;
142};144};
143145
146struct ConstCastBadAllowsZero {
147 ZigType *wanted_type;
148 ZigType *actual_type;
149};
150
151
144enum UndefAllowed {152enum UndefAllowed {
145 UndefOk,153 UndefOk,
146 UndefBad,154 UndefBad,
...@@ -164,11 +172,15 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -164,11 +172,15 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
164static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,172static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
165 ConstExprValue *out_val, ConstExprValue *ptr_val);173 ConstExprValue *out_val, ConstExprValue *ptr_val);
166static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,174static 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);
168static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);176static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
169static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);177static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);
170static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);178static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
171static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry);179static 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
173static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {185static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
174 assert(get_src_ptr_type(const_val->type) != nullptr);186 assert(get_src_ptr_type(const_val->type) != nullptr);
...@@ -2190,12 +2202,13 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo...@@ -2190,12 +2202,13 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo
2190}2202}
21912203
2192static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node,2204static 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)
2194{2206{
2195 IrInstructionPtrCastSrc *instruction = ir_build_instruction<IrInstructionPtrCastSrc>(2207 IrInstructionPtrCastSrc *instruction = ir_build_instruction<IrInstructionPtrCastSrc>(
2196 irb, scope, source_node);2208 irb, scope, source_node);
2197 instruction->dest_type = dest_type;2209 instruction->dest_type = dest_type;
2198 instruction->ptr = ptr;2210 instruction->ptr = ptr;
2211 instruction->safety_check_on = safety_check_on;
21992212
2200 ir_ref_instruction(dest_type, irb->current_basic_block);2213 ir_ref_instruction(dest_type, irb->current_basic_block);
2201 ir_ref_instruction(ptr, irb->current_basic_block);2214 ir_ref_instruction(ptr, irb->current_basic_block);
...@@ -2204,12 +2217,13 @@ static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNod...@@ -2204,12 +2217,13 @@ static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNod
2204}2217}
22052218
2206static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction,2219static 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)
2208{2221{
2209 IrInstructionPtrCastGen *instruction = ir_build_instruction<IrInstructionPtrCastGen>(2222 IrInstructionPtrCastGen *instruction = ir_build_instruction<IrInstructionPtrCastGen>(
2210 &ira->new_irb, source_instruction->scope, source_instruction->source_node);2223 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
2211 instruction->base.value.type = ptr_type;2224 instruction->base.value.type = ptr_type;
2212 instruction->ptr = ptr;2225 instruction->ptr = ptr;
2226 instruction->safety_check_on = safety_check_on;
22132227
2214 ir_ref_instruction(ptr, ira->new_irb.current_basic_block);2228 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 *...@@ -2458,7 +2472,7 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode *
24582472
2459 ir_ref_instruction(type_value, irb->current_basic_block);2473 ir_ref_instruction(type_value, irb->current_basic_block);
24602474
2461 return &instruction->base; 2475 return &instruction->base;
2462}2476}
24632477
2464static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node,2478static 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...@@ -4493,7 +4507,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4493 if (arg1_value == irb->codegen->invalid_instruction)4507 if (arg1_value == irb->codegen->invalid_instruction)
4494 return arg1_value;4508 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);
4497 return ir_lval_wrap(irb, scope, ptr_cast, lval);4511 return ir_lval_wrap(irb, scope, ptr_cast, lval);
4498 }4512 }
4499 case BuiltinFnIdBitCast:4513 case BuiltinFnIdBitCast:
...@@ -5019,10 +5033,23 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *...@@ -5019,10 +5033,23 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *
5019 return ir_build_ref(irb, scope, value->source_node, value, false, false);5033 return ir_build_ref(irb, scope, value->source_node, value, false, false);
5020}5034}
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
5022static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) {5050static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) {
5023 assert(node->type == NodeTypePointerType);5051 assert(node->type == NodeTypePointerType);
5024 PtrLen ptr_len = (node->data.pointer_type.star_token->id == TokenIdStar ||5052 PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id);
5025 node->data.pointer_type.star_token->id == TokenIdStarStar) ? PtrLenSingle : PtrLenUnknown;
5026 bool is_const = node->data.pointer_type.is_const;5053 bool is_const = node->data.pointer_type.is_const;
5027 bool is_volatile = node->data.pointer_type.is_volatile;5054 bool is_volatile = node->data.pointer_type.is_volatile;
5028 AstNode *expr_node = node->data.pointer_type.op_expr;5055 AstNode *expr_node = node->data.pointer_type.op_expr;
...@@ -6715,14 +6742,15 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode...@@ -6715,14 +6742,15 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode
6715 IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b0106742 IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010
67166743
6717 // TODO relies on Zig not re-ordering fields6744 // 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);
6719 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);6747 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
6720 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);6748 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
6721 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,6749 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
6722 atomic_state_field_name);6750 atomic_state_field_name);
67236751
6724 // set the is_canceled bit6752 // 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,
6726 usize_type_val, atomic_state_ptr, nullptr, is_canceled_mask, nullptr,6754 usize_type_val, atomic_state_ptr, nullptr, is_canceled_mask, nullptr,
6727 AtomicRmwOp_or, AtomicOrderSeqCst);6755 AtomicRmwOp_or, AtomicOrderSeqCst);
67286756
...@@ -6793,14 +6821,15 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode...@@ -6793,14 +6821,15 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode
6793 get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));6821 get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));
67946822
6795 // TODO relies on Zig not re-ordering fields6823 // 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);
6797 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);6826 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
6798 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);6827 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
6799 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,6828 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
6800 atomic_state_field_name);6829 atomic_state_field_name);
68016830
6802 // clear the is_suspended bit6831 // 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,
6804 usize_type_val, atomic_state_ptr, nullptr, and_mask, nullptr,6833 usize_type_val, atomic_state_ptr, nullptr, and_mask, nullptr,
6805 AtomicRmwOp_and, AtomicOrderSeqCst);6834 AtomicRmwOp_and, AtomicOrderSeqCst);
68066835
...@@ -6916,7 +6945,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6916,7 +6945,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
69166945
6917 IrInstruction *coro_handle_addr = ir_build_ptr_to_int(irb, scope, node, irb->exec->coro_handle);6946 IrInstruction *coro_handle_addr = ir_build_ptr_to_int(irb, scope, node, irb->exec->coro_handle);
6918 IrInstruction *mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, coro_handle_addr, await_mask, false);6947 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,
6920 usize_type_val, atomic_state_ptr, nullptr, mask_bits, nullptr,6949 usize_type_val, atomic_state_ptr, nullptr, mask_bits, nullptr,
6921 AtomicRmwOp_or, AtomicOrderSeqCst);6950 AtomicRmwOp_or, AtomicOrderSeqCst);
69226951
...@@ -6959,7 +6988,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6959,7 +6988,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
69596988
69606989
6961 ir_set_cursor_at_end_and_append_block(irb, yes_suspend_block);6990 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,
6963 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, is_suspended_mask, nullptr,6992 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, is_suspended_mask, nullptr,
6964 AtomicRmwOp_or, AtomicOrderSeqCst);6993 AtomicRmwOp_or, AtomicOrderSeqCst);
6965 IrInstruction *my_is_suspended_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, my_prev_atomic_value, is_suspended_mask, false);6994 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...@@ -6991,7 +7020,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
69917020
6992 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);7021 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
6993 IrInstruction *my_mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, ptr_mask, is_canceled_mask, false);7022 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,
6995 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, my_mask_bits, nullptr,7024 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, my_mask_bits, nullptr,
6996 AtomicRmwOp_or, AtomicOrderSeqCst);7025 AtomicRmwOp_or, AtomicOrderSeqCst);
6997 IrInstruction *my_await_handle_addr = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, b_my_prev_atomic_value, ptr_mask, false);7026 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...@@ -7338,7 +7367,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
73387367
7339 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,7368 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,
7340 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));7369 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);
7342 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);7372 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);
7343 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);7373 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
7344 IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);7374 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...@@ -7362,7 +7392,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7362 ir_build_return(irb, coro_scope, node, undef);7392 ir_build_return(irb, coro_scope, node, undef);
73637393
7364 ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);7394 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);
7366 irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);7397 irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);
73677398
7368 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);7399 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...@@ -7440,9 +7471,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7440 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,7471 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
7441 false, false, PtrLenUnknown, 0, 0, 0));7472 false, false, PtrLenUnknown, 0, 0, 0));
7442 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);7473 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);7474 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
7444 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,7475 result_ptr, false);
7445 irb->exec->coro_result_field_ptr);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);
7446 IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,7478 IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,
7447 fn_entry->type_entry->data.fn.fn_type_id.return_type);7479 fn_entry->type_entry->data.fn.fn_type_id.return_type);
7448 IrInstruction *size_of_ret_val = ir_build_size_of(irb, scope, node, return_type_inst);7480 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...@@ -7492,7 +7524,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7492 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,7524 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
7493 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,7525 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
7494 false, false, PtrLenUnknown, 0, 0, 0));7526 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);
7496 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);7529 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
7497 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);7530 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
7498 IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);7531 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...@@ -8619,7 +8652,6 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp
8619 return err_set_type;8652 return err_set_type;
8620}8653}
86218654
8622
8623static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted_type,8655static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted_type,
8624 ZigType *actual_type, AstNode *source_node, bool wanted_is_mutable)8656 ZigType *actual_type, AstNode *source_node, bool wanted_is_mutable)
8625{8657{
...@@ -8632,53 +8664,63 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -8632,53 +8664,63 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
8632 if (wanted_type == actual_type)8664 if (wanted_type == actual_type)
8633 return result;8665 return result;
86348666
8635 // *T and [*]T may const-cast-only to ?*U and ?[*]U, respectively8667 // If pointers have the same representation in memory, they can be "const-casted".
8636 // but not if we want a mutable pointer8668 // `const` attribute can be gained
8637 // and not if the actual pointer has zero bits8669 // `volatile` attribute can be gained
8638 if (!wanted_is_mutable && wanted_type->id == ZigTypeIdOptional &&8670 // `allowzero` attribute can be gained (whether from explicit attribute, C pointer, or optional pointer)
8639 wanted_type->data.maybe.child_type->id == ZigTypeIdPointer &&8671 // but only if !wanted_is_mutable
8640 actual_type->id == ZigTypeIdPointer && type_has_bits(actual_type))8672 // alignment can be decreased
8641 {8673 // bit offset attributes must match exactly
8642 ConstCastOnly child = types_match_const_cast_only(ira,8674 // PtrLenSingle/PtrLenUnknown must match exactly, but PtrLenC matches either one
8643 wanted_type->data.maybe.child_type, actual_type, source_node, wanted_is_mutable);8675 ZigType *wanted_ptr_type = get_src_ptr_type(wanted_type);
8644 if (child.id == ConstCastResultIdInvalid)8676 ZigType *actual_ptr_type = get_src_ptr_type(actual_type);
8645 return child;8677 bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type);
8646 if (child.id != ConstCastResultIdOk) {8678 bool actual_allows_zero = ptr_allows_addr_zero(actual_type);
8647 result.id = ConstCastResultIdNullWrapPtr;8679 bool wanted_is_c_ptr = wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC;
8648 result.data.null_wrap_ptr_child = allocate_nonzero<ConstCastOnly>(1);8680 bool actual_is_c_ptr = actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenC;
8649 *result.data.null_wrap_ptr_child = child;8681 bool wanted_opt_or_ptr = wanted_ptr_type != nullptr &&
8650 }8682 (wanted_type->id == ZigTypeIdPointer || wanted_type->id == ZigTypeIdOptional);
8651 return result;8683 bool actual_opt_or_ptr = actual_ptr_type != nullptr &&
8652 }8684 (actual_type->id == ZigTypeIdPointer || actual_type->id == ZigTypeIdOptional);
86538685 if (wanted_opt_or_ptr && actual_opt_or_ptr) {
8654 // pointer const8686 ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type,
8655 if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) {8687 actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const);
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);
8658 if (child.id == ConstCastResultIdInvalid)8688 if (child.id == ConstCastResultIdInvalid)
8659 return child;8689 return child;
8660 if (child.id != ConstCastResultIdOk) {8690 if (child.id != ConstCastResultIdOk) {
8661 result.id = ConstCastResultIdPointerChild;8691 result.id = ConstCastResultIdPointerChild;
8662 result.data.pointer_mismatch = allocate_nonzero<ConstCastPointerMismatch>(1);8692 result.data.pointer_mismatch = allocate_nonzero<ConstCastPointerMismatch>(1);
8663 result.data.pointer_mismatch->child = child;8693 result.data.pointer_mismatch->child = child;
8664 result.data.pointer_mismatch->wanted_child = wanted_type->data.pointer.child_type;8694 result.data.pointer_mismatch->wanted_child = wanted_ptr_type->data.pointer.child_type;
8665 result.data.pointer_mismatch->actual_child = actual_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;
8666 return result;8706 return result;
8667 }8707 }
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))) {
8669 result.id = ConstCastResultIdInvalid;8709 result.id = ConstCastResultIdInvalid;
8670 return result;8710 return result;
8671 }8711 }
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))) {
8673 result.id = ConstCastResultIdInvalid;8713 result.id = ConstCastResultIdInvalid;
8674 return result;8714 return result;
8675 }8715 }
8676 if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) &&8716 bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
8677 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&8717 if ((ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr) &&
8678 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) &&8718 type_has_bits(wanted_type) == type_has_bits(actual_type) &&
8679 actual_type->data.pointer.bit_offset_in_host == wanted_type->data.pointer.bit_offset_in_host &&8719 (!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) &&
8680 actual_type->data.pointer.host_int_bytes == wanted_type->data.pointer.host_int_bytes &&8720 (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) &&
8681 get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type))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))
8682 {8724 {
8683 return result;8725 return result;
8684 }8726 }
...@@ -8912,7 +8954,9 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t *...@@ -8912,7 +8954,9 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t *
8912 *errors = reallocate(*errors, old_errors_count, *errors_count);8954 *errors = reallocate(*errors, old_errors_count, *errors_count);
8913}8955}
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{
8916 Error err;8960 Error err;
8917 assert(instruction_count >= 1);8961 assert(instruction_count >= 1);
8918 IrInstruction *prev_inst = instructions[0];8962 IrInstruction *prev_inst = instructions[0];
...@@ -9229,6 +9273,37 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -9229,6 +9273,37 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
9229 continue;9273 continue;
9230 }9274 }
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
9232 if (types_match_const_cast_only(ira, prev_type, cur_type, source_node, false).id == ConstCastResultIdOk) {9307 if (types_match_const_cast_only(ira, prev_type, cur_type, source_node, false).id == ConstCastResultIdOk) {
9233 continue;9308 continue;
9234 }9309 }
...@@ -9864,7 +9939,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un...@@ -9864,7 +9939,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
9864 if (undef_allowed == UndefOk) {9939 if (undef_allowed == UndefOk) {
9865 return &value->value;9940 return &value->value;
9866 } else {9941 } 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"));
9868 return nullptr;9943 return nullptr;
9869 }9944 }
9870 }9945 }
...@@ -10770,6 +10845,24 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa...@@ -10770,6 +10845,24 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
10770 report_recursive_error(ira, source_node, cast_result->data.fn_arg.child, msg);10845 report_recursive_error(ira, source_node, cast_result->data.fn_arg.child, msg);
10771 break;10846 break;
10772 }10847 }
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 }
10773 case ConstCastResultIdFnAlign: // TODO10866 case ConstCastResultIdFnAlign: // TODO
10774 case ConstCastResultIdFnCC: // TODO10867 case ConstCastResultIdFnCC: // TODO
10775 case ConstCastResultIdFnVarArgs: // TODO10868 case ConstCastResultIdFnVarArgs: // TODO
...@@ -10780,7 +10873,6 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa...@@ -10780,7 +10873,6 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
10780 case ConstCastResultIdFnArgNoAlias: // TODO10873 case ConstCastResultIdFnArgNoAlias: // TODO
10781 case ConstCastResultIdUnresolvedInferredErrSet: // TODO10874 case ConstCastResultIdUnresolvedInferredErrSet: // TODO
10782 case ConstCastResultIdAsyncAllocatorType: // TODO10875 case ConstCastResultIdAsyncAllocatorType: // TODO
10783 case ConstCastResultIdNullWrapPtr: // TODO
10784 break;10876 break;
10785 }10877 }
10786}10878}
...@@ -10811,6 +10903,39 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *...@@ -10811,6 +10903,39 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *
10811 return ir_build_vector_to_array(ira, source_instr, vector, array_type);10903 return ir_build_vector_to_array(ira, source_instr, vector, array_type);
10812}10904}
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
10814static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,10939static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
10815 ZigType *wanted_type, IrInstruction *value)10940 ZigType *wanted_type, IrInstruction *value)
10816{10941{
...@@ -11182,7 +11307,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11182,7 +11307,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11182 actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes &&11307 actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes &&
11183 get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type))11308 get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type))
11184 {11309 {
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);
11186 }11311 }
11187 }11312 }
1118811313
...@@ -11217,6 +11342,23 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11217,6 +11342,23 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11217 return ir_analyze_array_to_vector(ira, source_instr, value, wanted_type);11342 return ir_analyze_array_to_vector(ira, source_instr, value, wanted_type);
11218 }11343 }
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
11220 // cast from undefined to anything11362 // cast from undefined to anything
11221 if (actual_type->id == ZigTypeIdUndefined) {11363 if (actual_type->id == ZigTypeIdUndefined) {
11222 return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type);11364 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...@@ -11588,28 +11730,34 @@ static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
11588}11730}
1158911731
11590static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {11732static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {
11591 if (op_id == IrBinOpCmpEq) {11733 switch (op_id) {
11592 return cmp == CmpEQ;11734 case IrBinOpCmpEq:
11593 } else if (op_id == IrBinOpCmpNotEq) {11735 return cmp == CmpEQ;
11594 return cmp != CmpEQ;11736 case IrBinOpCmpNotEq:
11595 } else if (op_id == IrBinOpCmpLessThan) {11737 return cmp != CmpEQ;
11596 return cmp == CmpLT;11738 case IrBinOpCmpLessThan:
11597 } else if (op_id == IrBinOpCmpGreaterThan) {11739 return cmp == CmpLT;
11598 return cmp == CmpGT;11740 case IrBinOpCmpGreaterThan:
11599 } else if (op_id == IrBinOpCmpLessOrEq) {11741 return cmp == CmpGT;
11600 return cmp != CmpGT;11742 case IrBinOpCmpLessOrEq:
11601 } else if (op_id == IrBinOpCmpGreaterOrEq) {11743 return cmp != CmpGT;
11602 return cmp != CmpLT;11744 case IrBinOpCmpGreaterOrEq:
11603 } else {11745 return cmp != CmpLT;
11604 zig_unreachable();11746 default:
11747 zig_unreachable();
11605 }11748 }
11606}11749}
1160711750
11608static bool optional_value_is_null(ConstExprValue *val) {11751static bool optional_value_is_null(ConstExprValue *val) {
11609 assert(val->special == ConstValSpecialStatic);11752 assert(val->special == ConstValSpecialStatic);
11610 if (get_codegen_ptr_type(val->type) != nullptr) {11753 if (get_codegen_ptr_type(val->type) != nullptr) {
11611 return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&11754 if (val->data.x_ptr.special == ConstPtrSpecialNull) {
11612 val->data.x_ptr.data.hard_coded_addr.addr == 0;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 }
11613 } else if (is_opt_err_set(val->type)) {11761 } else if (is_opt_err_set(val->type)) {
11614 return val->data.x_err_set == nullptr;11762 return val->data.x_err_set == nullptr;
11615 } else {11763 } else {
...@@ -11773,7 +11921,6 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -11773,7 +11921,6 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
11773 case ZigTypeIdBool:11921 case ZigTypeIdBool:
11774 case ZigTypeIdMetaType:11922 case ZigTypeIdMetaType:
11775 case ZigTypeIdVoid:11923 case ZigTypeIdVoid:
11776 case ZigTypeIdPointer:
11777 case ZigTypeIdErrorSet:11924 case ZigTypeIdErrorSet:
11778 case ZigTypeIdFn:11925 case ZigTypeIdFn:
11779 case ZigTypeIdOpaque:11926 case ZigTypeIdOpaque:
...@@ -11785,6 +11932,10 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -11785,6 +11932,10 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
11785 operator_allowed = is_equality_cmp;11932 operator_allowed = is_equality_cmp;
11786 break;11933 break;
1178711934
11935 case ZigTypeIdPointer:
11936 operator_allowed = is_equality_cmp || (resolved_type->data.pointer.ptr_len == PtrLenC);
11937 break;
11938
11788 case ZigTypeIdUnreachable:11939 case ZigTypeIdUnreachable:
11789 case ZigTypeIdArray:11940 case ZigTypeIdArray:
11790 case ZigTypeIdStruct:11941 case ZigTypeIdStruct:
...@@ -11832,15 +11983,38 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -11832,15 +11983,38 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
11832 if (op2_val == nullptr)11983 if (op2_val == nullptr)
11833 return ira->codegen->invalid_instruction;11984 return ira->codegen->invalid_instruction;
1183411985
11835 bool answer;
11836 if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) {11986 if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) {
11837 Cmp cmp_result = float_cmp(op1_val, op2_val);11987 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);
11839 } else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) {11990 } else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) {
11840 Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint);11991 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 }
11842 } else {12015 } else {
11843 bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val);12016 bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val);
12017 bool answer;
11844 if (op_id == IrBinOpCmpEq) {12018 if (op_id == IrBinOpCmpEq) {
11845 answer = are_equal;12019 answer = are_equal;
11846 } else if (op_id == IrBinOpCmpNotEq) {12020 } else if (op_id == IrBinOpCmpNotEq) {
...@@ -11848,9 +12022,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -11848,9 +12022,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
11848 } else {12022 } else {
11849 zig_unreachable();12023 zig_unreachable();
11850 }12024 }
12025 return ir_const_bool(ira, &bin_op_instruction->base, answer);
11851 }12026 }
11852
11853 return ir_const_bool(ira, &bin_op_instruction->base, answer);
11854 }12027 }
1185512028
11856 // some comparisons with unsigned numbers can be evaluated12029 // some comparisons with unsigned numbers can be evaluated
...@@ -12245,7 +12418,29 @@ static bool ok_float_op(IrBinOp op) {...@@ -12245,7 +12418,29 @@ static bool ok_float_op(IrBinOp op) {
12245 zig_unreachable();12418 zig_unreachable();
12246}12419}
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
12248static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) {12441static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) {
12442 Error err;
12443
12249 IrInstruction *op1 = instruction->op1->child;12444 IrInstruction *op1 = instruction->op1->child;
12250 if (type_is_invalid(op1->value.type))12445 if (type_is_invalid(op1->value.type))
12251 return ira->codegen->invalid_instruction;12446 return ira->codegen->invalid_instruction;
...@@ -12257,13 +12452,44 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -12257,13 +12452,44 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
12257 IrBinOp op_id = instruction->op_id;12452 IrBinOp op_id = instruction->op_id;
1225812453
12259 // look for pointer math12454 // look for pointer math
12260 if (op1->value.type->id == ZigTypeIdPointer && op1->value.type->data.pointer.ptr_len == PtrLenUnknown &&12455 if (is_pointer_arithmetic_allowed(op1->value.type, op_id)) {
12261 (op_id == IrBinOpAdd || op_id == IrBinOpSub))
12262 {
12263 IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize);12456 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))
12265 return ira->codegen->invalid_instruction;12458 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
12267 IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,12493 IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,
12268 instruction->base.source_node, op_id, op1, casted_op2, true);12494 instruction->base.source_node, op_id, op1, casted_op2, true);
12269 result->value.type = op1->value.type;12495 result->value.type = op1->value.type;
...@@ -16366,7 +16592,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -16366,7 +16592,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
16366 pointee_val = const_ptr_pointee(ira, ira->codegen, &target_value_ptr->value, target_value_ptr->source_node);16592 pointee_val = const_ptr_pointee(ira, ira->codegen, &target_value_ptr->value, target_value_ptr->source_node);
16367 if (pointee_val == nullptr)16593 if (pointee_val == nullptr)
16368 return ira->codegen->invalid_instruction;16594 return ira->codegen->invalid_instruction;
16369 16595
16370 if (pointee_val->special == ConstValSpecialRuntime)16596 if (pointee_val->special == ConstValSpecialRuntime)
16371 pointee_val = nullptr;16597 pointee_val = nullptr;
16372 }16598 }
...@@ -17116,7 +17342,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,...@@ -17116,7 +17342,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
17116static TypeStructField *validate_byte_offset(IrAnalyze *ira,17342static TypeStructField *validate_byte_offset(IrAnalyze *ira,
17117 IrInstruction *type_value,17343 IrInstruction *type_value,
17118 IrInstruction *field_name_value,17344 IrInstruction *field_name_value,
17119 size_t *byte_offset) 17345 size_t *byte_offset)
17120{17346{
17121 ZigType *container_type = ir_resolve_type(ira, type_value);17347 ZigType *container_type = ir_resolve_type(ira, type_value);
17122 if (type_is_invalid(container_type))17348 if (type_is_invalid(container_type))
...@@ -17290,7 +17516,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco...@@ -17290,7 +17516,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
1729017516
17291 // Loop through the definitions and generate info.17517 // Loop through the definitions and generate info.
17292 decl_it = decls_scope->decl_table.entry_iterator();17518 decl_it = decls_scope->decl_table.entry_iterator();
17293 curr_entry = nullptr; 17519 curr_entry = nullptr;
17294 int definition_index = 0;17520 int definition_index = 0;
17295 while ((curr_entry = decl_it.next()) != nullptr) {17521 while ((curr_entry = decl_it.next()) != nullptr) {
17296 // Skip comptime blocks and test functions.17522 // Skip comptime blocks and test functions.
...@@ -17469,6 +17695,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco...@@ -17469,6 +17695,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
17469 return ErrorNone;17695 return ErrorNone;
17470}17696}
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
17472static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) {17710static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) {
17473 Error err;17711 Error err;
17474 ZigType *attrs_type;17712 ZigType *attrs_type;
...@@ -17478,7 +17716,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty...@@ -17478,7 +17716,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
17478 size_enum_index = 2;17716 size_enum_index = 2;
17479 } else if (ptr_type_entry->id == ZigTypeIdPointer) {17717 } else if (ptr_type_entry->id == ZigTypeIdPointer) {
17480 attrs_type = ptr_type_entry;17718 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);
17482 } else {17720 } else {
17483 zig_unreachable();17721 zig_unreachable();
17484 }17722 }
...@@ -20236,7 +20474,7 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,...@@ -20236,7 +20474,7 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
20236 } else {20474 } else {
20237 seenFalse += 1;20475 seenFalse += 1;
20238 }20476 }
20239 20477
20240 if ((seenTrue > 1) || (seenFalse > 1)) {20478 if ((seenTrue > 1) || (seenFalse > 1)) {
20241 ir_add_error(ira, value, buf_sprintf("duplicate switch value"));20479 ir_add_error(ira, value, buf_sprintf("duplicate switch value"));
20242 return ira->codegen->invalid_instruction;20480 return ira->codegen->invalid_instruction;
...@@ -20369,7 +20607,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3...@@ -20369,7 +20607,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
20369}20607}
2037020608
20371static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,20609static 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)
20373{20611{
20374 Error err;20612 Error err;
2037520613
...@@ -20379,12 +20617,14 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -20379,12 +20617,14 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
20379 // We have a check for zero bits later so we use get_src_ptr_type to20617 // We have a check for zero bits later so we use get_src_ptr_type to
20380 // validate src_type and dest_type.20618 // 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) {
20383 ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));20622 ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));
20384 return ira->codegen->invalid_instruction;20623 return ira->codegen->invalid_instruction;
20385 }20624 }
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) {
20388 ir_add_error(ira, dest_type_src,20628 ir_add_error(ira, dest_type_src,
20389 buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));20629 buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
20390 return ira->codegen->invalid_instruction;20630 return ira->codegen->invalid_instruction;
...@@ -20396,10 +20636,23 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -20396,10 +20636,23 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
20396 }20636 }
2039720637
20398 if (instr_is_comptime(ptr)) {20638 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);
20400 if (!val)20642 if (!val)
20401 return ira->codegen->invalid_instruction;20643 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
20403 IrInstruction *result = ir_const(ira, source_instr, dest_type);20656 IrInstruction *result = ir_const(ira, source_instr, dest_type);
20404 copy_const_val(&result->value, val, false);20657 copy_const_val(&result->value, val, false);
20405 result->value.type = dest_type;20658 result->value.type = dest_type;
...@@ -20423,7 +20676,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -20423,7 +20676,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
20423 return ira->codegen->invalid_instruction;20676 return ira->codegen->invalid_instruction;
20424 }20677 }
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
20428 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {20681 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
20429 ErrorMsg *msg = ir_add_error(ira, source_instr,20682 ErrorMsg *msg = ir_add_error(ira, source_instr,
...@@ -20460,7 +20713,8 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct...@@ -20460,7 +20713,8 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct
20460 if (type_is_invalid(src_type))20713 if (type_is_invalid(src_type))
20461 return ira->codegen->invalid_instruction;20714 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);
20464}20718}
2046520719
20466static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ConstExprValue *val, size_t len) {20720static 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...@@ -20668,32 +20922,10 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
20668 zig_unreachable();20922 zig_unreachable();
20669}20923}
2067020924
20671static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {20925static bool type_can_bit_cast(ZigType *t) {
20672 Error err;20926 switch (t->id) {
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) {
20696 case ZigTypeIdInvalid:20927 case ZigTypeIdInvalid:
20928 zig_unreachable();
20697 case ZigTypeIdMetaType:20929 case ZigTypeIdMetaType:
20698 case ZigTypeIdOpaque:20930 case ZigTypeIdOpaque:
20699 case ZigTypeIdBoundFn:20931 case ZigTypeIdBoundFn:
...@@ -20704,42 +20936,36 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct...@@ -20704,42 +20936,36 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
20704 case ZigTypeIdComptimeInt:20936 case ZigTypeIdComptimeInt:
20705 case ZigTypeIdUndefined:20937 case ZigTypeIdUndefined:
20706 case ZigTypeIdNull:20938 case ZigTypeIdNull:
20707 ir_add_error(ira, dest_type_value,20939 case ZigTypeIdPointer:
20708 buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));20940 return false;
20709 return ira->codegen->invalid_instruction;
20710 default:20941 default:
20711 break;20942 // TODO list these types out explicitly, there are probably some other invalid ones here
20943 return true;
20712 }20944 }
20945}
2071320946
20714 if (get_codegen_ptr_type(dest_type) != nullptr) {20947static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
20715 ir_add_error(ira, dest_type_value,20948 ZigType *dest_type)
20716 buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));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)))
20717 return ira->codegen->invalid_instruction;20962 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
20739 uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);20965 uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);
20740 uint64_t src_size_bytes = type_size(ira->codegen, src_type);20966 uint64_t src_size_bytes = type_size(ira->codegen, src_type);
20741 if (dest_size_bytes != src_size_bytes) {20967 if (dest_size_bytes != src_size_bytes) {
20742 ir_add_error(ira, &instruction->base,20968 ir_add_error(ira, source_instr,
20743 buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,20969 buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,
20744 buf_ptr(&dest_type->name), dest_size_bytes,20970 buf_ptr(&dest_type->name), dest_size_bytes,
20745 buf_ptr(&src_type->name), src_size_bytes));20971 buf_ptr(&src_type->name), src_size_bytes));
...@@ -20749,7 +20975,7 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct...@@ -20749,7 +20975,7 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
20749 uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type);20975 uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type);
20750 uint64_t src_size_bits = type_size_bits(ira->codegen, src_type);20976 uint64_t src_size_bits = type_size_bits(ira->codegen, src_type);
20751 if (dest_size_bits != src_size_bits) {20977 if (dest_size_bits != src_size_bits) {
20752 ir_add_error(ira, &instruction->base,20978 ir_add_error(ira, source_instr,
20753 buf_sprintf("destination type '%s' has %" ZIG_PRI_u64 " bits but source type '%s' has %" ZIG_PRI_u64 " bits",20979 buf_sprintf("destination type '%s' has %" ZIG_PRI_u64 " bits but source type '%s' has %" ZIG_PRI_u64 " bits",
20754 buf_ptr(&dest_type->name), dest_size_bits,20980 buf_ptr(&dest_type->name), dest_size_bits,
20755 buf_ptr(&src_type->name), src_size_bits));20981 buf_ptr(&src_type->name), src_size_bits));
...@@ -20761,44 +20987,63 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct...@@ -20761,44 +20987,63 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
20761 if (!val)20987 if (!val)
20762 return ira->codegen->invalid_instruction;20988 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);
20765 uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);20991 uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);
20766 buf_write_value_bytes(ira->codegen, buf, val);20992 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)))
20768 return ira->codegen->invalid_instruction;20994 return ira->codegen->invalid_instruction;
20769 return result;20995 return result;
20770 }20996 }
2077120997
20772 IrInstruction *result = ir_build_bit_cast(&ira->new_irb, instruction->base.scope,20998 IrInstruction *result = ir_build_bit_cast(&ira->new_irb, source_instr->scope,
20773 instruction->base.source_node, nullptr, value);20999 source_instr->source_node, nullptr, value);
20774 result->value.type = dest_type;21000 result->value.type = dest_type;
20775 return result;21001 return result;
20776}21002}
2077721003
20778static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) {21004static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
20779 Error err;
20780 IrInstruction *dest_type_value = instruction->dest_type->child;21005 IrInstruction *dest_type_value = instruction->dest_type->child;
20781 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);21006 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
20782 if (type_is_invalid(dest_type))21007 if (type_is_invalid(dest_type))
20783 return ira->codegen->invalid_instruction;21008 return ira->codegen->invalid_instruction;
2078421009
20785 // We explicitly check for the size, so we can use get_src_ptr_type21010 IrInstruction *value = instruction->value->child;
20786 if (get_src_ptr_type(dest_type) == nullptr) {21011 ZigType *src_type = value->value.type;
20787 ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));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)));
20788 return ira->codegen->invalid_instruction;21018 return ira->codegen->invalid_instruction;
20789 }21019 }
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)));
20792 return ira->codegen->invalid_instruction;21024 return ira->codegen->invalid_instruction;
20793 if (!type_has_bits(dest_type)) {21025 }
21026
21027 if (get_codegen_ptr_type(dest_type) != nullptr) {
20794 ir_add_error(ira, dest_type_value,21028 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)));
20796 return ira->codegen->invalid_instruction;21030 return ira->codegen->invalid_instruction;
20797 }21031 }
2079821032
20799 IrInstruction *target = instruction->target->child;21033 if (!type_can_bit_cast(dest_type)) {
20800 if (type_is_invalid(target->value.type))21034 ir_add_error(ira, dest_type_value,
21035 buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
20801 return ira->codegen->invalid_instruction;21036 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
20803 IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);21048 IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);
20804 if (type_is_invalid(casted_int->value.type))21049 if (type_is_invalid(casted_int->value.type))
...@@ -20809,19 +21054,48 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru...@@ -20809,19 +21054,48 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru
20809 if (!val)21054 if (!val)
20810 return ira->codegen->invalid_instruction;21055 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);
20813 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;21058 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
20814 result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;21059 result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
20815 result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);21060 result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);
20816 return result;21061 return result;
20817 }21062 }
2081821063
20819 IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, instruction->base.scope,21064 IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, source_instr->scope,
20820 instruction->base.source_node, nullptr, casted_int);21065 source_instr->source_node, nullptr, casted_int);
20821 result->value.type = dest_type;21066 result->value.type = ptr_type;
20822 return result;21067 return result;
20823}21068}
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
20825static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,21099static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
20826 IrInstructionDeclRef *instruction)21100 IrInstructionDeclRef *instruction)
20827{21101{
...@@ -20925,6 +21199,15 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct...@@ -20925,6 +21199,15 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
20925 } else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) {21199 } else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) {
20926 ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque"));21200 ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque"));
20927 return ira->codegen->invalid_instruction;21201 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 }
20928 }21211 }
2092921212
20930 uint32_t align_bytes;21213 uint32_t align_bytes;
src/parser.cpp+9-1
...@@ -2778,7 +2778,8 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {...@@ -2778,7 +2778,8 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {
2778// PtrTypeStart2778// PtrTypeStart
2779// <- ASTERISK2779// <- ASTERISK
2780// / ASTERISK22780// / ASTERISK2
2781// / LBRACKET ASTERISK RBRACKET2781// / PTRUNKNOWN
2782// / PTRC
2782static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {2783static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
2783 Token *asterisk = eat_token_if(pc, TokenIdStar);2784 Token *asterisk = eat_token_if(pc, TokenIdStar);
2784 if (asterisk != nullptr) {2785 if (asterisk != nullptr) {
...@@ -2804,6 +2805,13 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {...@@ -2804,6 +2805,13 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
2804 return res;2805 return res;
2805 }2806 }
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
2807 return nullptr;2815 return nullptr;
2808}2816}
28092817
src/target.cpp+4
...@@ -807,6 +807,10 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {...@@ -807,6 +807,10 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
807 zig_unreachable();807 zig_unreachable();
808}808}
809809
810bool target_allows_addr_zero(const ZigTarget *target) {
811 return target->os == OsFreestanding;
812}
813
810const char *target_o_file_ext(ZigTarget *target) {814const char *target_o_file_ext(ZigTarget *target) {
811 if (target->env_type == ZigLLVM_MSVC || target->os == OsWindows || target->os == OsUefi) {815 if (target->env_type == ZigLLVM_MSVC || target->os == OsWindows || target->os == OsUefi) {
812 return ".obj";816 return ".obj";
src/target.hpp+1
...@@ -135,5 +135,6 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target...@@ -135,5 +135,6 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target
135ZigLLVM_OSType get_llvm_os_type(Os os_type);135ZigLLVM_OSType get_llvm_os_type(Os os_type);
136136
137bool target_is_arm(const ZigTarget *target);137bool target_is_arm(const ZigTarget *target);
138bool target_allows_addr_zero(const ZigTarget *target);
138139
139#endif140#endif
src/tokenizer.cpp+18-1
...@@ -221,6 +221,7 @@ enum TokenizeState {...@@ -221,6 +221,7 @@ enum TokenizeState {
221 TokenizeStateError,221 TokenizeStateError,
222 TokenizeStateLBracket,222 TokenizeStateLBracket,
223 TokenizeStateLBracketStar,223 TokenizeStateLBracketStar,
224 TokenizeStateLBracketStarC,
224};225};
225226
226227
...@@ -846,7 +847,6 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -846,7 +847,6 @@ void tokenize(Buf *buf, Tokenization *out) {
846 switch (c) {847 switch (c) {
847 case '*':848 case '*':
848 t.state = TokenizeStateLBracketStar;849 t.state = TokenizeStateLBracketStar;
849 set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket);
850 break;850 break;
851 default:851 default:
852 // reinterpret as just an lbracket852 // reinterpret as just an lbracket
...@@ -857,6 +857,21 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -857,6 +857,21 @@ void tokenize(Buf *buf, Tokenization *out) {
857 }857 }
858 break;858 break;
859 case TokenizeStateLBracketStar:859 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:
860 switch (c) {875 switch (c) {
861 case ']':876 case ']':
862 end_token(&t);877 end_token(&t);
...@@ -1491,6 +1506,7 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1491,6 +1506,7 @@ void tokenize(Buf *buf, Tokenization *out) {
1491 case TokenizeStateLineStringContinue:1506 case TokenizeStateLineStringContinue:
1492 case TokenizeStateLineStringContinueC:1507 case TokenizeStateLineStringContinueC:
1493 case TokenizeStateLBracketStar:1508 case TokenizeStateLBracketStar:
1509 case TokenizeStateLBracketStarC:
1494 tokenize_error(&t, "unexpected EOF");1510 tokenize_error(&t, "unexpected EOF");
1495 break;1511 break;
1496 case TokenizeStateLineComment:1512 case TokenizeStateLineComment:
...@@ -1528,6 +1544,7 @@ const char * token_name(TokenId id) {...@@ -1528,6 +1544,7 @@ const char * token_name(TokenId id) {
1528 case TokenIdBitShiftRightEq: return ">>=";1544 case TokenIdBitShiftRightEq: return ">>=";
1529 case TokenIdBitXorEq: return "^=";1545 case TokenIdBitXorEq: return "^=";
1530 case TokenIdBracketStarBracket: return "[*]";1546 case TokenIdBracketStarBracket: return "[*]";
1547 case TokenIdBracketStarCBracket: return "[*c]";
1531 case TokenIdCharLiteral: return "CharLiteral";1548 case TokenIdCharLiteral: return "CharLiteral";
1532 case TokenIdCmpEq: return "==";1549 case TokenIdCmpEq: return "==";
1533 case TokenIdCmpGreaterOrEq: return ">=";1550 case TokenIdCmpGreaterOrEq: return ">=";
src/tokenizer.hpp+1
...@@ -29,6 +29,7 @@ enum TokenId {...@@ -29,6 +29,7 @@ enum TokenId {
29 TokenIdBitShiftRightEq,29 TokenIdBitShiftRightEq,
30 TokenIdBitXorEq,30 TokenIdBitXorEq,
31 TokenIdBracketStarBracket,31 TokenIdBracketStarBracket,
32 TokenIdBracketStarCBracket,
32 TokenIdCharLiteral,33 TokenIdCharLiteral,
33 TokenIdCmpEq,34 TokenIdCmpEq,
34 TokenIdCmpGreaterOrEq,35 TokenIdCmpGreaterOrEq,
src/translate_c.cpp+28-12
...@@ -291,11 +291,22 @@ static AstNode *maybe_suppress_result(Context *c, ResultUsed result_used, AstNod...@@ -291,11 +291,22 @@ static AstNode *maybe_suppress_result(Context *c, ResultUsed result_used, AstNod
291 node);291 node);
292}292}
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
294static AstNode *trans_create_node_ptr_type(Context *c, bool is_const, bool is_volatile, AstNode *child_node, PtrLen ptr_len) {306static AstNode *trans_create_node_ptr_type(Context *c, bool is_const, bool is_volatile, AstNode *child_node, PtrLen ptr_len) {
295 AstNode *node = trans_create_node(c, NodeTypePointerType);307 AstNode *node = trans_create_node(c, NodeTypePointerType);
296 node->data.pointer_type.star_token = allocate<ZigToken>(1);308 node->data.pointer_type.star_token = allocate<ZigToken>(1);
297 node->data.pointer_type.star_token->id = (ptr_len == PtrLenSingle) ? TokenIdStar: TokenIdBracketStarBracket;309 node->data.pointer_type.star_token->id = ptr_len_to_token_id(ptr_len);
298 node->data.pointer_type.is_const = is_const;
299 node->data.pointer_type.is_const = is_const;310 node->data.pointer_type.is_const = is_const;
300 node->data.pointer_type.is_volatile = is_volatile;311 node->data.pointer_type.is_volatile = is_volatile;
301 node->data.pointer_type.op_expr = child_node;312 node->data.pointer_type.op_expr = child_node;
...@@ -925,11 +936,14 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou...@@ -925,11 +936,14 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
925 return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);936 return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
926 }937 }
927938
928 PtrLen ptr_len = type_is_opaque(c, child_qt.getTypePtr(), source_loc) ? PtrLenSingle : PtrLenUnknown;939 if (type_is_opaque(c, child_qt.getTypePtr(), source_loc)) {
929940 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
930 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),941 child_qt.isVolatileQualified(), child_node, PtrLenSingle);
931 child_qt.isVolatileQualified(), child_node, ptr_len);942 return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);
932 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 }
933 }947 }
934 case Type::Typedef:948 case Type::Typedef:
935 {949 {
...@@ -1113,7 +1127,7 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou...@@ -1113,7 +1127,7 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
1113 return nullptr;1127 return nullptr;
1114 }1128 }
1115 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),1129 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);
1117 return pointer_node;1131 return pointer_node;
1118 }1132 }
1119 case Type::BlockPointer:1133 case Type::BlockPointer:
...@@ -1693,7 +1707,7 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im...@@ -1693,7 +1707,7 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im
1693 return node;1707 return node;
1694 }1708 }
1695 case CK_NullToPointer:1709 case CK_NullToPointer:
1696 return trans_create_node(c, NodeTypeNullLiteral);1710 return trans_create_node_unsigned(c, 0);
1697 case CK_Dependent:1711 case CK_Dependent:
1698 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dependent");1712 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dependent");
1699 return nullptr;1713 return nullptr;
...@@ -2425,7 +2439,8 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *...@@ -2425,7 +2439,8 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
2425 case BuiltinType::Float16:2439 case BuiltinType::Float16:
2426 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));2440 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));
2427 case BuiltinType::NullPtr:2441 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
2430 case BuiltinType::Void:2445 case BuiltinType::Void:
2431 case BuiltinType::Half:2446 case BuiltinType::Half:
...@@ -2510,7 +2525,8 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *...@@ -2510,7 +2525,8 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
2510 break;2525 break;
2511 }2526 }
2512 case Type::Pointer:2527 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
2515 case Type::Typedef:2531 case Type::Typedef:
2516 {2532 {
...@@ -4568,7 +4584,7 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t...@@ -4568,7 +4584,7 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t
4568 } else if (first_tok->id == CTokIdAsterisk) {4584 } else if (first_tok->id == CTokIdAsterisk) {
4569 *tok_i += 1;4585 *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);
4572 } else {4588 } else {
4573 return node;4589 return node;
4574 }4590 }
std/fmt/index.zig+3
...@@ -236,6 +236,9 @@ pub fn formatType(...@@ -236,6 +236,9 @@ pub fn formatType(
236 const casted_value = ([]const u8)(value);236 const casted_value = ([]const u8)(value);
237 return output(context, casted_value);237 return output(context, casted_value);
238 },238 },
239 builtin.TypeInfo.Pointer.Size.C => {
240 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
241 },
239 },242 },
240 builtin.TypeId.Array => |info| {243 builtin.TypeId.Array => |info| {
241 if (info.child == u8) {244 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...@@ -496,6 +496,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type
496 builtin.TypeId.Pointer => |info| switch (info.size) {496 builtin.TypeId.Pointer => |info| switch (info.size) {
497 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto hash for single item pointers"),497 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto hash for single item pointers"),
498 builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto hash for many item pointers"),498 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"),
499 builtin.TypeInfo.Pointer.Size.Slice => {500 builtin.TypeInfo.Pointer.Size.Slice => {
500 const interval = std.math.max(1, key.len / 256);501 const interval = std.math.max(1, key.len / 256);
501 var i: usize = 0;502 var i: usize = 0;
...@@ -543,6 +544,7 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {...@@ -543,6 +544,7 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {
543 builtin.TypeId.Pointer => |info| switch (info.size) {544 builtin.TypeId.Pointer => |info| switch (info.size) {
544 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto eql for single item pointers"),545 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto eql for single item pointers"),
545 builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto eql for many item pointers"),546 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"),
546 builtin.TypeInfo.Pointer.Size.Slice => {548 builtin.TypeInfo.Pointer.Size.Slice => {
547 if (a.len != b.len) return false;549 if (a.len != b.len) return false;
548 for (a) |a_item, i| {550 for (a) |a_item, i| {
std/meta/index.zig+6-3
...@@ -463,13 +463,16 @@ pub fn eql(a: var, b: @typeOf(a)) bool {...@@ -463,13 +463,16 @@ pub fn eql(a: var, b: @typeOf(a)) bool {
463 builtin.TypeId.Pointer => {463 builtin.TypeId.Pointer => {
464 const info = @typeInfo(T).Pointer;464 const info = @typeInfo(T).Pointer;
465 switch (info.size) {465 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,
467 builtin.TypeInfo.Pointer.Size.Slice => return a.ptr == b.ptr and a.len == b.len,470 builtin.TypeInfo.Pointer.Size.Slice => return a.ptr == b.ptr and a.len == b.len,
468 }471 }
469 },472 },
470 builtin.TypeId.Optional => {473 builtin.TypeId.Optional => {
471 if(a == null and b == null) return true;474 if (a == null and b == null) return true;
472 if(a == null or b == null) return false;475 if (a == null or b == null) return false;
473 return eql(a.?, b.?);476 return eql(a.?, b.?);
474 },477 },
475 else => return a == b,478 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 {...@@ -665,7 +665,7 @@ pub fn pwrite(fd: i32, buf: [*]const u8, nbyte: usize, offset: u64) usize {
665665
666pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {666pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
667 const ptr_result = c.mmap(667 const ptr_result = c.mmap(
668 @ptrCast(*c_void, address),668 @ptrCast(?*c_void, address),
669 length,669 length,
670 @bitCast(c_int, @intCast(c_uint, prot)),670 @bitCast(c_int, @intCast(c_uint, prot)),
671 @bitCast(c_int, c_uint(flags)),671 @bitCast(c_int, c_uint(flags)),
std/testing.zig+1-2
...@@ -65,7 +65,7 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {...@@ -65,7 +65,7 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {
65 }65 }
66 },66 },
6767
68 builtin.TypeInfo.Pointer.Size.Slice => { 68 builtin.TypeInfo.Pointer.Size.Slice => {
69 if (actual.ptr != expected.ptr) {69 if (actual.ptr != expected.ptr) {
70 std.debug.panic("expected slice ptr {}, found {}", expected.ptr, actual.ptr);70 std.debug.panic("expected slice ptr {}, found {}", expected.ptr, actual.ptr);
71 }71 }
...@@ -118,7 +118,6 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {...@@ -118,7 +118,6 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {
118 }118 }
119 }119 }
120 },120 },
121
122 }121 }
123}122}
124123
std/zig/parse.zig+6-1
...@@ -3525,7 +3525,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {...@@ -3525,7 +3525,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {
3525 Token.Id.Minus => ast.Node.PrefixOp.Op{ .Negation = void{} },3525 Token.Id.Minus => ast.Node.PrefixOp.Op{ .Negation = void{} },
3526 Token.Id.MinusPercent => ast.Node.PrefixOp.Op{ .NegationWrap = void{} },3526 Token.Id.MinusPercent => ast.Node.PrefixOp.Op{ .NegationWrap = void{} },
3527 Token.Id.Ampersand => ast.Node.PrefixOp.Op{ .AddressOf = void{} },3527 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{
3529 .PtrType = ast.Node.PrefixOp.PtrInfo{3534 .PtrType = ast.Node.PrefixOp.PtrInfo{
3530 .align_info = null,3535 .align_info = null,
3531 .const_token = null,3536 .const_token = null,
std/zig/parser_test.zig+7
...@@ -1,3 +1,10 @@...@@ -1,3 +1,10 @@
1test "zig fmt: C pointers" {
2 try testCanonical(
3 \\const Ptr = [*c]i32;
4 \\
5 );
6}
7
1test "zig fmt: threadlocal" {8test "zig fmt: threadlocal" {
2 try testCanonical(9 try testCanonical(
3 \\threadlocal var x: i32 = 1234;10 \\threadlocal var x: i32 = 1234;
std/zig/tokenizer.zig+22-1
...@@ -141,6 +141,7 @@ pub const Token = struct {...@@ -141,6 +141,7 @@ pub const Token = struct {
141 LineComment,141 LineComment,
142 DocComment,142 DocComment,
143 BracketStarBracket,143 BracketStarBracket,
144 BracketStarCBracket,
144 ShebangLine,145 ShebangLine,
145 Keyword_align,146 Keyword_align,
146 Keyword_and,147 Keyword_and,
...@@ -279,6 +280,7 @@ pub const Tokenizer = struct {...@@ -279,6 +280,7 @@ pub const Tokenizer = struct {
279 SawAtSign,280 SawAtSign,
280 LBracket,281 LBracket,
281 LBracketStar,282 LBracketStar,
283 LBracketStarC,
282 };284 };
283285
284 pub fn next(self: *Tokenizer) Token {286 pub fn next(self: *Tokenizer) Token {
...@@ -456,6 +458,9 @@ pub const Tokenizer = struct {...@@ -456,6 +458,9 @@ pub const Tokenizer = struct {
456 },458 },
457459
458 State.LBracketStar => switch (c) {460 State.LBracketStar => switch (c) {
461 'c' => {
462 state = State.LBracketStarC;
463 },
459 ']' => {464 ']' => {
460 result.id = Token.Id.BracketStarBracket;465 result.id = Token.Id.BracketStarBracket;
461 self.index += 1;466 self.index += 1;
...@@ -467,6 +472,18 @@ pub const Tokenizer = struct {...@@ -467,6 +472,18 @@ pub const Tokenizer = struct {
467 },472 },
468 },473 },
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
470 State.Ampersand => switch (c) {487 State.Ampersand => switch (c) {
471 '=' => {488 '=' => {
472 result.id = Token.Id.AmpersandEqual;489 result.id = Token.Id.AmpersandEqual;
...@@ -1035,6 +1052,7 @@ pub const Tokenizer = struct {...@@ -1035,6 +1052,7 @@ pub const Tokenizer = struct {
1035 State.CharLiteralEnd,1052 State.CharLiteralEnd,
1036 State.StringLiteralBackslash,1053 State.StringLiteralBackslash,
1037 State.LBracketStar,1054 State.LBracketStar,
1055 State.LBracketStarC,
1038 => {1056 => {
1039 result.id = Token.Id.Invalid;1057 result.id = Token.Id.Invalid;
1040 },1058 },
...@@ -1169,12 +1187,15 @@ test "tokenizer" {...@@ -1169,12 +1187,15 @@ test "tokenizer" {
1169 testTokenize("test", []Token.Id{Token.Id.Keyword_test});1187 testTokenize("test", []Token.Id{Token.Id.Keyword_test});
1170}1188}
11711189
1172test "tokenizer - unknown length pointer" {1190test "tokenizer - unknown length pointer and then c pointer" {
1173 testTokenize(1191 testTokenize(
1174 \\[*]u81192 \\[*]u8
1193 \\[*c]u8
1175 , []Token.Id{1194 , []Token.Id{
1176 Token.Id.BracketStarBracket,1195 Token.Id.BracketStarBracket,
1177 Token.Id.Identifier,1196 Token.Id.Identifier,
1197 Token.Id.BracketStarCBracket,
1198 Token.Id.Identifier,
1178 });1199 });
1179}1200}
11801201
test/compile_errors.zig+181-45
...@@ -1,13 +1,149 @@...@@ -1,13 +1,149 @@
1const tests = @import("tests.zig");1const tests = @import("tests.zig");
22
3pub fn addCases(cases: *tests.CompileErrorContext) void {3pub fn addCases(cases: *tests.CompileErrorContext) void {
4 cases.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
4 cases.addTest(140 cases.addTest(
5 "@truncate undefined value",141 "@truncate undefined value",
6 \\export fn entry() void {142 \\export fn entry() void {
7 \\ var z = @truncate(u8, u16(undefined));143 \\ var z = @truncate(u8, u16(undefined));
8 \\}144 \\}
9 ,145 ,
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",
11 );147 );
12148
13 cases.addTest(149 cases.addTest(
...@@ -368,7 +504,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -368,7 +504,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
368 \\ f(i32);504 \\ f(i32);
369 \\}505 \\}
370 ,506 ,
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",
372 );508 );
373509
374 cases.add(510 cases.add(
...@@ -768,7 +904,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -768,7 +904,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
768 \\ command.exec();904 \\ command.exec();
769 \\}905 \\}
770 ,906 ,
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",
772 );908 );
773909
774 cases.add(910 cases.add(
...@@ -781,7 +917,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -781,7 +917,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
781 \\ command.exec();917 \\ command.exec();
782 \\}918 \\}
783 ,919 ,
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",
785 );921 );
786922
787 cases.add(923 cases.add(
...@@ -2752,7 +2888,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2752,7 +2888,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2752 \\2888 \\
2753 \\export fn entry() usize { return @sizeOf(@typeOf(x)); }2889 \\export fn entry() usize { return @sizeOf(@typeOf(x)); }
2754 ,2890 ,
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",
2756 );2892 );
27572893
2758 cases.add(2894 cases.add(
...@@ -2762,7 +2898,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2762,7 +2898,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2762 \\ _ = a / a;2898 \\ _ = a / a;
2763 \\}2899 \\}
2764 ,2900 ,
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",
2766 );2902 );
27672903
2768 cases.add(2904 cases.add(
...@@ -2772,7 +2908,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2772,7 +2908,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2772 \\ a /= a;2908 \\ a /= a;
2773 \\}2909 \\}
2774 ,2910 ,
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",
2776 );2912 );
27772913
2778 cases.add(2914 cases.add(
...@@ -2782,7 +2918,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2782,7 +2918,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2782 \\ _ = a % a;2918 \\ _ = a % a;
2783 \\}2919 \\}
2784 ,2920 ,
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",
2786 );2922 );
27872923
2788 cases.add(2924 cases.add(
...@@ -2792,7 +2928,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2792,7 +2928,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2792 \\ a %= a;2928 \\ a %= a;
2793 \\}2929 \\}
2794 ,2930 ,
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",
2796 );2932 );
27972933
2798 cases.add(2934 cases.add(
...@@ -2802,7 +2938,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2802,7 +2938,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2802 \\ _ = a + a;2938 \\ _ = a + a;
2803 \\}2939 \\}
2804 ,2940 ,
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",
2806 );2942 );
28072943
2808 cases.add(2944 cases.add(
...@@ -2812,7 +2948,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2812,7 +2948,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2812 \\ a += a;2948 \\ a += a;
2813 \\}2949 \\}
2814 ,2950 ,
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",
2816 );2952 );
28172953
2818 cases.add(2954 cases.add(
...@@ -2822,7 +2958,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2822,7 +2958,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2822 \\ _ = a +% a;2958 \\ _ = a +% a;
2823 \\}2959 \\}
2824 ,2960 ,
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",
2826 );2962 );
28272963
2828 cases.add(2964 cases.add(
...@@ -2832,7 +2968,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2832,7 +2968,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2832 \\ a +%= a;2968 \\ a +%= a;
2833 \\}2969 \\}
2834 ,2970 ,
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",
2836 );2972 );
28372973
2838 cases.add(2974 cases.add(
...@@ -2842,7 +2978,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2842,7 +2978,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2842 \\ _ = a - a;2978 \\ _ = a - a;
2843 \\}2979 \\}
2844 ,2980 ,
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",
2846 );2982 );
28472983
2848 cases.add(2984 cases.add(
...@@ -2852,7 +2988,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2852,7 +2988,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2852 \\ a -= a;2988 \\ a -= a;
2853 \\}2989 \\}
2854 ,2990 ,
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",
2856 );2992 );
28572993
2858 cases.add(2994 cases.add(
...@@ -2862,7 +2998,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2862,7 +2998,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2862 \\ _ = a -% a;2998 \\ _ = a -% a;
2863 \\}2999 \\}
2864 ,3000 ,
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",
2866 );3002 );
28673003
2868 cases.add(3004 cases.add(
...@@ -2872,7 +3008,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2872,7 +3008,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2872 \\ a -%= a;3008 \\ a -%= a;
2873 \\}3009 \\}
2874 ,3010 ,
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",
2876 );3012 );
28773013
2878 cases.add(3014 cases.add(
...@@ -2882,7 +3018,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2882,7 +3018,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2882 \\ _ = a * a;3018 \\ _ = a * a;
2883 \\}3019 \\}
2884 ,3020 ,
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",
2886 );3022 );
28873023
2888 cases.add(3024 cases.add(
...@@ -2892,7 +3028,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2892,7 +3028,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2892 \\ a *= a;3028 \\ a *= a;
2893 \\}3029 \\}
2894 ,3030 ,
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",
2896 );3032 );
28973033
2898 cases.add(3034 cases.add(
...@@ -2902,7 +3038,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2902,7 +3038,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2902 \\ _ = a *% a;3038 \\ _ = a *% a;
2903 \\}3039 \\}
2904 ,3040 ,
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",
2906 );3042 );
29073043
2908 cases.add(3044 cases.add(
...@@ -2912,7 +3048,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2912,7 +3048,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2912 \\ a *%= a;3048 \\ a *%= a;
2913 \\}3049 \\}
2914 ,3050 ,
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",
2916 );3052 );
29173053
2918 cases.add(3054 cases.add(
...@@ -2922,7 +3058,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2922,7 +3058,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2922 \\ _ = a << 2;3058 \\ _ = a << 2;
2923 \\}3059 \\}
2924 ,3060 ,
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",
2926 );3062 );
29273063
2928 cases.add(3064 cases.add(
...@@ -2932,7 +3068,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2932,7 +3068,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2932 \\ a <<= 2;3068 \\ a <<= 2;
2933 \\}3069 \\}
2934 ,3070 ,
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",
2936 );3072 );
29373073
2938 cases.add(3074 cases.add(
...@@ -2942,7 +3078,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2942,7 +3078,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2942 \\ _ = a >> 2;3078 \\ _ = a >> 2;
2943 \\}3079 \\}
2944 ,3080 ,
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",
2946 );3082 );
29473083
2948 cases.add(3084 cases.add(
...@@ -2952,7 +3088,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2952,7 +3088,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2952 \\ a >>= 2;3088 \\ a >>= 2;
2953 \\}3089 \\}
2954 ,3090 ,
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",
2956 );3092 );
29573093
2958 cases.add(3094 cases.add(
...@@ -2962,7 +3098,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2962,7 +3098,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2962 \\ _ = a & a;3098 \\ _ = a & a;
2963 \\}3099 \\}
2964 ,3100 ,
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",
2966 );3102 );
29673103
2968 cases.add(3104 cases.add(
...@@ -2972,7 +3108,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2972,7 +3108,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2972 \\ a &= a;3108 \\ a &= a;
2973 \\}3109 \\}
2974 ,3110 ,
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",
2976 );3112 );
29773113
2978 cases.add(3114 cases.add(
...@@ -2982,7 +3118,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2982,7 +3118,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2982 \\ _ = a | a;3118 \\ _ = a | a;
2983 \\}3119 \\}
2984 ,3120 ,
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",
2986 );3122 );
29873123
2988 cases.add(3124 cases.add(
...@@ -2992,7 +3128,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2992,7 +3128,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2992 \\ a |= a;3128 \\ a |= a;
2993 \\}3129 \\}
2994 ,3130 ,
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",
2996 );3132 );
29973133
2998 cases.add(3134 cases.add(
...@@ -3002,7 +3138,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3002,7 +3138,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3002 \\ _ = a ^ a;3138 \\ _ = a ^ a;
3003 \\}3139 \\}
3004 ,3140 ,
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",
3006 );3142 );
30073143
3008 cases.add(3144 cases.add(
...@@ -3012,7 +3148,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3012,7 +3148,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3012 \\ a ^= a;3148 \\ a ^= a;
3013 \\}3149 \\}
3014 ,3150 ,
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",
3016 );3152 );
30173153
3018 cases.add(3154 cases.add(
...@@ -3022,7 +3158,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3022,7 +3158,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3022 \\ _ = a == a;3158 \\ _ = a == a;
3023 \\}3159 \\}
3024 ,3160 ,
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",
3026 );3162 );
30273163
3028 cases.add(3164 cases.add(
...@@ -3032,7 +3168,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3032,7 +3168,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3032 \\ _ = a != a;3168 \\ _ = a != a;
3033 \\}3169 \\}
3034 ,3170 ,
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",
3036 );3172 );
30373173
3038 cases.add(3174 cases.add(
...@@ -3042,7 +3178,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3042,7 +3178,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3042 \\ _ = a > a;3178 \\ _ = a > a;
3043 \\}3179 \\}
3044 ,3180 ,
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",
3046 );3182 );
30473183
3048 cases.add(3184 cases.add(
...@@ -3052,7 +3188,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3052,7 +3188,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3052 \\ _ = a >= a;3188 \\ _ = a >= a;
3053 \\}3189 \\}
3054 ,3190 ,
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",
3056 );3192 );
30573193
3058 cases.add(3194 cases.add(
...@@ -3062,7 +3198,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3062,7 +3198,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3062 \\ _ = a < a;3198 \\ _ = a < a;
3063 \\}3199 \\}
3064 ,3200 ,
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",
3066 );3202 );
30673203
3068 cases.add(3204 cases.add(
...@@ -3072,7 +3208,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3072,7 +3208,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3072 \\ _ = a <= a;3208 \\ _ = a <= a;
3073 \\}3209 \\}
3074 ,3210 ,
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",
3076 );3212 );
30773213
3078 cases.add(3214 cases.add(
...@@ -3082,7 +3218,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3082,7 +3218,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3082 \\ _ = a and a;3218 \\ _ = a and a;
3083 \\}3219 \\}
3084 ,3220 ,
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",
3086 );3222 );
30873223
3088 cases.add(3224 cases.add(
...@@ -3092,7 +3228,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3092,7 +3228,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3092 \\ _ = a or a;3228 \\ _ = a or a;
3093 \\}3229 \\}
3094 ,3230 ,
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",
3096 );3232 );
30973233
3098 cases.add(3234 cases.add(
...@@ -3102,7 +3238,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3102,7 +3238,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3102 \\ _ = -a;3238 \\ _ = -a;
3103 \\}3239 \\}
3104 ,3240 ,
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",
3106 );3242 );
31073243
3108 cases.add(3244 cases.add(
...@@ -3112,7 +3248,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3112,7 +3248,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3112 \\ _ = -%a;3248 \\ _ = -%a;
3113 \\}3249 \\}
3114 ,3250 ,
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",
3116 );3252 );
31173253
3118 cases.add(3254 cases.add(
...@@ -3122,7 +3258,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3122,7 +3258,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3122 \\ _ = ~a;3258 \\ _ = ~a;
3123 \\}3259 \\}
3124 ,3260 ,
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",
3126 );3262 );
31273263
3128 cases.add(3264 cases.add(
...@@ -3132,7 +3268,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3132,7 +3268,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3132 \\ _ = !a;3268 \\ _ = !a;
3133 \\}3269 \\}
3134 ,3270 ,
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",
3136 );3272 );
31373273
3138 cases.add(3274 cases.add(
...@@ -3142,7 +3278,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3142,7 +3278,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3142 \\ _ = a orelse false;3278 \\ _ = a orelse false;
3143 \\}3279 \\}
3144 ,3280 ,
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",
3146 );3282 );
31473283
3148 cases.add(3284 cases.add(
...@@ -3152,7 +3288,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3152,7 +3288,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3152 \\ _ = a catch |err| false;3288 \\ _ = a catch |err| false;
3153 \\}3289 \\}
3154 ,3290 ,
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",
3156 );3292 );
31573293
3158 cases.add(3294 cases.add(
test/runtime_safety.zig+10
...@@ -1,6 +1,16 @@...@@ -1,6 +1,16 @@
1const tests = @import("tests.zig");1const tests = @import("tests.zig");
22
3pub fn addCases(cases: *tests.CompareOutputContext) void {3pub 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
4 cases.addRuntimeSafety("@intToEnum - no matching tag value",14 cases.addRuntimeSafety("@intToEnum - no matching tag value",
5 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {15 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
6 \\ @import("std").os.exit(126);16 \\ @import("std").os.exit(126);
test/stage1/behavior/pointers.zig+82
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const expect = std.testing.expect;2const expect = std.testing.expect;
3const expectError = std.testing.expectError;
34
4test "dereference pointer" {5test "dereference pointer" {
5 comptime testDerefPtr();6 comptime testDerefPtr();
...@@ -42,3 +43,84 @@ test "double pointer parsing" {...@@ -42,3 +43,84 @@ test "double pointer parsing" {
42fn PtrOf(comptime T: type) type {43fn PtrOf(comptime T: type) type {
43 return *T;44 return *T;
44}45}
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 {...@@ -61,6 +61,21 @@ fn testUnknownLenPtr() void {
61 expect(u32_ptr_info.Pointer.child == f64);61 expect(u32_ptr_info.Pointer.child == f64);
62}62}
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
64test "type info: slice type info" {79test "type info: slice type info" {
65 testSlice();80 testSlice();
66 comptime testSlice();81 comptime testSlice();
test/translate_c.zig+31-31
...@@ -117,11 +117,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -117,11 +117,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
117 \\};117 \\};
118 ,118 ,
119 \\pub const struct_Foo = extern struct {119 \\pub const struct_Foo = extern struct {
120 \\ a: ?[*]Foo,120 \\ a: [*c]Foo,
121 \\};121 \\};
122 \\pub const Foo = struct_Foo;122 \\pub const Foo = struct_Foo;
123 \\pub const struct_Bar = extern struct {123 \\pub const struct_Bar = extern struct {
124 \\ a: ?[*]Foo,124 \\ a: [*c]Foo,
125 \\};125 \\};
126 );126 );
127127
...@@ -213,7 +213,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -213,7 +213,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
213 ,213 ,
214 \\const struct_Foo = extern struct {214 \\const struct_Foo = extern struct {
215 \\ x: c_int,215 \\ x: c_int,
216 \\ y: ?[*]u8,216 \\ y: [*c]u8,
217 \\};217 \\};
218 ,218 ,
219 \\pub const Foo = struct_Foo;219 \\pub const Foo = struct_Foo;
...@@ -244,7 +244,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -244,7 +244,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
244 ,244 ,
245 \\pub const BarB = enum_Bar.B;245 \\pub const BarB = enum_Bar.B;
246 ,246 ,
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;
248 ,248 ,
249 \\pub const Foo = struct_Foo;249 \\pub const Foo = struct_Foo;
250 ,250 ,
...@@ -254,7 +254,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -254,7 +254,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
254 cases.add("constant size array",254 cases.add("constant size array",
255 \\void func(int array[20]);255 \\void func(int array[20]);
256 ,256 ,
257 \\pub extern fn func(array: ?[*]c_int) void;257 \\pub extern fn func(array: [*c]c_int) void;
258 );258 );
259259
260 cases.add("self referential struct with function pointer",260 cases.add("self referential struct with function pointer",
...@@ -263,7 +263,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -263,7 +263,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
263 \\};263 \\};
264 ,264 ,
265 \\pub const struct_Foo = extern struct {265 \\pub const struct_Foo = extern struct {
266 \\ derp: ?extern fn(?[*]struct_Foo) void,266 \\ derp: ?extern fn([*c]struct_Foo) void,
267 \\};267 \\};
268 ,268 ,
269 \\pub const Foo = struct_Foo;269 \\pub const Foo = struct_Foo;
...@@ -322,11 +322,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -322,11 +322,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
322 \\};322 \\};
323 ,323 ,
324 \\pub const struct_Bar = extern struct {324 \\pub const struct_Bar = extern struct {
325 \\ next: ?[*]struct_Foo,325 \\ next: [*c]struct_Foo,
326 \\};326 \\};
327 ,327 ,
328 \\pub const struct_Foo = extern struct {328 \\pub const struct_Foo = extern struct {
329 \\ next: ?[*]struct_Bar,329 \\ next: [*c]struct_Bar,
330 \\};330 \\};
331 );331 );
332332
...@@ -610,11 +610,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -610,11 +610,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
610 ,610 ,
611 \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {611 \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
612 \\ if ((a != 0) and (b != 0)) return 0;612 \\ if ((a != 0) and (b != 0)) return 0;
613 \\ if ((b != 0) and (c != null)) return 1;613 \\ if ((b != 0) and (c != 0)) return 1;
614 \\ if ((a != 0) and (c != null)) return 2;614 \\ if ((a != 0) and (c != 0)) return 2;
615 \\ if ((a != 0) or (b != 0)) return 3;615 \\ if ((a != 0) or (b != 0)) return 3;
616 \\ if ((b != 0) or (c != null)) return 4;616 \\ if ((b != 0) or (c != 0)) return 4;
617 \\ if ((a != 0) or (c != null)) return 5;617 \\ if ((a != 0) or (c != 0)) return 5;
618 \\ return 6;618 \\ return 6;
619 \\}619 \\}
620 );620 );
...@@ -710,7 +710,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -710,7 +710,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
710 \\pub const struct_Foo = extern struct {710 \\pub const struct_Foo = extern struct {
711 \\ field: c_int,711 \\ field: c_int,
712 \\};712 \\};
713 \\pub export fn read_field(foo: ?[*]struct_Foo) c_int {713 \\pub export fn read_field(foo: [*c]struct_Foo) c_int {
714 \\ return foo.?.field;714 \\ return foo.?.field;
715 \\}715 \\}
716 );716 );
...@@ -756,7 +756,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -756,7 +756,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
756 \\ return x;756 \\ return x;
757 \\}757 \\}
758 ,758 ,
759 \\pub export fn foo(x: ?[*]c_ushort) ?*c_void {759 \\pub export fn foo(x: [*c]c_ushort) ?*c_void {
760 \\ return @ptrCast(?*c_void, x);760 \\ return @ptrCast(?*c_void, x);
761 \\}761 \\}
762 );762 );
...@@ -777,8 +777,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -777,8 +777,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
777 \\ return 0;777 \\ return 0;
778 \\}778 \\}
779 ,779 ,
780 \\pub export fn foo() ?[*]c_int {780 \\pub export fn foo() [*c]c_int {
781 \\ return null;781 \\ return 0;
782 \\}782 \\}
783 );783 );
784784
...@@ -1086,7 +1086,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1086,7 +1086,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1086 \\ *x = 1;1086 \\ *x = 1;
1087 \\}1087 \\}
1088 ,1088 ,
1089 \\pub export fn foo(x: ?[*]c_int) void {1089 \\pub export fn foo(x: [*c]c_int) void {
1090 \\ x.?.* = 1;1090 \\ x.?.* = 1;
1091 \\}1091 \\}
1092 );1092 );
...@@ -1114,7 +1114,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1114,7 +1114,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1114 ,1114 ,
1115 \\pub fn foo() c_int {1115 \\pub fn foo() c_int {
1116 \\ var x: c_int = 1234;1116 \\ var x: c_int = 1234;
1117 \\ var ptr: ?[*]c_int = &x;1117 \\ var ptr: [*c]c_int = &x;
1118 \\ return ptr.?.*;1118 \\ return ptr.?.*;
1119 \\}1119 \\}
1120 );1120 );
...@@ -1124,7 +1124,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1124,7 +1124,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1124 \\ return "bar";1124 \\ return "bar";
1125 \\}1125 \\}
1126 ,1126 ,
1127 \\pub fn foo() ?[*]const u8 {1127 \\pub fn foo() [*c]const u8 {
1128 \\ return c"bar";1128 \\ return c"bar";
1129 \\}1129 \\}
1130 );1130 );
...@@ -1253,8 +1253,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1253,8 +1253,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1253 \\ return (float *)a;1253 \\ return (float *)a;
1254 \\}1254 \\}
1255 ,1255 ,
1256 \\fn ptrcast(a: ?[*]c_int) ?[*]f32 {1256 \\fn ptrcast(a: [*c]c_int) [*c]f32 {
1257 \\ return @ptrCast(?[*]f32, a);1257 \\ return @ptrCast([*c]f32, a);
1258 \\}1258 \\}
1259 );1259 );
12601260
...@@ -1280,7 +1280,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1280,7 +1280,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1280 \\ return !(a == 0);1280 \\ return !(a == 0);
1281 \\ return !(a != 0);1281 \\ return !(a != 0);
1282 \\ return !(b != 0);1282 \\ return !(b != 0);
1283 \\ return !(c != null);1283 \\ return !(c != 0);
1284 \\}1284 \\}
1285 );1285 );
12861286
...@@ -1297,7 +1297,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1297,7 +1297,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1297 cases.add("const ptr initializer",1297 cases.add("const ptr initializer",
1298 \\static const char *v0 = "0.0.0";1298 \\static const char *v0 = "0.0.0";
1299 ,1299 ,
1300 \\pub var v0: ?[*]const u8 = c"0.0.0";1300 \\pub var v0: [*c]const u8 = c"0.0.0";
1301 );1301 );
13021302
1303 cases.add("static incomplete array inside function",1303 cases.add("static incomplete array inside function",
...@@ -1306,17 +1306,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1306,17 +1306,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1306 \\}1306 \\}
1307 ,1307 ,
1308 \\pub fn foo() void {1308 \\pub fn foo() void {
1309 \\ const v2: [*]const u8 = c"2.2.2";1309 \\ const v2: [*c]const u8 = c"2.2.2";
1310 \\}1310 \\}
1311 );1311 );
13121312
1313 cases.add("macro pointer cast",1313 cases.add("macro pointer cast",
1314 \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)1314 \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
1315 ,1315 ,
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);
1317 );1317 );
13181318
1319 cases.add("if on none bool",1319 cases.add("if on non-bool",
1320 \\enum SomeEnum { A, B, C };1320 \\enum SomeEnum { A, B, C };
1321 \\int if_none_bool(int a, float b, void *c, enum SomeEnum d) {1321 \\int if_none_bool(int a, float b, void *c, enum SomeEnum d) {
1322 \\ if (a) return 0;1322 \\ if (a) return 0;
...@@ -1337,13 +1337,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1337,13 +1337,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1337 \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int {1337 \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int {
1338 \\ if (a != 0) return 0;1338 \\ if (a != 0) return 0;
1339 \\ if (b != 0) return 1;1339 \\ if (b != 0) return 1;
1340 \\ if (c != null) return 2;1340 \\ if (c != 0) return 2;
1341 \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3;1341 \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3;
1342 \\ return 4;1342 \\ return 4;
1343 \\}1343 \\}
1344 );1344 );
13451345
1346 cases.add("while on none bool",1346 cases.add("while on non-bool",
1347 \\int while_none_bool(int a, float b, void *c) {1347 \\int while_none_bool(int a, float b, void *c) {
1348 \\ while (a) return 0;1348 \\ while (a) return 0;
1349 \\ while (b) return 1;1349 \\ while (b) return 1;
...@@ -1354,12 +1354,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1354,12 +1354,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1354 \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {1354 \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
1355 \\ while (a != 0) return 0;1355 \\ while (a != 0) return 0;
1356 \\ while (b != 0) return 1;1356 \\ while (b != 0) return 1;
1357 \\ while (c != null) return 2;1357 \\ while (c != 0) return 2;
1358 \\ return 3;1358 \\ return 3;
1359 \\}1359 \\}
1360 );1360 );
13611361
1362 cases.add("for on none bool",1362 cases.add("for on non-bool",
1363 \\int for_none_bool(int a, float b, void *c) {1363 \\int for_none_bool(int a, float b, void *c) {
1364 \\ for (;a;) return 0;1364 \\ for (;a;) return 0;
1365 \\ for (;b;) return 1;1365 \\ for (;b;) return 1;
...@@ -1370,7 +1370,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1370,7 +1370,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1370 \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {1370 \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
1371 \\ while (a != 0) return 0;1371 \\ while (a != 0) return 0;
1372 \\ while (b != 0) return 1;1372 \\ while (b != 0) return 1;
1373 \\ while (c != null) return 2;1373 \\ while (c != 0) return 2;
1374 \\ return 3;1374 \\ return 3;
1375 \\}1375 \\}
1376 );1376 );