| author | |
| committer | |
| log | 567c9b688effdb64e3995df09af4b45105515c2c |
| tree | 11bc01aa7484d427455a12502710b0ee286fb6aa |
| parent | ee5e196f8832359cfe05808677f143d4f460f6bc |
| parent | 99b19adeb31469cbc4a906f036bb4d70d8730916 |
| signature |
implement C pointers37 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]), |
| 920 | 921 | ||
| 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 store | 1699 | <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#} |
| 1829 | const assert = @import("std").debug.assert; | 1831 | const 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#} |
| 6108 | 6114 | ||
| 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#} |
| 7347 | 7353 | ||
| 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#} |
| 7351 | 7357 | ||
| 7358 | {#header_open|Pointer Cast Invalid Null#} | ||
| 7359 | <p>At compile-time:</p> | ||
| 7360 | {#code_begin|test_err|null pointer casted to type#} | ||
| 7361 | comptime { | ||
| 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#} | ||
| 7368 | pub 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 used | 7468 | 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 languages | 7536 | 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 |
| 8164 | PtrTypeStart | 8218 | PtrTypeStart |
| 8165 | &lt;- ASTERISK | 8219 | &lt;- ASTERISK |
| 8166 | / ASTERISK2 | 8220 | / ASTERISK2 |
| 8167 | / LBRACKET ASTERISK RBRACKET | 8221 | / PTRUNKNOWN |
| 8222 | / PTRC | ||
| 8168 | 8223 | ||
| 8169 | # ContainerDecl specific | 8224 | # ContainerDecl specific |
| 8170 | ContainerDeclAuto &lt;- ContainerDeclType LBRACE ContainerMembers RBRACE | 8225 | ContainerDeclAuto &lt;- ContainerDeclType LBRACE ContainerMembers RBRACE |
| ... | @@ -8262,7 +8317,7 @@ LARROW2 &lt;- '&lt;&lt;' ![=] skip | ... | @@ -8262,7 +8317,7 @@ LARROW2 &lt;- '&lt;&lt;' ![=] skip |
| 8262 | LARROW2EQUAL &lt;- '&lt;&lt;=' skip | 8317 | LARROW2EQUAL &lt;- '&lt;&lt;=' skip |
| 8263 | LARROWEQUAL &lt;- '&lt;=' skip | 8318 | LARROWEQUAL &lt;- '&lt;=' skip |
| 8264 | LBRACE &lt;- '{' skip | 8319 | LBRACE &lt;- '{' skip |
| 8265 | LBRACKET &lt;- '[' skip | 8320 | LBRACKET &lt;- '[' ![*] skip |
| 8266 | LPAREN &lt;- '(' skip | 8321 | LPAREN &lt;- '(' skip |
| 8267 | MINUS &lt;- '-' ![%=&gt;] skip | 8322 | MINUS &lt;- '-' ![%=&gt;] skip |
| 8268 | MINUSEQUAL &lt;- '-=' skip | 8323 | MINUSEQUAL &lt;- '-=' skip |
| ... | @@ -8279,6 +8334,8 @@ PLUS2 &lt;- '++' skip | ... | @@ -8279,6 +8334,8 @@ PLUS2 &lt;- '++' skip |
| 8279 | PLUSEQUAL &lt;- '+=' skip | 8334 | PLUSEQUAL &lt;- '+=' skip |
| 8280 | PLUSPERCENT &lt;- '+%' ![=] skip | 8335 | PLUSPERCENT &lt;- '+%' ![=] skip |
| 8281 | PLUSPERCENTEQUAL &lt;- '+%=' skip | 8336 | PLUSPERCENTEQUAL &lt;- '+%=' skip |
| 8337 | PTRC &lt;- '[*c]' skip | ||
| 8338 | PTRUNKNOWN &lt;- '[*]' skip | ||
| 8282 | QUESTIONMARK &lt;- '?' skip | 8339 | QUESTIONMARK &lt;- '?' skip |
| 8283 | RARROW &lt;- '&gt;' ![&gt;=] skip | 8340 | RARROW &lt;- '&gt;' ![&gt;=] skip |
| 8284 | RARROW2 &lt;- '&gt;&gt;' ![=] skip | 8341 | RARROW2 &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) |
| 137 | 137 | ||
| 138 | pub const ObjectFile = struct { | 138 | pub 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, |
| 146 | 146 | ||
| ... | @@ -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) |
| 323 | 323 | ||
| 324 | fn addLLVMAttr( | 324 | fn 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( |
| 335 | 335 | ||
| 336 | fn addLLVMAttrStr( | 336 | fn 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 | } |
| 352 | 352 | ||
| 353 | fn addLLVMAttrInt( | 353 | fn 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 | } |
| 364 | 364 | ||
| 365 | fn addLLVMFnAttr(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8) !void { | 365 | fn 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 | } |
| 368 | 368 | ||
| 369 | fn addLLVMFnAttrStr(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8, attr_val: []const u8) !void { | 369 | fn 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 | } |
| 372 | 372 | ||
| 373 | fn addLLVMFnAttrInt(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8, attr_val: u64) !void { | 373 | fn 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 | } |
| 376 | 376 | ||
| 377 | fn renderLoadUntyped( | 377 | fn 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 | } |
| 392 | 392 | ||
| 393 | fn renderLoad(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Pointer, name: [*]const u8) !llvm.ValueRef { | 393 | fn 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 | } |
| 396 | 396 | ||
| 397 | pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Pointer) !?llvm.ValueRef { | 397 | pub 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 |
| 407 | 407 | ||
| 408 | pub fn renderStoreUntyped( | 408 | pub 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( |
| 423 | 423 | ||
| 424 | pub fn renderStore( | 424 | pub 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 | } |
| 432 | 432 | ||
| ... | @@ -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 | } |
| 445 | 445 | ||
| 446 | pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: llvm.TypeRef) u32 { | 446 | pub 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. |
| 38 | pub const ZigCompiler = struct { | 38 | pub 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, |
| 42 | 42 | ||
| 43 | /// TODO pool these so that it doesn't have to lock | 43 | /// 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 }; |
| 82 | 82 | ||
| 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); |
| 85 | 85 | ||
| 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 | }; |
| 115 | 115 | ||
| 116 | pub const LlvmHandle = struct { | 116 | pub const LlvmHandle = struct { |
| 117 | node: *std.atomic.Stack(llvm.ContextRef).Node, | 117 | node: *std.atomic.Stack(*llvm.Context).Node, |
| 118 | 118 | ||
| 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, |
| 214 | 214 | ||
| 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, |
| 219 | 219 |
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, |
| 68 | 68 | ||
| 69 | /// populated durign codegen | 69 | /// populated durign codegen |
| 70 | llvm_value: ?llvm.ValueRef, | 70 | llvm_value: ?*llvm.Value, |
| 71 | 71 | ||
| 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 | } |
| 131 | 131 | ||
| 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 | } |
| 315 | 315 | ||
| 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.?; |
| 318 | 318 | ||
| 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 | } |
| 362 | 362 | ||
| 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 | } |
| 394 | 394 | ||
| 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(); |
| 398 | 398 | ||
| ... | @@ -540,7 +540,7 @@ pub const Inst = struct { | ... | @@ -540,7 +540,7 @@ pub const Inst = struct { |
| 540 | } | 540 | } |
| 541 | } | 541 | } |
| 542 | 542 | ||
| 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 pass | 545 | 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 | } |
| 598 | 598 | ||
| 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, |
| 936 | 936 | ||
| 937 | /// for codegen | 937 | /// for codegen |
| 938 | llvm_block: llvm.BasicBlockRef, | 938 | llvm_block: *llvm.BasicBlock, |
| 939 | llvm_exit_block: llvm.BasicBlockRef, | 939 | llvm_exit_block: *llvm.BasicBlock, |
| 940 | 940 | ||
| 941 | /// the basic block that is derived from this one in analysis | 941 | /// 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; |
| 156 | 156 | ||
| 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 { |
| 437 | 437 | ||
| 438 | fn fillSearch(search_buf: *[2]Search, sdk: *c.ZigWindowsSDK) []Search { | 438 | fn 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; |
| 11 | pub const AttributeIndex = c_uint; | 11 | pub const AttributeIndex = c_uint; |
| 12 | pub const Bool = c_int; | 12 | pub const Bool = c_int; |
| 13 | 13 | ||
| 14 | pub const BuilderRef = removeNullability(c.LLVMBuilderRef); | 14 | pub const Builder = c.LLVMBuilderRef.Child.Child; |
| 15 | pub const ContextRef = removeNullability(c.LLVMContextRef); | 15 | pub const Context = c.LLVMContextRef.Child.Child; |
| 16 | pub const ModuleRef = removeNullability(c.LLVMModuleRef); | 16 | pub const Module = c.LLVMModuleRef.Child.Child; |
| 17 | pub const ValueRef = removeNullability(c.LLVMValueRef); | 17 | pub const Value = c.LLVMValueRef.Child.Child; |
| 18 | pub const TypeRef = removeNullability(c.LLVMTypeRef); | 18 | pub const Type = c.LLVMTypeRef.Child.Child; |
| 19 | pub const BasicBlockRef = removeNullability(c.LLVMBasicBlockRef); | 19 | pub const BasicBlock = c.LLVMBasicBlockRef.Child.Child; |
| 20 | pub const AttributeRef = removeNullability(c.LLVMAttributeRef); | 20 | pub const Attribute = c.LLVMAttributeRef.Child.Child; |
| 21 | pub const TargetRef = removeNullability(c.LLVMTargetRef); | 21 | pub const Target = c.LLVMTargetRef.Child.Child; |
| 22 | pub const TargetMachineRef = removeNullability(c.LLVMTargetMachineRef); | 22 | pub const TargetMachine = c.LLVMTargetMachineRef.Child.Child; |
| 23 | pub const TargetDataRef = removeNullability(c.LLVMTargetDataRef); | 23 | pub const TargetData = c.LLVMTargetDataRef.Child.Child; |
| 24 | pub const DIBuilder = c.ZigLLVMDIBuilder; | 24 | pub const DIBuilder = c.ZigLLVMDIBuilder; |
| 25 | pub const DIFile = c.ZigLLVMDIFile; | ||
| 26 | pub const DICompileUnit = c.ZigLLVMDICompileUnit; | ||
| 25 | 27 | ||
| 26 | pub const ABIAlignmentOfType = c.LLVMABIAlignmentOfType; | 28 | pub const ABIAlignmentOfType = c.LLVMABIAlignmentOfType; |
| 27 | pub const AddAttributeAtIndex = c.LLVMAddAttributeAtIndex; | 29 | pub const AddAttributeAtIndex = c.LLVMAddAttributeAtIndex; |
| 28 | pub const AddFunction = c.LLVMAddFunction; | ||
| 29 | pub const AddGlobal = c.LLVMAddGlobal; | ||
| 30 | pub const AddModuleCodeViewFlag = c.ZigLLVMAddModuleCodeViewFlag; | 30 | pub const AddModuleCodeViewFlag = c.ZigLLVMAddModuleCodeViewFlag; |
| 31 | pub const AddModuleDebugInfoFlag = c.ZigLLVMAddModuleDebugInfoFlag; | 31 | pub const AddModuleDebugInfoFlag = c.ZigLLVMAddModuleDebugInfoFlag; |
| 32 | pub const ArrayType = c.LLVMArrayType; | ||
| 33 | pub const BuildLoad = c.LLVMBuildLoad; | ||
| 34 | pub const ClearCurrentDebugLocation = c.ZigLLVMClearCurrentDebugLocation; | 32 | pub const ClearCurrentDebugLocation = c.ZigLLVMClearCurrentDebugLocation; |
| 35 | pub const ConstAllOnes = c.LLVMConstAllOnes; | 33 | pub const ConstAllOnes = c.LLVMConstAllOnes; |
| 36 | pub const ConstArray = c.LLVMConstArray; | 34 | pub const ConstArray = c.LLVMConstArray; |
| 37 | pub const ConstBitCast = c.LLVMConstBitCast; | 35 | pub const ConstBitCast = c.LLVMConstBitCast; |
| 38 | pub const ConstInt = c.LLVMConstInt; | ||
| 39 | pub const ConstIntOfArbitraryPrecision = c.LLVMConstIntOfArbitraryPrecision; | 36 | pub const ConstIntOfArbitraryPrecision = c.LLVMConstIntOfArbitraryPrecision; |
| 40 | pub const ConstNeg = c.LLVMConstNeg; | 37 | pub const ConstNeg = c.LLVMConstNeg; |
| 41 | pub const ConstNull = c.LLVMConstNull; | ||
| 42 | pub const ConstStringInContext = c.LLVMConstStringInContext; | ||
| 43 | pub const ConstStructInContext = c.LLVMConstStructInContext; | 38 | pub const ConstStructInContext = c.LLVMConstStructInContext; |
| 44 | pub const CopyStringRepOfTargetData = c.LLVMCopyStringRepOfTargetData; | ||
| 45 | pub const CreateBuilderInContext = c.LLVMCreateBuilderInContext; | ||
| 46 | pub const CreateCompileUnit = c.ZigLLVMCreateCompileUnit; | ||
| 47 | pub const CreateDIBuilder = c.ZigLLVMCreateDIBuilder; | ||
| 48 | pub const CreateEnumAttribute = c.LLVMCreateEnumAttribute; | ||
| 49 | pub const CreateFile = c.ZigLLVMCreateFile; | ||
| 50 | pub const CreateStringAttribute = c.LLVMCreateStringAttribute; | ||
| 51 | pub const CreateTargetDataLayout = c.LLVMCreateTargetDataLayout; | ||
| 52 | pub const CreateTargetMachine = c.LLVMCreateTargetMachine; | ||
| 53 | pub const DIBuilderFinalize = c.ZigLLVMDIBuilderFinalize; | 39 | pub const DIBuilderFinalize = c.ZigLLVMDIBuilderFinalize; |
| 54 | pub const DisposeBuilder = c.LLVMDisposeBuilder; | 40 | pub const DisposeBuilder = c.LLVMDisposeBuilder; |
| 55 | pub const DisposeDIBuilder = c.ZigLLVMDisposeDIBuilder; | 41 | pub const DisposeDIBuilder = c.ZigLLVMDisposeDIBuilder; |
| ... | @@ -62,9 +48,7 @@ pub const DumpModule = c.LLVMDumpModule; | ... | @@ -62,9 +48,7 @@ pub const DumpModule = c.LLVMDumpModule; |
| 62 | pub const FP128TypeInContext = c.LLVMFP128TypeInContext; | 48 | pub const FP128TypeInContext = c.LLVMFP128TypeInContext; |
| 63 | pub const FloatTypeInContext = c.LLVMFloatTypeInContext; | 49 | pub const FloatTypeInContext = c.LLVMFloatTypeInContext; |
| 64 | pub const GetEnumAttributeKindForName = c.LLVMGetEnumAttributeKindForName; | 50 | pub const GetEnumAttributeKindForName = c.LLVMGetEnumAttributeKindForName; |
| 65 | pub const GetHostCPUName = c.ZigLLVMGetHostCPUName; | ||
| 66 | pub const GetMDKindIDInContext = c.LLVMGetMDKindIDInContext; | 51 | pub const GetMDKindIDInContext = c.LLVMGetMDKindIDInContext; |
| 67 | pub const GetNativeFeatures = c.ZigLLVMGetNativeFeatures; | ||
| 68 | pub const GetUndef = c.LLVMGetUndef; | 52 | pub const GetUndef = c.LLVMGetUndef; |
| 69 | pub const HalfTypeInContext = c.LLVMHalfTypeInContext; | 53 | pub const HalfTypeInContext = c.LLVMHalfTypeInContext; |
| 70 | pub const InitializeAllAsmParsers = c.LLVMInitializeAllAsmParsers; | 54 | pub const InitializeAllAsmParsers = c.LLVMInitializeAllAsmParsers; |
| ... | @@ -81,14 +65,11 @@ pub const Int64TypeInContext = c.LLVMInt64TypeInContext; | ... | @@ -81,14 +65,11 @@ pub const Int64TypeInContext = c.LLVMInt64TypeInContext; |
| 81 | pub const Int8TypeInContext = c.LLVMInt8TypeInContext; | 65 | pub const Int8TypeInContext = c.LLVMInt8TypeInContext; |
| 82 | pub const IntPtrTypeForASInContext = c.LLVMIntPtrTypeForASInContext; | 66 | pub const IntPtrTypeForASInContext = c.LLVMIntPtrTypeForASInContext; |
| 83 | pub const IntPtrTypeInContext = c.LLVMIntPtrTypeInContext; | 67 | pub const IntPtrTypeInContext = c.LLVMIntPtrTypeInContext; |
| 84 | pub const IntTypeInContext = c.LLVMIntTypeInContext; | ||
| 85 | pub const LabelTypeInContext = c.LLVMLabelTypeInContext; | 68 | pub const LabelTypeInContext = c.LLVMLabelTypeInContext; |
| 86 | pub const MDNodeInContext = c.LLVMMDNodeInContext; | 69 | pub const MDNodeInContext = c.LLVMMDNodeInContext; |
| 87 | pub const MDStringInContext = c.LLVMMDStringInContext; | 70 | pub const MDStringInContext = c.LLVMMDStringInContext; |
| 88 | pub const MetadataTypeInContext = c.LLVMMetadataTypeInContext; | 71 | pub const MetadataTypeInContext = c.LLVMMetadataTypeInContext; |
| 89 | pub const ModuleCreateWithNameInContext = c.LLVMModuleCreateWithNameInContext; | ||
| 90 | pub const PPCFP128TypeInContext = c.LLVMPPCFP128TypeInContext; | 72 | pub const PPCFP128TypeInContext = c.LLVMPPCFP128TypeInContext; |
| 91 | pub const PointerType = c.LLVMPointerType; | ||
| 92 | pub const SetAlignment = c.LLVMSetAlignment; | 73 | pub const SetAlignment = c.LLVMSetAlignment; |
| 93 | pub const SetDataLayout = c.LLVMSetDataLayout; | 74 | pub const SetDataLayout = c.LLVMSetDataLayout; |
| 94 | pub const SetGlobalConstant = c.LLVMSetGlobalConstant; | 75 | pub const SetGlobalConstant = c.LLVMSetGlobalConstant; |
| ... | @@ -99,50 +80,146 @@ pub const SetUnnamedAddr = c.LLVMSetUnnamedAddr; | ... | @@ -99,50 +80,146 @@ pub const SetUnnamedAddr = c.LLVMSetUnnamedAddr; |
| 99 | pub const SetVolatile = c.LLVMSetVolatile; | 80 | pub const SetVolatile = c.LLVMSetVolatile; |
| 100 | pub const StructTypeInContext = c.LLVMStructTypeInContext; | 81 | pub const StructTypeInContext = c.LLVMStructTypeInContext; |
| 101 | pub const TokenTypeInContext = c.LLVMTokenTypeInContext; | 82 | pub const TokenTypeInContext = c.LLVMTokenTypeInContext; |
| 102 | pub const VoidTypeInContext = c.LLVMVoidTypeInContext; | ||
| 103 | pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext; | 83 | pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext; |
| 104 | pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext; | 84 | pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext; |
| 105 | 85 | ||
| 86 | pub const AddGlobal = LLVMAddGlobal; | ||
| 87 | extern fn LLVMAddGlobal(M: *Module, Ty: *Type, Name: [*]const u8) ?*Value; | ||
| 88 | |||
| 89 | pub const ConstStringInContext = LLVMConstStringInContext; | ||
| 90 | extern fn LLVMConstStringInContext(C: *Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: Bool) ?*Value; | ||
| 91 | |||
| 92 | pub const ConstInt = LLVMConstInt; | ||
| 93 | extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) ?*Value; | ||
| 94 | |||
| 95 | pub const BuildLoad = LLVMBuildLoad; | ||
| 96 | extern fn LLVMBuildLoad(arg0: *Builder, PointerVal: *Value, Name: [*]const u8) ?*Value; | ||
| 97 | |||
| 98 | pub const ConstNull = LLVMConstNull; | ||
| 99 | extern fn LLVMConstNull(Ty: *Type) ?*Value; | ||
| 100 | |||
| 101 | pub const CreateStringAttribute = LLVMCreateStringAttribute; | ||
| 102 | extern fn LLVMCreateStringAttribute( | ||
| 103 | C: *Context, | ||
| 104 | K: [*]const u8, | ||
| 105 | KLength: c_uint, | ||
| 106 | V: [*]const u8, | ||
| 107 | VLength: c_uint, | ||
| 108 | ) ?*Attribute; | ||
| 109 | |||
| 110 | pub const CreateEnumAttribute = LLVMCreateEnumAttribute; | ||
| 111 | extern fn LLVMCreateEnumAttribute(C: *Context, KindID: c_uint, Val: u64) ?*Attribute; | ||
| 112 | |||
| 113 | pub const AddFunction = LLVMAddFunction; | ||
| 114 | extern fn LLVMAddFunction(M: *Module, Name: [*]const u8, FunctionTy: *Type) ?*Value; | ||
| 115 | |||
| 116 | pub const CreateCompileUnit = ZigLLVMCreateCompileUnit; | ||
| 117 | extern 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 | |||
| 130 | pub const CreateFile = ZigLLVMCreateFile; | ||
| 131 | extern fn ZigLLVMCreateFile(dibuilder: *DIBuilder, filename: [*]const u8, directory: [*]const u8) ?*DIFile; | ||
| 132 | |||
| 133 | pub const ArrayType = LLVMArrayType; | ||
| 134 | extern fn LLVMArrayType(ElementType: *Type, ElementCount: c_uint) ?*Type; | ||
| 135 | |||
| 136 | pub const CreateDIBuilder = ZigLLVMCreateDIBuilder; | ||
| 137 | extern fn ZigLLVMCreateDIBuilder(module: *Module, allow_unresolved: bool) ?*DIBuilder; | ||
| 138 | |||
| 139 | pub const PointerType = LLVMPointerType; | ||
| 140 | extern fn LLVMPointerType(ElementType: *Type, AddressSpace: c_uint) ?*Type; | ||
| 141 | |||
| 142 | pub const CreateBuilderInContext = LLVMCreateBuilderInContext; | ||
| 143 | extern fn LLVMCreateBuilderInContext(C: *Context) ?*Builder; | ||
| 144 | |||
| 145 | pub const IntTypeInContext = LLVMIntTypeInContext; | ||
| 146 | extern fn LLVMIntTypeInContext(C: *Context, NumBits: c_uint) ?*Type; | ||
| 147 | |||
| 148 | pub const ModuleCreateWithNameInContext = LLVMModuleCreateWithNameInContext; | ||
| 149 | extern fn LLVMModuleCreateWithNameInContext(ModuleID: [*]const u8, C: *Context) ?*Module; | ||
| 150 | |||
| 151 | pub const VoidTypeInContext = LLVMVoidTypeInContext; | ||
| 152 | extern fn LLVMVoidTypeInContext(C: *Context) ?*Type; | ||
| 153 | |||
| 154 | pub const ContextCreate = LLVMContextCreate; | ||
| 155 | extern fn LLVMContextCreate() ?*Context; | ||
| 156 | |||
| 157 | pub const ContextDispose = LLVMContextDispose; | ||
| 158 | extern fn LLVMContextDispose(C: *Context) void; | ||
| 159 | |||
| 160 | pub const CopyStringRepOfTargetData = LLVMCopyStringRepOfTargetData; | ||
| 161 | extern fn LLVMCopyStringRepOfTargetData(TD: *TargetData) ?[*]u8; | ||
| 162 | |||
| 163 | pub const CreateTargetDataLayout = LLVMCreateTargetDataLayout; | ||
| 164 | extern fn LLVMCreateTargetDataLayout(T: *TargetMachine) ?*TargetData; | ||
| 165 | |||
| 166 | pub const CreateTargetMachine = LLVMCreateTargetMachine; | ||
| 167 | extern 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 | |||
| 177 | pub const GetHostCPUName = LLVMGetHostCPUName; | ||
| 178 | extern fn LLVMGetHostCPUName() ?[*]u8; | ||
| 179 | |||
| 180 | pub const GetNativeFeatures = ZigLLVMGetNativeFeatures; | ||
| 181 | extern fn ZigLLVMGetNativeFeatures() ?[*]u8; | ||
| 182 | |||
| 106 | pub const GetElementType = LLVMGetElementType; | 183 | pub const GetElementType = LLVMGetElementType; |
| 107 | extern fn LLVMGetElementType(Ty: TypeRef) TypeRef; | 184 | extern fn LLVMGetElementType(Ty: *Type) *Type; |
| 108 | 185 | ||
| 109 | pub const TypeOf = LLVMTypeOf; | 186 | pub const TypeOf = LLVMTypeOf; |
| 110 | extern fn LLVMTypeOf(Val: ValueRef) TypeRef; | 187 | extern fn LLVMTypeOf(Val: *Value) *Type; |
| 111 | 188 | ||
| 112 | pub const BuildStore = LLVMBuildStore; | 189 | pub const BuildStore = LLVMBuildStore; |
| 113 | extern fn LLVMBuildStore(arg0: BuilderRef, Val: ValueRef, Ptr: ValueRef) ?ValueRef; | 190 | extern fn LLVMBuildStore(arg0: *Builder, Val: *Value, Ptr: *Value) ?*Value; |
| 114 | 191 | ||
| 115 | pub const BuildAlloca = LLVMBuildAlloca; | 192 | pub const BuildAlloca = LLVMBuildAlloca; |
| 116 | extern fn LLVMBuildAlloca(arg0: BuilderRef, Ty: TypeRef, Name: ?[*]const u8) ?ValueRef; | 193 | extern fn LLVMBuildAlloca(arg0: *Builder, Ty: *Type, Name: ?[*]const u8) ?*Value; |
| 117 | 194 | ||
| 118 | pub const ConstInBoundsGEP = LLVMConstInBoundsGEP; | 195 | pub const ConstInBoundsGEP = LLVMConstInBoundsGEP; |
| 119 | pub extern fn LLVMConstInBoundsGEP(ConstantVal: ValueRef, ConstantIndices: [*]ValueRef, NumIndices: c_uint) ?ValueRef; | 196 | pub extern fn LLVMConstInBoundsGEP(ConstantVal: *Value, ConstantIndices: [*]*Value, NumIndices: c_uint) ?*Value; |
| 120 | 197 | ||
| 121 | pub const GetTargetFromTriple = LLVMGetTargetFromTriple; | 198 | pub const GetTargetFromTriple = LLVMGetTargetFromTriple; |
| 122 | extern fn LLVMGetTargetFromTriple(Triple: [*]const u8, T: *TargetRef, ErrorMessage: ?*[*]u8) Bool; | 199 | extern fn LLVMGetTargetFromTriple(Triple: [*]const u8, T: **Target, ErrorMessage: ?*[*]u8) Bool; |
| 123 | 200 | ||
| 124 | pub const VerifyModule = LLVMVerifyModule; | 201 | pub const VerifyModule = LLVMVerifyModule; |
| 125 | extern fn LLVMVerifyModule(M: ModuleRef, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool; | 202 | extern fn LLVMVerifyModule(M: *Module, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool; |
| 126 | 203 | ||
| 127 | pub const GetInsertBlock = LLVMGetInsertBlock; | 204 | pub const GetInsertBlock = LLVMGetInsertBlock; |
| 128 | extern fn LLVMGetInsertBlock(Builder: BuilderRef) BasicBlockRef; | 205 | extern fn LLVMGetInsertBlock(Builder: *Builder) *BasicBlock; |
| 129 | 206 | ||
| 130 | pub const FunctionType = LLVMFunctionType; | 207 | pub const FunctionType = LLVMFunctionType; |
| 131 | extern fn LLVMFunctionType( | 208 | extern 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; |
| 137 | 214 | ||
| 138 | pub const GetParam = LLVMGetParam; | 215 | pub const GetParam = LLVMGetParam; |
| 139 | extern fn LLVMGetParam(Fn: ValueRef, Index: c_uint) ValueRef; | 216 | extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value; |
| 140 | 217 | ||
| 141 | pub const AppendBasicBlockInContext = LLVMAppendBasicBlockInContext; | 218 | pub const AppendBasicBlockInContext = LLVMAppendBasicBlockInContext; |
| 142 | extern fn LLVMAppendBasicBlockInContext(C: ContextRef, Fn: ValueRef, Name: [*]const u8) ?BasicBlockRef; | 219 | extern fn LLVMAppendBasicBlockInContext(C: *Context, Fn: *Value, Name: [*]const u8) ?*BasicBlock; |
| 143 | 220 | ||
| 144 | pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd; | 221 | pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd; |
| 145 | extern fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef) void; | 222 | extern fn LLVMPositionBuilderAtEnd(Builder: *Builder, Block: *BasicBlock) void; |
| 146 | 223 | ||
| 147 | pub const AbortProcessAction = VerifierFailureAction.LLVMAbortProcessAction; | 224 | pub const AbortProcessAction = VerifierFailureAction.LLVMAbortProcessAction; |
| 148 | pub const PrintMessageAction = VerifierFailureAction.LLVMPrintMessageAction; | 225 | pub const PrintMessageAction = VerifierFailureAction.LLVMPrintMessageAction; |
| ... | @@ -190,17 +267,17 @@ pub const FnInline = extern enum { | ... | @@ -190,17 +267,17 @@ pub const FnInline = extern enum { |
| 190 | }; | 267 | }; |
| 191 | 268 | ||
| 192 | fn removeNullability(comptime T: type) type { | 269 | fn 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 | } |
| 196 | 273 | ||
| 197 | pub const BuildRet = LLVMBuildRet; | 274 | pub const BuildRet = LLVMBuildRet; |
| 198 | extern fn LLVMBuildRet(arg0: BuilderRef, V: ?ValueRef) ?ValueRef; | 275 | extern fn LLVMBuildRet(arg0: *Builder, V: ?*Value) ?*Value; |
| 199 | 276 | ||
| 200 | pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile; | 277 | pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile; |
| 201 | extern fn ZigLLVMTargetMachineEmitToFile( | 278 | extern 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; |
| 210 | 287 | ||
| 211 | pub const BuildCall = ZigLLVMBuildCall; | 288 | pub const BuildCall = ZigLLVMBuildCall; |
| 212 | extern fn ZigLLVMBuildCall(B: BuilderRef, Fn: ValueRef, Args: [*]ValueRef, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*]const u8) ?ValueRef; | 289 | extern fn ZigLLVMBuildCall(B: *Builder, Fn: *Value, Args: [*]*Value, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*]const u8) ?*Value; |
| 213 | 290 | ||
| 214 | pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage; | 291 | pub 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 | }; |
| 367 | 367 | ||
| 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 | } |
| 459 | 459 | ||
| 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 | } |
| 197 | 197 | ||
| 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.*; |
| 201 | 201 | ||
| 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 | } |
| 206 | 206 | ||
| 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 | } |
| 220 | 220 | ||
| 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 | } |
| 498 | 498 | ||
| 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 | } |
| 561 | 561 | ||
| 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 | } |
| 660 | 660 | ||
| 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 | } |
| 672 | 672 | ||
| 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 | } |
| 837 | 838 | ||
| 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 | } |
| 905 | 906 | ||
| 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 | } |
| 918 | 919 | ||
| 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 | } |
| 968 | 969 | ||
| 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 | } |
| 980 | 981 | ||
| 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 | } |
| 992 | 993 | ||
| 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 | } |
| 1004 | 1005 | ||
| 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 | } |
| 1016 | 1017 | ||
| 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 | } |
| 1036 | 1037 | ||
| 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 | } |
| 1056 | 1057 | ||
| 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 | } |
| 1068 | 1069 | ||
| 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 | } |
| 59 | 59 | ||
| 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 | } |
| 155 | 155 | ||
| 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 ObjectFile | 240 | /// 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 | } |
| 285 | 285 | ||
| 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 | } |
| 383 | 383 | ||
| 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_ptr | 386 | // 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 | } |
| 461 | 461 | ||
| 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 | } |
| 536 | 536 | ||
| 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 | }; |
| 698 | 699 | ||
| 699 | struct AstNodeArrayType { | 700 | struct 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); |
| 1038 | enum PtrLen { | 1040 | enum PtrLen { |
| 1039 | PtrLenUnknown, | 1041 | PtrLenUnknown, |
| 1040 | PtrLenSingle, | 1042 | PtrLenSingle, |
| 1043 | PtrLenC, | ||
| 1041 | }; | 1044 | }; |
| 1042 | 1045 | ||
| 1043 | struct ZigTypePointer { | 1046 | struct 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 aligned | 1052 | 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 | }; |
| 1053 | 1057 | ||
| 1054 | struct ZigTypeInt { | 1058 | struct 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, | ||
| 1487 | 1492 | ||
| 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 | }; |
| 2595 | 2602 | ||
| 2596 | struct IrInstructionPromiseType { | 2603 | struct 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 | }; |
| 2610 | 2618 | ||
| 2611 | struct IrInstructionAsm { | 2619 | struct IrInstructionAsm { |
| ... | @@ -2994,12 +3002,14 @@ struct IrInstructionPtrCastSrc { | ... | @@ -2994,12 +3002,14 @@ struct IrInstructionPtrCastSrc { |
| 2994 | 3002 | ||
| 2995 | IrInstruction *dest_type; | 3003 | IrInstruction *dest_type; |
| 2996 | IrInstruction *ptr; | 3004 | IrInstruction *ptr; |
| 3005 | bool safety_check_on; | ||
| 2997 | }; | 3006 | }; |
| 2998 | 3007 | ||
| 2999 | struct IrInstructionPtrCastGen { | 3008 | struct IrInstructionPtrCastGen { |
| 3000 | IrInstruction base; | 3009 | IrInstruction base; |
| 3001 | 3010 | ||
| 3002 | IrInstruction *ptr; | 3011 | IrInstruction *ptr; |
| 3012 | bool safety_check_on; | ||
| 3003 | }; | 3013 | }; |
| 3004 | 3014 | ||
| 3005 | struct IrInstructionBitCast { | 3015 | struct 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 | } |
| 419 | 419 | ||
| 420 | static 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 | |||
| 420 | ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, | 432 | ZigType *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); |
| 426 | 441 | ||
| ... | @@ -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 |
| 440 | 455 | ||
| 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; | ||
| 452 | 468 | ||
| 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 |
| 466 | 482 | ||
| 467 | ZigType *entry = new_type_table_entry(ZigTypeIdPointer); | 483 | ZigType *entry = new_type_table_entry(ZigTypeIdPointer); |
| 468 | 484 | ||
| 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 | } |
| 485 | 511 | ||
| 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); |
| 489 | 515 | ||
| 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; | ||
| 525 | 554 | ||
| 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) { |
| 838 | 867 | ||
| 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 | } |
| 1459 | 1488 | ||
| 1460 | static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { | 1489 | bool 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 | } |
| 2652 | 2681 | ||
| 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; |
| 2936 | 2972 | ||
| 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 | } |
| 4057 | 4102 | ||
| 4103 | bool type_is_nonnull_ptr(ZigType *type) { | ||
| 4104 | return type_is_codegen_pointer(type) && !ptr_allows_addr_zero(type); | ||
| 4105 | } | ||
| 4106 | |||
| 4058 | bool type_is_codegen_pointer(ZigType *type) { | 4107 | bool 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 |
| 6883 | 6934 | ||
| 6884 | return ErrorNone; | 6935 | return ErrorNone; |
| 6885 | } | 6936 | } |
| 6937 | |||
| 6938 | const 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 | |||
| 6947 | bool 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); |
| 44 | void find_libc_lib_path(CodeGen *g); | 44 | void find_libc_lib_path(CodeGen *g); |
| 45 | 45 | ||
| 46 | bool type_has_bits(ZigType *type_entry); | 46 | bool type_has_bits(ZigType *type_entry); |
| 47 | 47 | bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry); | |
| 48 | bool ptr_allows_addr_zero(ZigType *ptr_type); | ||
| 49 | bool type_is_nonnull_ptr(ZigType *type); | ||
| 48 | 50 | ||
| 49 | ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code); | 51 | ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code); |
| 50 | 52 | ||
| ... | @@ -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); |
| 215 | X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty); | 217 | X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty); |
| 216 | bool type_is_c_abi_int(CodeGen *g, ZigType *ty); | 218 | bool type_is_c_abi_int(CodeGen *g, ZigType *ty); |
| 217 | bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id); | 219 | bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id); |
| 220 | const char *container_string(ContainerKind kind); | ||
| 218 | 221 | ||
| 219 | uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field); | 222 | uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field); |
| 220 | 223 |
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 | } |
| 138 | 138 | ||
| 139 | const char *container_string(ContainerKind kind) { | 139 | static 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 | } |
| 147 | 153 | ||
| 148 | static const char *node_type_str(NodeType node_type) { | 154 | static 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); |
| 17 | 17 | ||
| 18 | void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size); | 18 | void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size); |
| 19 | 19 | ||
| 20 | const char *container_string(ContainerKind kind); | ||
| 21 | |||
| 22 | #endif | 20 | #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 do | 619 | // 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) { |
| 637 | 638 | ||
| 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 | } |
| 642 | 645 | ||
| ... | @@ -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; |
| 2717 | 2732 | ||
| 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 | } |
| 3033 | 3063 | ||
| 3034 | static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable, | 3064 | static 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 | ConstCastResultIdNullWrapPtr | 64 | ConstCastResultIdBadAllowsZero, |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | struct ConstCastOnly; | 67 | struct ConstCastOnly; |
| ... | @@ -83,6 +83,7 @@ struct ConstCastErrUnionErrSetMismatch; | ... | @@ -83,6 +83,7 @@ struct ConstCastErrUnionErrSetMismatch; |
| 83 | struct ConstCastErrUnionPayloadMismatch; | 83 | struct ConstCastErrUnionPayloadMismatch; |
| 84 | struct ConstCastErrSetMismatch; | 84 | struct ConstCastErrSetMismatch; |
| 85 | struct ConstCastTypeMismatch; | 85 | struct ConstCastTypeMismatch; |
| 86 | struct ConstCastBadAllowsZero; | ||
| 86 | 87 | ||
| 87 | struct ConstCastOnly { | 88 | struct 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 | }; |
| 104 | 106 | ||
| ... | @@ -141,6 +143,12 @@ struct ConstCastErrSetMismatch { | ... | @@ -141,6 +143,12 @@ struct ConstCastErrSetMismatch { |
| 141 | ZigList<ErrorTableEntry *> missing_errors; | 143 | ZigList<ErrorTableEntry *> missing_errors; |
| 142 | }; | 144 | }; |
| 143 | 145 | ||
| 146 | struct ConstCastBadAllowsZero { | ||
| 147 | ZigType *wanted_type; | ||
| 148 | ZigType *actual_type; | ||
| 149 | }; | ||
| 150 | |||
| 151 | |||
| 144 | enum UndefAllowed { | 152 | enum 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 |
| 164 | static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, | 172 | static 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); |
| 166 | static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr, | 174 | static 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); |
| 168 | static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed); | 176 | static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed); |
| 169 | static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs); | 177 | static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs); |
| 170 | static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align); | 178 | static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align); |
| 171 | static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry); | 179 | static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry); |
| 180 | static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target, | ||
| 181 | ZigType *ptr_type); | ||
| 182 | static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, | ||
| 183 | ZigType *dest_type); | ||
| 172 | 184 | ||
| 173 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { | 185 | static 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 | } |
| 2191 | 2203 | ||
| 2192 | static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node, | 2204 | static 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; | ||
| 2199 | 2212 | ||
| 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 | } |
| 2205 | 2218 | ||
| 2206 | static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction, | 2219 | static 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; | ||
| 2213 | 2227 | ||
| 2214 | ir_ref_instruction(ptr, ira->new_irb.current_basic_block); | 2228 | ir_ref_instruction(ptr, ira->new_irb.current_basic_block); |
| 2215 | 2229 | ||
| ... | @@ -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 * |
| 2458 | 2472 | ||
| 2459 | ir_ref_instruction(type_value, irb->current_basic_block); | 2473 | ir_ref_instruction(type_value, irb->current_basic_block); |
| 2460 | 2474 | ||
| 2461 | return &instruction->base; | 2475 | return &instruction->base; |
| 2462 | } | 2476 | } |
| 2463 | 2477 | ||
| 2464 | static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node, | 2478 | static 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; |
| 4495 | 4509 | ||
| 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 | } |
| 5021 | 5035 | ||
| 5036 | static 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 | |||
| 5022 | static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) { | 5050 | static 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); // 0b010 | 6742 | IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010 |
| 6716 | 6743 | ||
| 6717 | // TODO relies on Zig not re-ordering fields | 6744 | // 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); |
| 6723 | 6751 | ||
| 6724 | // set the is_canceled bit | 6752 | // 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); |
| 6728 | 6756 | ||
| ... | @@ -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)); |
| 6794 | 6822 | ||
| 6795 | // TODO relies on Zig not re-ordering fields | 6823 | // 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); |
| 6801 | 6830 | ||
| 6802 | // clear the is_suspended bit | 6831 | // 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); |
| 6806 | 6835 | ||
| ... | @@ -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 |
| 6916 | 6945 | ||
| 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); |
| 6922 | 6951 | ||
| ... | @@ -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 |
| 6959 | 6988 | ||
| 6960 | 6989 | ||
| 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 |
| 6991 | 7020 | ||
| 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 |
| 7338 | 7367 | ||
| 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); |
| 7363 | 7393 | ||
| 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); |
| 7367 | 7398 | ||
| 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 | } |
| 8621 | 8654 | ||
| 8622 | |||
| 8623 | static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted_type, | 8655 | static 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; |
| 8634 | 8666 | ||
| 8635 | // *T and [*]T may const-cast-only to ?*U and ?[*]U, respectively | 8667 | // If pointers have the same representation in memory, they can be "const-casted". |
| 8636 | // but not if we want a mutable pointer | 8668 | // `const` attribute can be gained |
| 8637 | // and not if the actual pointer has zero bits | 8669 | // `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); |
| 8653 | 8685 | if (wanted_opt_or_ptr && actual_opt_or_ptr) { | |
| 8654 | // pointer const | 8686 | 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 | } |
| 8914 | 8956 | ||
| 8915 | static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type, IrInstruction **instructions, size_t instruction_count) { | 8957 | static 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 | } |
| 9231 | 9275 | ||
| 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: // TODO | 10866 | case ConstCastResultIdFnAlign: // TODO |
| 10774 | case ConstCastResultIdFnCC: // TODO | 10867 | case ConstCastResultIdFnCC: // TODO |
| 10775 | case ConstCastResultIdFnVarArgs: // TODO | 10868 | 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: // TODO | 10873 | case ConstCastResultIdFnArgNoAlias: // TODO |
| 10781 | case ConstCastResultIdUnresolvedInferredErrSet: // TODO | 10874 | case ConstCastResultIdUnresolvedInferredErrSet: // TODO |
| 10782 | case ConstCastResultIdAsyncAllocatorType: // TODO | 10875 | 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 | } |
| 10813 | 10905 | ||
| 10906 | static 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 | |||
| 10814 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, | 10939 | static 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 | } |
| 11188 | 11313 | ||
| ... | @@ -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 | } |
| 11219 | 11344 | ||
| 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 anything | 11362 | // 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 | } |
| 11589 | 11731 | ||
| 11590 | static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) { | 11732 | static 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 | } |
| 11607 | 11750 | ||
| 11608 | static bool optional_value_is_null(ConstExprValue *val) { | 11751 | static 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; |
| 11787 | 11934 | ||
| 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; |
| 11834 | 11985 | ||
| 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 | } |
| 11855 | 12028 | ||
| 11856 | // some comparisons with unsigned numbers can be evaluated | 12029 | // 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 | } |
| 12247 | 12420 | ||
| 12421 | static 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 | |||
| 12248 | static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) { | 12441 | static 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; |
| 12258 | 12453 | ||
| 12259 | // look for pointer math | 12454 | // 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; |
| 12266 | 12459 | ||
| 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, |
| 17116 | static TypeStructField *validate_byte_offset(IrAnalyze *ira, | 17342 | static 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 |
| 17290 | 17516 | ||
| 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 | } |
| 17471 | 17697 | ||
| 17698 | static 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 | |||
| 17472 | static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) { | 17710 | static 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 | } |
| 20370 | 20608 | ||
| 20371 | static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr, | 20609 | static 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; |
| 20375 | 20613 | ||
| ... | @@ -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 to | 20617 | // 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. |
| 20381 | 20619 | ||
| 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 | } |
| 20386 | 20625 | ||
| 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 | } |
| 20397 | 20637 | ||
| 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; |
| 20402 | 20644 | ||
| 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 | } |
| 20425 | 20678 | ||
| 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); |
| 20427 | 20680 | ||
| 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; |
| 20462 | 20715 | ||
| 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 | } |
| 20465 | 20719 | ||
| 20466 | static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ConstExprValue *val, size_t len) { | 20720 | static 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 | } |
| 20670 | 20924 | ||
| 20671 | static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) { | 20925 | static 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 | } | ||
| 20713 | 20946 | ||
| 20714 | if (get_codegen_ptr_type(dest_type) != nullptr) { | 20947 | static 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 | } | ||
| 20719 | 20963 | ||
| 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 | } | ||
| 20738 | 20964 | ||
| 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; |
| 20763 | 20989 | ||
| 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 | } |
| 20771 | 20997 | ||
| 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 | } |
| 20777 | 21003 | ||
| 20778 | static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) { | 21004 | static 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; |
| 20784 | 21009 | ||
| 20785 | // We explicitly check for the size, so we can use get_src_ptr_type | 21010 | 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 | } |
| 20790 | 21020 | ||
| 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 | } |
| 20798 | 21032 | ||
| 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 | |||
| 21042 | static 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)); | ||
| 20802 | 21047 | ||
| 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; |
| 20811 | 21056 | ||
| 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 | } |
| 20818 | 21063 | ||
| 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 | } |
| 20824 | 21069 | ||
| 21070 | static 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 | |||
| 20825 | static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira, | 21099 | static 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 | } |
| 20929 | 21212 | ||
| 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 | // PtrTypeStart | 2778 | // PtrTypeStart |
| 2779 | // <- ASTERISK | 2779 | // <- ASTERISK |
| 2780 | // / ASTERISK2 | 2780 | // / ASTERISK2 |
| 2781 | // / LBRACKET ASTERISK RBRACKET | 2781 | // / PTRUNKNOWN |
| 2782 | // / PTRC | ||
| 2782 | static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { | 2783 | static 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 | } |
| 2806 | 2807 | ||
| 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 | } |
| 2809 | 2817 |
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 | } |
| 809 | 809 | ||
| 810 | bool target_allows_addr_zero(const ZigTarget *target) { | ||
| 811 | return target->os == OsFreestanding; | ||
| 812 | } | ||
| 813 | |||
| 810 | const char *target_o_file_ext(ZigTarget *target) { | 814 | const 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 |
| 135 | ZigLLVM_OSType get_llvm_os_type(Os os_type); | 135 | ZigLLVM_OSType get_llvm_os_type(Os os_type); |
| 136 | 136 | ||
| 137 | bool target_is_arm(const ZigTarget *target); | 137 | bool target_is_arm(const ZigTarget *target); |
| 138 | bool target_allows_addr_zero(const ZigTarget *target); | ||
| 138 | 139 | ||
| 139 | #endif | 140 | #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 | }; |
| 225 | 226 | ||
| 226 | 227 | ||
| ... | @@ -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 lbracket | 852 | // 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 | } |
| 293 | 293 | ||
| 294 | static 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 | |||
| 294 | static AstNode *trans_create_node_ptr_type(Context *c, bool is_const, bool is_volatile, AstNode *child_node, PtrLen ptr_len) { | 306 | static 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 | } |
| 927 | 938 | ||
| 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)) { |
| 929 | 940 | 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)); | ||
| 2429 | 2444 | ||
| 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)); | ||
| 2514 | 2530 | ||
| 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; |
| 4570 | 4586 | ||
| 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 { |
| 665 | 665 | ||
| 666 | pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize { | 666 | pub 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 | }, |
| 67 | 67 | ||
| 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 | } |
| 124 | 123 |
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 @@ |
| 1 | test "zig fmt: C pointers" { | ||
| 2 | try testCanonical( | ||
| 3 | \\const Ptr = [*c]i32; | ||
| 4 | \\ | ||
| 5 | ); | ||
| 6 | } | ||
| 7 | |||
| 1 | test "zig fmt: threadlocal" { | 8 | test "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 | }; |
| 283 | 285 | ||
| 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 | }, |
| 457 | 459 | ||
| 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 | }, |
| 469 | 474 | ||
| 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 | } |
| 1171 | 1189 | ||
| 1172 | test "tokenizer - unknown length pointer" { | 1190 | test "tokenizer - unknown length pointer and then c pointer" { |
| 1173 | testTokenize( | 1191 | testTokenize( |
| 1174 | \\[*]u8 | 1192 | \\[*]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 | } |
| 1180 | 1201 |
test/compile_errors.zig+181-45| ... | @@ -1,13 +1,149 @@ | ... | @@ -1,13 +1,149 @@ |
| 1 | const tests = @import("tests.zig"); | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | ||
| 3 | pub fn addCases(cases: *tests.CompileErrorContext) void { | 3 | pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4 | cases.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 | ); |
| 12 | 148 | ||
| 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 | ); |
| 373 | 509 | ||
| 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 | ); |
| 773 | 909 | ||
| 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 | ); |
| 786 | 922 | ||
| 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 | ); |
| 2757 | 2893 | ||
| 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 | ); |
| 2767 | 2903 | ||
| 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 | ); |
| 2777 | 2913 | ||
| 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 | ); |
| 2787 | 2923 | ||
| 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 | ); |
| 2797 | 2933 | ||
| 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 | ); |
| 2807 | 2943 | ||
| 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 | ); |
| 2817 | 2953 | ||
| 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 | ); |
| 2827 | 2963 | ||
| 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 | ); |
| 2837 | 2973 | ||
| 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 | ); |
| 2847 | 2983 | ||
| 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 | ); |
| 2857 | 2993 | ||
| 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 | ); |
| 2867 | 3003 | ||
| 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 | ); |
| 2877 | 3013 | ||
| 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 | ); |
| 2887 | 3023 | ||
| 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 | ); |
| 2897 | 3033 | ||
| 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 | ); |
| 2907 | 3043 | ||
| 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 | ); |
| 2917 | 3053 | ||
| 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 | ); |
| 2927 | 3063 | ||
| 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 | ); |
| 2937 | 3073 | ||
| 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 | ); |
| 2947 | 3083 | ||
| 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 | ); |
| 2957 | 3093 | ||
| 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 | ); |
| 2967 | 3103 | ||
| 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 | ); |
| 2977 | 3113 | ||
| 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 | ); |
| 2987 | 3123 | ||
| 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 | ); |
| 2997 | 3133 | ||
| 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 | ); |
| 3007 | 3143 | ||
| 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 | ); |
| 3017 | 3153 | ||
| 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 | ); |
| 3027 | 3163 | ||
| 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 | ); |
| 3037 | 3173 | ||
| 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 | ); |
| 3047 | 3183 | ||
| 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 | ); |
| 3057 | 3193 | ||
| 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 | ); |
| 3067 | 3203 | ||
| 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 | ); |
| 3077 | 3213 | ||
| 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 | ); |
| 3087 | 3223 | ||
| 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 | ); |
| 3097 | 3233 | ||
| 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 | ); |
| 3107 | 3243 | ||
| 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 | ); |
| 3117 | 3253 | ||
| 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 | ); |
| 3127 | 3263 | ||
| 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 | ); |
| 3137 | 3273 | ||
| 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 | ); |
| 3147 | 3283 | ||
| 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 | ); |
| 3157 | 3293 | ||
| 3158 | cases.add( | 3294 | cases.add( |
test/runtime_safety.zig+10| ... | @@ -1,6 +1,16 @@ | ... | @@ -1,6 +1,16 @@ |
| 1 | const tests = @import("tests.zig"); | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | ||
| 3 | pub fn addCases(cases: *tests.CompareOutputContext) void { | 3 | pub 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 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const expect = std.testing.expect; | 2 | const expect = std.testing.expect; |
| 3 | const expectError = std.testing.expectError; | ||
| 3 | 4 | ||
| 4 | test "dereference pointer" { | 5 | test "dereference pointer" { |
| 5 | comptime testDerefPtr(); | 6 | comptime testDerefPtr(); |
| ... | @@ -42,3 +43,84 @@ test "double pointer parsing" { | ... | @@ -42,3 +43,84 @@ test "double pointer parsing" { |
| 42 | fn PtrOf(comptime T: type) type { | 43 | fn PtrOf(comptime T: type) type { |
| 43 | return *T; | 44 | return *T; |
| 44 | } | 45 | } |
| 46 | |||
| 47 | test "assigning integer to C pointer" { | ||
| 48 | var x: i32 = 0; | ||
| 49 | var ptr: [*c]u8 = 0; | ||
| 50 | var ptr2: [*c]u8 = x; | ||
| 51 | } | ||
| 52 | |||
| 53 | test "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 | |||
| 61 | test "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 | |||
| 87 | test "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 | |||
| 102 | test "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 | |||
| 112 | test "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 | } |
| 63 | 63 | ||
| 64 | test "type info: C pointer type info" { | ||
| 65 | testCPtr(); | ||
| 66 | comptime testCPtr(); | ||
| 67 | } | ||
| 68 | |||
| 69 | fn 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 | |||
| 64 | test "type info: slice type info" { | 79 | test "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 | ); |
| 127 | 127 | ||
| ... | @@ -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 | ); |
| 259 | 259 | ||
| 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 | ); |
| 332 | 332 | ||
| ... | @@ -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 | ); |
| 784 | 784 | ||
| ... | @@ -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 | ); |
| 1260 | 1260 | ||
| ... | @@ -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 | ); |
| 1286 | 1286 | ||
| ... | @@ -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 | ); |
| 1302 | 1302 | ||
| 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 | ); |
| 1312 | 1312 | ||
| 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 | ); |
| 1318 | 1318 | ||
| 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 | ); |
| 1345 | 1345 | ||
| 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 | ); |
| 1361 | 1361 | ||
| 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 | ); |