| author | |
| committer | |
| log | 97c0373fa7ee125d2d4e73f9b1dc8ea0e2c2e86a |
| tree | d2aa342a53aef95f88456a63fa7874f3c51ba3b8 |
| parent | 75f3e7a4a05db7ea805e581f78117a41768945ae |
| parent | 516945d7d9b4d8b969d037076799d4ed29cecdda |
| signature |
Implement @prefetch()16 files changed, 395 insertions(+), 7 deletions(-)
doc/langref.html.in+44| ... | @@ -8674,6 +8674,50 @@ test "@wasmMemoryGrow" { | ... | @@ -8674,6 +8674,50 @@ test "@wasmMemoryGrow" { |
| 8674 | {#see_also|@ctz|@clz#} | 8674 | {#see_also|@ctz|@clz#} |
| 8675 | {#header_close#} | 8675 | {#header_close#} |
| 8676 | 8676 | ||
| 8677 | {#header_open|@prefetch#} | ||
| 8678 | <pre>{#syntax#}@prefetch(ptr: anytype, comptime options: std.builtin.PrefetchOptions){#endsyntax#}</pre> | ||
| 8679 | <p> | ||
| 8680 | This builtin tells the compiler to emit a prefetch instruction if supported by the | ||
| 8681 | target CPU. If the target CPU does not support the requested prefetch instruction, | ||
| 8682 | this builtin is a noop. This function has no effect on the behavior of the program, | ||
| 8683 | only on the performance characteristics. | ||
| 8684 | </p> | ||
| 8685 | <p> | ||
| 8686 | The {#syntax#}ptr{#endsyntax#} argument may be any pointer type and determines the memory | ||
| 8687 | address to prefetch. This function does not dereference the pointer, it is perfectly legal | ||
| 8688 | to pass a pointer to invalid memory to this function and no illegal behavior will result. | ||
| 8689 | </p> | ||
| 8690 | <p> | ||
| 8691 | The {#syntax#}options{#endsyntax#} argument is the following struct: | ||
| 8692 | </p> | ||
| 8693 | {#code_begin|syntax|builtin#} | ||
| 8694 | /// This data structure is used by the Zig language code generation and | ||
| 8695 | /// therefore must be kept in sync with the compiler implementation. | ||
| 8696 | pub const PrefetchOptions = struct { | ||
| 8697 | /// Whether the prefetch should prepare for a read or a write. | ||
| 8698 | rw: Rw = .read, | ||
| 8699 | /// 0 means no temporal locality. That is, the data can be immediately | ||
| 8700 | /// dropped from the cache after it is accessed. | ||
| 8701 | /// | ||
| 8702 | /// 3 means high temporal locality. That is, the data should be kept in | ||
| 8703 | /// the cache as it is likely to be accessed again soon. | ||
| 8704 | locality: u2 = 3, | ||
| 8705 | /// The cache that the prefetch should be preformed on. | ||
| 8706 | cache: Cache = .data, | ||
| 8707 | |||
| 8708 | pub const Rw = enum { | ||
| 8709 | read, | ||
| 8710 | write, | ||
| 8711 | }; | ||
| 8712 | |||
| 8713 | pub const Cache = enum { | ||
| 8714 | instruction, | ||
| 8715 | data, | ||
| 8716 | }; | ||
| 8717 | }; | ||
| 8718 | {#code_end#} | ||
| 8719 | {#header_close#} | ||
| 8720 | |||
| 8677 | {#header_open|@ptrCast#} | 8721 | {#header_open|@ptrCast#} |
| 8678 | <pre>{#syntax#}@ptrCast(comptime DestType: type, value: anytype) DestType{#endsyntax#}</pre> | 8722 | <pre>{#syntax#}@ptrCast(comptime DestType: type, value: anytype) DestType{#endsyntax#}</pre> |
| 8679 | <p> | 8723 | <p> |
lib/std/builtin.zig+25| ... | @@ -651,6 +651,31 @@ pub const CallOptions = struct { | ... | @@ -651,6 +651,31 @@ pub const CallOptions = struct { |
| 651 | }; | 651 | }; |
| 652 | }; | 652 | }; |
| 653 | 653 | ||
| 654 | /// This data structure is used by the Zig language code generation and | ||
| 655 | /// therefore must be kept in sync with the compiler implementation. | ||
| 656 | pub const PrefetchOptions = struct { | ||
| 657 | /// Whether the prefetch should prepare for a read or a write. | ||
| 658 | rw: Rw = .read, | ||
| 659 | /// 0 means no temporal locality. That is, the data can be immediately | ||
| 660 | /// dropped from the cache after it is accessed. | ||
| 661 | /// | ||
| 662 | /// 3 means high temporal locality. That is, the data should be kept in | ||
| 663 | /// the cache as it is likely to be accessed again soon. | ||
| 664 | locality: u2 = 3, | ||
| 665 | /// The cache that the prefetch should be preformed on. | ||
| 666 | cache: Cache = .data, | ||
| 667 | |||
| 668 | pub const Rw = enum { | ||
| 669 | read, | ||
| 670 | write, | ||
| 671 | }; | ||
| 672 | |||
| 673 | pub const Cache = enum { | ||
| 674 | instruction, | ||
| 675 | data, | ||
| 676 | }; | ||
| 677 | }; | ||
| 678 | |||
| 654 | /// This data structure is used by the Zig language code generation and | 679 | /// This data structure is used by the Zig language code generation and |
| 655 | /// therefore must be kept in sync with the compiler implementation. | 680 | /// therefore must be kept in sync with the compiler implementation. |
| 656 | pub const ExportOptions = struct { | 681 | pub const ExportOptions = struct { |
src/AstGen.zig+20-6| ... | @@ -6739,7 +6739,6 @@ fn builtinCall( | ... | @@ -6739,7 +6739,6 @@ fn builtinCall( |
| 6739 | } | 6739 | } |
| 6740 | } | 6740 | } |
| 6741 | 6741 | ||
| 6742 | // zig fmt: off | ||
| 6743 | switch (info.tag) { | 6742 | switch (info.tag) { |
| 6744 | .import => { | 6743 | .import => { |
| 6745 | const node_tags = tree.nodes.items(.tag); | 6744 | const node_tags = tree.nodes.items(.tag); |
| ... | @@ -6768,7 +6767,7 @@ fn builtinCall( | ... | @@ -6768,7 +6767,7 @@ fn builtinCall( |
| 6768 | astgen.extra.items[extra_index] = @enumToInt(param_ref); | 6767 | astgen.extra.items[extra_index] = @enumToInt(param_ref); |
| 6769 | extra_index += 1; | 6768 | extra_index += 1; |
| 6770 | } | 6769 | } |
| 6771 | const result = try gz.addExtendedMultiOpPayloadIndex(.compile_log,payload_index, params.len); | 6770 | const result = try gz.addExtendedMultiOpPayloadIndex(.compile_log, payload_index, params.len); |
| 6772 | return rvalue(gz, rl, result, node); | 6771 | return rvalue(gz, rl, result, node); |
| 6773 | }, | 6772 | }, |
| 6774 | .field => { | 6773 | .field => { |
| ... | @@ -6784,11 +6783,14 @@ fn builtinCall( | ... | @@ -6784,11 +6783,14 @@ fn builtinCall( |
| 6784 | }); | 6783 | }); |
| 6785 | return rvalue(gz, rl, result, node); | 6784 | return rvalue(gz, rl, result, node); |
| 6786 | }, | 6785 | }, |
| 6786 | |||
| 6787 | // zig fmt: off | ||
| 6787 | .as => return as( gz, scope, rl, node, params[0], params[1]), | 6788 | .as => return as( gz, scope, rl, node, params[0], params[1]), |
| 6788 | .bit_cast => return bitCast( gz, scope, rl, node, params[0], params[1]), | 6789 | .bit_cast => return bitCast( gz, scope, rl, node, params[0], params[1]), |
| 6789 | .TypeOf => return typeOf( gz, scope, rl, node, params), | 6790 | .TypeOf => return typeOf( gz, scope, rl, node, params), |
| 6790 | .union_init => return unionInit(gz, scope, rl, node, params), | 6791 | .union_init => return unionInit(gz, scope, rl, node, params), |
| 6791 | .c_import => return cImport( gz, scope, node, params[0]), | 6792 | .c_import => return cImport( gz, scope, node, params[0]), |
| 6793 | // zig fmt: on | ||
| 6792 | 6794 | ||
| 6793 | .@"export" => { | 6795 | .@"export" => { |
| 6794 | const node_tags = tree.nodes.items(.tag); | 6796 | const node_tags = tree.nodes.items(.tag); |
| ... | @@ -6858,9 +6860,7 @@ fn builtinCall( | ... | @@ -6858,9 +6860,7 @@ fn builtinCall( |
| 6858 | const field_ident = dot_token + 1; | 6860 | const field_ident = dot_token + 1; |
| 6859 | decl_name = try astgen.identAsString(field_ident); | 6861 | decl_name = try astgen.identAsString(field_ident); |
| 6860 | }, | 6862 | }, |
| 6861 | else => return astgen.failNode( | 6863 | else => return astgen.failNode(params[0], "symbol to export must identify a declaration", .{}), |
| 6862 | params[0], "symbol to export must identify a declaration", .{}, | ||
| 6863 | ), | ||
| 6864 | } | 6864 | } |
| 6865 | const options = try comptimeExpr(gz, scope, .{ .ty = .export_options_type }, params[1]); | 6865 | const options = try comptimeExpr(gz, scope, .{ .ty = .export_options_type }, params[1]); |
| 6866 | _ = try gz.addPlNode(.@"export", node, Zir.Inst.Export{ | 6866 | _ = try gz.addPlNode(.@"export", node, Zir.Inst.Export{ |
| ... | @@ -6888,6 +6888,7 @@ fn builtinCall( | ... | @@ -6888,6 +6888,7 @@ fn builtinCall( |
| 6888 | 6888 | ||
| 6889 | .breakpoint => return simpleNoOpVoid(gz, rl, node, .breakpoint), | 6889 | .breakpoint => return simpleNoOpVoid(gz, rl, node, .breakpoint), |
| 6890 | 6890 | ||
| 6891 | // zig fmt: off | ||
| 6891 | .This => return rvalue(gz, rl, try gz.addNodeExtended(.this, node), node), | 6892 | .This => return rvalue(gz, rl, try gz.addNodeExtended(.this, node), node), |
| 6892 | .return_address => return rvalue(gz, rl, try gz.addNodeExtended(.ret_addr, node), node), | 6893 | .return_address => return rvalue(gz, rl, try gz.addNodeExtended(.ret_addr, node), node), |
| 6893 | .src => return rvalue(gz, rl, try gz.addNodeExtended(.builtin_src, node), node), | 6894 | .src => return rvalue(gz, rl, try gz.addNodeExtended(.builtin_src, node), node), |
| ... | @@ -6942,6 +6943,8 @@ fn builtinCall( | ... | @@ -6942,6 +6943,8 @@ fn builtinCall( |
| 6942 | .err_set_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .err_set_cast), | 6943 | .err_set_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .err_set_cast), |
| 6943 | .ptr_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .ptr_cast), | 6944 | .ptr_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .ptr_cast), |
| 6944 | .truncate => return typeCast(gz, scope, rl, node, params[0], params[1], .truncate), | 6945 | .truncate => return typeCast(gz, scope, rl, node, params[0], params[1], .truncate), |
| 6946 | // zig fmt: on | ||
| 6947 | |||
| 6945 | .align_cast => { | 6948 | .align_cast => { |
| 6946 | const dest_align = try comptimeExpr(gz, scope, align_rl, params[0]); | 6949 | const dest_align = try comptimeExpr(gz, scope, align_rl, params[0]); |
| 6947 | const rhs = try expr(gz, scope, .none, params[1]); | 6950 | const rhs = try expr(gz, scope, .none, params[1]); |
| ... | @@ -6952,6 +6955,7 @@ fn builtinCall( | ... | @@ -6952,6 +6955,7 @@ fn builtinCall( |
| 6952 | return rvalue(gz, rl, result, node); | 6955 | return rvalue(gz, rl, result, node); |
| 6953 | }, | 6956 | }, |
| 6954 | 6957 | ||
| 6958 | // zig fmt: off | ||
| 6955 | .has_decl => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_decl), | 6959 | .has_decl => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_decl), |
| 6956 | .has_field => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_field), | 6960 | .has_field => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_field), |
| 6957 | 6961 | ||
| ... | @@ -6978,6 +6982,7 @@ fn builtinCall( | ... | @@ -6978,6 +6982,7 @@ fn builtinCall( |
| 6978 | 6982 | ||
| 6979 | .cmpxchg_strong => return cmpxchg(gz, scope, rl, node, params, .cmpxchg_strong), | 6983 | .cmpxchg_strong => return cmpxchg(gz, scope, rl, node, params, .cmpxchg_strong), |
| 6980 | .cmpxchg_weak => return cmpxchg(gz, scope, rl, node, params, .cmpxchg_weak), | 6984 | .cmpxchg_weak => return cmpxchg(gz, scope, rl, node, params, .cmpxchg_weak), |
| 6985 | // zig fmt: on | ||
| 6981 | 6986 | ||
| 6982 | .wasm_memory_size => { | 6987 | .wasm_memory_size => { |
| 6983 | const operand = try expr(gz, scope, .{ .ty = .u32_type }, params[0]); | 6988 | const operand = try expr(gz, scope, .{ .ty = .u32_type }, params[0]); |
| ... | @@ -7221,8 +7226,17 @@ fn builtinCall( | ... | @@ -7221,8 +7226,17 @@ fn builtinCall( |
| 7221 | }); | 7226 | }); |
| 7222 | return rvalue(gz, rl, result, node); | 7227 | return rvalue(gz, rl, result, node); |
| 7223 | }, | 7228 | }, |
| 7229 | .prefetch => { | ||
| 7230 | const ptr = try expr(gz, scope, .none, params[0]); | ||
| 7231 | const options = try comptimeExpr(gz, scope, .{ .ty = .prefetch_options_type }, params[1]); | ||
| 7232 | const result = try gz.addExtendedPayload(.prefetch, Zir.Inst.BinNode{ | ||
| 7233 | .node = gz.nodeIndexToRelative(node), | ||
| 7234 | .lhs = ptr, | ||
| 7235 | .rhs = options, | ||
| 7236 | }); | ||
| 7237 | return rvalue(gz, rl, result, node); | ||
| 7238 | }, | ||
| 7224 | } | 7239 | } |
| 7225 | // zig fmt: on | ||
| 7226 | } | 7240 | } |
| 7227 | 7241 | ||
| 7228 | fn simpleNoOpVoid( | 7242 | fn simpleNoOpVoid( |
src/BuiltinFn.zig+8| ... | @@ -67,6 +67,7 @@ pub const Tag = enum { | ... | @@ -67,6 +67,7 @@ pub const Tag = enum { |
| 67 | mul_with_overflow, | 67 | mul_with_overflow, |
| 68 | panic, | 68 | panic, |
| 69 | pop_count, | 69 | pop_count, |
| 70 | prefetch, | ||
| 70 | ptr_cast, | 71 | ptr_cast, |
| 71 | ptr_to_int, | 72 | ptr_to_int, |
| 72 | rem, | 73 | rem, |
| ... | @@ -615,6 +616,13 @@ pub const list = list: { | ... | @@ -615,6 +616,13 @@ pub const list = list: { |
| 615 | .param_count = 2, | 616 | .param_count = 2, |
| 616 | }, | 617 | }, |
| 617 | }, | 618 | }, |
| 619 | .{ | ||
| 620 | "@prefetch", | ||
| 621 | .{ | ||
| 622 | .tag = .prefetch, | ||
| 623 | .param_count = 2, | ||
| 624 | }, | ||
| 625 | }, | ||
| 618 | .{ | 626 | .{ |
| 619 | "@ptrCast", | 627 | "@ptrCast", |
| 620 | .{ | 628 | .{ |
src/Sema.zig+14| ... | @@ -1042,6 +1042,7 @@ fn zirExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -1042,6 +1042,7 @@ fn zirExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 1042 | .c_define => return sema.zirCDefine( block, extended), | 1042 | .c_define => return sema.zirCDefine( block, extended), |
| 1043 | .wasm_memory_size => return sema.zirWasmMemorySize( block, extended), | 1043 | .wasm_memory_size => return sema.zirWasmMemorySize( block, extended), |
| 1044 | .wasm_memory_grow => return sema.zirWasmMemoryGrow( block, extended), | 1044 | .wasm_memory_grow => return sema.zirWasmMemoryGrow( block, extended), |
| 1045 | .prefetch => return sema.zirPrefetch( block, extended), | ||
| 1045 | // zig fmt: on | 1046 | // zig fmt: on |
| 1046 | } | 1047 | } |
| 1047 | } | 1048 | } |
| ... | @@ -11104,6 +11105,16 @@ fn zirWasmMemoryGrow( | ... | @@ -11104,6 +11105,16 @@ fn zirWasmMemoryGrow( |
| 11104 | return sema.fail(block, src, "TODO: implement Sema.zirWasmMemoryGrow", .{}); | 11105 | return sema.fail(block, src, "TODO: implement Sema.zirWasmMemoryGrow", .{}); |
| 11105 | } | 11106 | } |
| 11106 | 11107 | ||
| 11108 | fn zirPrefetch( | ||
| 11109 | sema: *Sema, | ||
| 11110 | block: *Block, | ||
| 11111 | extended: Zir.Inst.Extended.InstData, | ||
| 11112 | ) CompileError!Air.Inst.Ref { | ||
| 11113 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; | ||
| 11114 | const src: LazySrcLoc = .{ .node_offset = extra.node }; | ||
| 11115 | return sema.fail(block, src, "TODO: implement Sema.zirPrefetch", .{}); | ||
| 11116 | } | ||
| 11117 | |||
| 11107 | fn zirBuiltinExtern( | 11118 | fn zirBuiltinExtern( |
| 11108 | sema: *Sema, | 11119 | sema: *Sema, |
| 11109 | block: *Block, | 11120 | block: *Block, |
| ... | @@ -14231,6 +14242,7 @@ fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Comp | ... | @@ -14231,6 +14242,7 @@ fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Comp |
| 14231 | .float_mode => return sema.resolveBuiltinTypeFields(block, src, "FloatMode"), | 14242 | .float_mode => return sema.resolveBuiltinTypeFields(block, src, "FloatMode"), |
| 14232 | .reduce_op => return sema.resolveBuiltinTypeFields(block, src, "ReduceOp"), | 14243 | .reduce_op => return sema.resolveBuiltinTypeFields(block, src, "ReduceOp"), |
| 14233 | .call_options => return sema.resolveBuiltinTypeFields(block, src, "CallOptions"), | 14244 | .call_options => return sema.resolveBuiltinTypeFields(block, src, "CallOptions"), |
| 14245 | .prefetch_options => return sema.resolveBuiltinTypeFields(block, src, "PrefetchOptions"), | ||
| 14234 | 14246 | ||
| 14235 | .@"union", .union_tagged => { | 14247 | .@"union", .union_tagged => { |
| 14236 | const union_obj = ty.cast(Type.Payload.Union).?.data; | 14248 | const union_obj = ty.cast(Type.Payload.Union).?.data; |
| ... | @@ -14819,6 +14831,7 @@ fn typeHasOnePossibleValue( | ... | @@ -14819,6 +14831,7 @@ fn typeHasOnePossibleValue( |
| 14819 | .float_mode, | 14831 | .float_mode, |
| 14820 | .reduce_op, | 14832 | .reduce_op, |
| 14821 | .call_options, | 14833 | .call_options, |
| 14834 | .prefetch_options, | ||
| 14822 | .export_options, | 14835 | .export_options, |
| 14823 | .extern_options, | 14836 | .extern_options, |
| 14824 | .type_info, | 14837 | .type_info, |
| ... | @@ -15032,6 +15045,7 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref { | ... | @@ -15032,6 +15045,7 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref { |
| 15032 | .float_mode => return .float_mode_type, | 15045 | .float_mode => return .float_mode_type, |
| 15033 | .reduce_op => return .reduce_op_type, | 15046 | .reduce_op => return .reduce_op_type, |
| 15034 | .call_options => return .call_options_type, | 15047 | .call_options => return .call_options_type, |
| 15048 | .prefetch_options => return .prefetch_options_type, | ||
| 15035 | .export_options => return .export_options_type, | 15049 | .export_options => return .export_options_type, |
| 15036 | .extern_options => return .extern_options_type, | 15050 | .extern_options => return .extern_options_type, |
| 15037 | .type_info => return .type_info_type, | 15051 | .type_info => return .type_info_type, |
src/Zir.zig+8| ... | @@ -1572,6 +1572,9 @@ pub const Inst = struct { | ... | @@ -1572,6 +1572,9 @@ pub const Inst = struct { |
| 1572 | wasm_memory_size, | 1572 | wasm_memory_size, |
| 1573 | /// `operand` is payload index to `BinNode`. | 1573 | /// `operand` is payload index to `BinNode`. |
| 1574 | wasm_memory_grow, | 1574 | wasm_memory_grow, |
| 1575 | /// The `@prefetch` builtin. | ||
| 1576 | /// `operand` is payload index to `BinNode`. | ||
| 1577 | prefetch, | ||
| 1575 | 1578 | ||
| 1576 | pub const InstData = struct { | 1579 | pub const InstData = struct { |
| 1577 | opcode: Extended, | 1580 | opcode: Extended, |
| ... | @@ -1648,6 +1651,7 @@ pub const Inst = struct { | ... | @@ -1648,6 +1651,7 @@ pub const Inst = struct { |
| 1648 | float_mode_type, | 1651 | float_mode_type, |
| 1649 | reduce_op_type, | 1652 | reduce_op_type, |
| 1650 | call_options_type, | 1653 | call_options_type, |
| 1654 | prefetch_options_type, | ||
| 1651 | export_options_type, | 1655 | export_options_type, |
| 1652 | extern_options_type, | 1656 | extern_options_type, |
| 1653 | type_info_type, | 1657 | type_info_type, |
| ... | @@ -1917,6 +1921,10 @@ pub const Inst = struct { | ... | @@ -1917,6 +1921,10 @@ pub const Inst = struct { |
| 1917 | .ty = Type.initTag(.type), | 1921 | .ty = Type.initTag(.type), |
| 1918 | .val = Value.initTag(.call_options_type), | 1922 | .val = Value.initTag(.call_options_type), |
| 1919 | }, | 1923 | }, |
| 1924 | .prefetch_options_type = .{ | ||
| 1925 | .ty = Type.initTag(.type), | ||
| 1926 | .val = Value.initTag(.prefetch_options_type), | ||
| 1927 | }, | ||
| 1920 | .export_options_type = .{ | 1928 | .export_options_type = .{ |
| 1921 | .ty = Type.initTag(.type), | 1929 | .ty = Type.initTag(.type), |
| 1922 | .val = Value.initTag(.export_options_type), | 1930 | .val = Value.initTag(.export_options_type), |
src/print_zir.zig+1-1| ... | @@ -477,7 +477,7 @@ const Writer = struct { | ... | @@ -477,7 +477,7 @@ const Writer = struct { |
| 477 | try self.writeSrc(stream, src); | 477 | try self.writeSrc(stream, src); |
| 478 | }, | 478 | }, |
| 479 | 479 | ||
| 480 | .builtin_extern, .c_define, .wasm_memory_grow => { | 480 | .builtin_extern, .c_define, .wasm_memory_grow, .prefetch => { |
| 481 | const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data; | 481 | const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| 482 | const src: LazySrcLoc = .{ .node_offset = inst_data.node }; | 482 | const src: LazySrcLoc = .{ .node_offset = inst_data.node }; |
| 483 | try self.writeInstRef(stream, inst_data.lhs); | 483 | try self.writeInstRef(stream, inst_data.lhs); |
src/stage1/all_types.hpp+34| ... | @@ -898,6 +898,18 @@ struct AstNodeFnCallExpr { | ... | @@ -898,6 +898,18 @@ struct AstNodeFnCallExpr { |
| 898 | bool seen; // used by @compileLog | 898 | bool seen; // used by @compileLog |
| 899 | }; | 899 | }; |
| 900 | 900 | ||
| 901 | // Must be kept in sync with std.builtin.PrefetchOptions.Rw | ||
| 902 | enum PrefetchRw { | ||
| 903 | PrefetchRwRead, | ||
| 904 | PrefetchRwWrite, | ||
| 905 | }; | ||
| 906 | |||
| 907 | // Must be kept in sync with std.builtin.PrefetchOptions.Cache | ||
| 908 | enum PrefetchCache { | ||
| 909 | PrefetchCacheInstruction, | ||
| 910 | PrefetchCacheData, | ||
| 911 | }; | ||
| 912 | |||
| 901 | struct AstNodeArrayAccessExpr { | 913 | struct AstNodeArrayAccessExpr { |
| 902 | AstNode *array_ref_expr; | 914 | AstNode *array_ref_expr; |
| 903 | AstNode *subscript; | 915 | AstNode *subscript; |
| ... | @@ -1818,6 +1830,7 @@ enum BuiltinFnId { | ... | @@ -1818,6 +1830,7 @@ enum BuiltinFnId { |
| 1818 | BuiltinFnIdReduce, | 1830 | BuiltinFnIdReduce, |
| 1819 | BuiltinFnIdMaximum, | 1831 | BuiltinFnIdMaximum, |
| 1820 | BuiltinFnIdMinimum, | 1832 | BuiltinFnIdMinimum, |
| 1833 | BuiltinFnIdPrefetch, | ||
| 1821 | }; | 1834 | }; |
| 1822 | 1835 | ||
| 1823 | struct BuiltinFnEntry { | 1836 | struct BuiltinFnEntry { |
| ... | @@ -2021,6 +2034,7 @@ struct CodeGen { | ... | @@ -2021,6 +2034,7 @@ struct CodeGen { |
| 2021 | LLVMValueRef return_err_fn; | 2034 | LLVMValueRef return_err_fn; |
| 2022 | LLVMValueRef wasm_memory_size; | 2035 | LLVMValueRef wasm_memory_size; |
| 2023 | LLVMValueRef wasm_memory_grow; | 2036 | LLVMValueRef wasm_memory_grow; |
| 2037 | LLVMValueRef prefetch; | ||
| 2024 | LLVMTypeRef anyframe_fn_type; | 2038 | LLVMTypeRef anyframe_fn_type; |
| 2025 | 2039 | ||
| 2026 | // reminder: hash tables must be initialized before use | 2040 | // reminder: hash tables must be initialized before use |
| ... | @@ -2647,6 +2661,7 @@ enum Stage1ZirInstId : uint8_t { | ... | @@ -2647,6 +2661,7 @@ enum Stage1ZirInstId : uint8_t { |
| 2647 | Stage1ZirInstIdWasmMemorySize, | 2661 | Stage1ZirInstIdWasmMemorySize, |
| 2648 | Stage1ZirInstIdWasmMemoryGrow, | 2662 | Stage1ZirInstIdWasmMemoryGrow, |
| 2649 | Stage1ZirInstIdSrc, | 2663 | Stage1ZirInstIdSrc, |
| 2664 | Stage1ZirInstIdPrefetch, | ||
| 2650 | }; | 2665 | }; |
| 2651 | 2666 | ||
| 2652 | // ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR. | 2667 | // ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR. |
| ... | @@ -2743,6 +2758,7 @@ enum Stage1AirInstId : uint8_t { | ... | @@ -2743,6 +2758,7 @@ enum Stage1AirInstId : uint8_t { |
| 2743 | Stage1AirInstIdWasmMemorySize, | 2758 | Stage1AirInstIdWasmMemorySize, |
| 2744 | Stage1AirInstIdWasmMemoryGrow, | 2759 | Stage1AirInstIdWasmMemoryGrow, |
| 2745 | Stage1AirInstIdExtern, | 2760 | Stage1AirInstIdExtern, |
| 2761 | Stage1AirInstIdPrefetch, | ||
| 2746 | }; | 2762 | }; |
| 2747 | 2763 | ||
| 2748 | struct Stage1ZirInst { | 2764 | struct Stage1ZirInst { |
| ... | @@ -3683,6 +3699,24 @@ struct Stage1ZirInstSrc { | ... | @@ -3683,6 +3699,24 @@ struct Stage1ZirInstSrc { |
| 3683 | Stage1ZirInst base; | 3699 | Stage1ZirInst base; |
| 3684 | }; | 3700 | }; |
| 3685 | 3701 | ||
| 3702 | struct Stage1ZirInstPrefetch { | ||
| 3703 | Stage1ZirInst base; | ||
| 3704 | |||
| 3705 | Stage1ZirInst *ptr; | ||
| 3706 | Stage1ZirInst *options; | ||
| 3707 | }; | ||
| 3708 | |||
| 3709 | struct Stage1AirInstPrefetch { | ||
| 3710 | Stage1AirInst base; | ||
| 3711 | |||
| 3712 | Stage1AirInst *ptr; | ||
| 3713 | PrefetchRw rw; | ||
| 3714 | // Must be in the range 0-3 inclusive | ||
| 3715 | uint8_t locality; | ||
| 3716 | PrefetchCache cache; | ||
| 3717 | }; | ||
| 3718 | |||
| 3719 | |||
| 3686 | struct Stage1ZirInstSlice { | 3720 | struct Stage1ZirInstSlice { |
| 3687 | Stage1ZirInst base; | 3721 | Stage1ZirInst base; |
| 3688 | 3722 |
src/stage1/astgen.cpp+44| ... | @@ -349,6 +349,8 @@ void destroy_instruction_src(Stage1ZirInst *inst) { | ... | @@ -349,6 +349,8 @@ void destroy_instruction_src(Stage1ZirInst *inst) { |
| 349 | return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstWasmMemoryGrow *>(inst)); | 349 | return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstWasmMemoryGrow *>(inst)); |
| 350 | case Stage1ZirInstIdSrc: | 350 | case Stage1ZirInstIdSrc: |
| 351 | return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSrc *>(inst)); | 351 | return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSrc *>(inst)); |
| 352 | case Stage1ZirInstIdPrefetch: | ||
| 353 | return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstPrefetch *>(inst)); | ||
| 352 | } | 354 | } |
| 353 | zig_unreachable(); | 355 | zig_unreachable(); |
| 354 | } | 356 | } |
| ... | @@ -941,6 +943,10 @@ static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSrc *) { | ... | @@ -941,6 +943,10 @@ static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSrc *) { |
| 941 | return Stage1ZirInstIdSrc; | 943 | return Stage1ZirInstIdSrc; |
| 942 | } | 944 | } |
| 943 | 945 | ||
| 946 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstPrefetch *) { | ||
| 947 | return Stage1ZirInstIdPrefetch; | ||
| 948 | } | ||
| 949 | |||
| 944 | template<typename T> | 950 | template<typename T> |
| 945 | static T *ir_create_instruction(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { | 951 | static T *ir_create_instruction(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { |
| 946 | T *special_instruction = heap::c_allocator.create<T>(); | 952 | T *special_instruction = heap::c_allocator.create<T>(); |
| ... | @@ -2870,6 +2876,21 @@ static Stage1ZirInst *ir_build_src(Stage1AstGen *ag, Scope *scope, AstNode *sour | ... | @@ -2870,6 +2876,21 @@ static Stage1ZirInst *ir_build_src(Stage1AstGen *ag, Scope *scope, AstNode *sour |
| 2870 | return &instruction->base; | 2876 | return &instruction->base; |
| 2871 | } | 2877 | } |
| 2872 | 2878 | ||
| 2879 | static Stage1ZirInst *ir_build_prefetch(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2880 | Stage1ZirInst *ptr, Stage1ZirInst *options) | ||
| 2881 | { | ||
| 2882 | Stage1ZirInstPrefetch *prefetch_instruction = ir_build_instruction<Stage1ZirInstPrefetch>( | ||
| 2883 | ag, scope, source_node); | ||
| 2884 | prefetch_instruction->ptr = ptr; | ||
| 2885 | prefetch_instruction->options = options; | ||
| 2886 | |||
| 2887 | ir_ref_instruction(ptr, ag->current_basic_block); | ||
| 2888 | ir_ref_instruction(options, ag->current_basic_block); | ||
| 2889 | |||
| 2890 | return &prefetch_instruction->base; | ||
| 2891 | } | ||
| 2892 | |||
| 2893 | |||
| 2873 | static void ir_count_defers(Stage1AstGen *ag, Scope *inner_scope, Scope *outer_scope, size_t *results) { | 2894 | static void ir_count_defers(Stage1AstGen *ag, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 2874 | results[ReturnKindUnconditional] = 0; | 2895 | results[ReturnKindUnconditional] = 0; |
| 2875 | results[ReturnKindError] = 0; | 2896 | results[ReturnKindError] = 0; |
| ... | @@ -5416,6 +5437,29 @@ static Stage1ZirInst *astgen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, Ast | ... | @@ -5416,6 +5437,29 @@ static Stage1ZirInst *astgen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, Ast |
| 5416 | Stage1ZirInst *src_inst = ir_build_src(ag, scope, node); | 5437 | Stage1ZirInst *src_inst = ir_build_src(ag, scope, node); |
| 5417 | return ir_lval_wrap(ag, scope, src_inst, lval, result_loc); | 5438 | return ir_lval_wrap(ag, scope, src_inst, lval, result_loc); |
| 5418 | } | 5439 | } |
| 5440 | case BuiltinFnIdPrefetch: | ||
| 5441 | { | ||
| 5442 | ZigType *options_type = get_builtin_type(ag->codegen, "PrefetchOptions"); | ||
| 5443 | Stage1ZirInst *options_type_inst = ir_build_const_type(ag, scope, node, options_type); | ||
| 5444 | ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, options_type_inst, no_result_loc()); | ||
| 5445 | |||
| 5446 | AstNode *ptr_node = node->data.fn_call_expr.params.at(0); | ||
| 5447 | Stage1ZirInst *ptr_value = astgen_node(ag, ptr_node, scope); | ||
| 5448 | if (ptr_value == ag->codegen->invalid_inst_src) | ||
| 5449 | return ptr_value; | ||
| 5450 | |||
| 5451 | AstNode *options_node = node->data.fn_call_expr.params.at(1); | ||
| 5452 | Stage1ZirInst *options_value = astgen_node_extra(ag, options_node, | ||
| 5453 | scope, LValNone, &result_loc_cast->base); | ||
| 5454 | if (options_value == ag->codegen->invalid_inst_src) | ||
| 5455 | return options_value; | ||
| 5456 | |||
| 5457 | Stage1ZirInst *casted_options_value = ir_build_implicit_cast( | ||
| 5458 | ag, scope, options_node, options_value, result_loc_cast); | ||
| 5459 | |||
| 5460 | Stage1ZirInst *ir_extern = ir_build_prefetch(ag, scope, node, ptr_value, casted_options_value); | ||
| 5461 | return ir_lval_wrap(ag, scope, ir_extern, lval, result_loc); | ||
| 5462 | } | ||
| 5419 | } | 5463 | } |
| 5420 | zig_unreachable(); | 5464 | zig_unreachable(); |
| 5421 | } | 5465 | } |
src/stage1/codegen.cpp+67| ... | @@ -1139,6 +1139,24 @@ static LLVMValueRef gen_wasm_memory_grow(CodeGen *g) { | ... | @@ -1139,6 +1139,24 @@ static LLVMValueRef gen_wasm_memory_grow(CodeGen *g) { |
| 1139 | return g->wasm_memory_grow; | 1139 | return g->wasm_memory_grow; |
| 1140 | } | 1140 | } |
| 1141 | 1141 | ||
| 1142 | static LLVMValueRef gen_prefetch(CodeGen *g) { | ||
| 1143 | if (g->prefetch) | ||
| 1144 | return g->prefetch; | ||
| 1145 | |||
| 1146 | // declare void @llvm.prefetch(i8*, i32, i32, i32) | ||
| 1147 | LLVMTypeRef param_types[] = { | ||
| 1148 | LLVMPointerType(LLVMInt8Type(), 0), | ||
| 1149 | LLVMInt32Type(), | ||
| 1150 | LLVMInt32Type(), | ||
| 1151 | LLVMInt32Type(), | ||
| 1152 | }; | ||
| 1153 | LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 4, false); | ||
| 1154 | g->prefetch = LLVMAddFunction(g->module, "llvm.prefetch.p0i8", fn_type); | ||
| 1155 | assert(LLVMGetIntrinsicID(g->prefetch)); | ||
| 1156 | |||
| 1157 | return g->prefetch; | ||
| 1158 | } | ||
| 1159 | |||
| 1142 | static LLVMValueRef get_stacksave_fn_val(CodeGen *g) { | 1160 | static LLVMValueRef get_stacksave_fn_val(CodeGen *g) { |
| 1143 | if (g->stacksave_fn_val) | 1161 | if (g->stacksave_fn_val) |
| 1144 | return g->stacksave_fn_val; | 1162 | return g->stacksave_fn_val; |
| ... | @@ -5899,6 +5917,52 @@ static LLVMValueRef ir_render_wasm_memory_grow(CodeGen *g, Stage1Air *executable | ... | @@ -5899,6 +5917,52 @@ static LLVMValueRef ir_render_wasm_memory_grow(CodeGen *g, Stage1Air *executable |
| 5899 | return val; | 5917 | return val; |
| 5900 | } | 5918 | } |
| 5901 | 5919 | ||
| 5920 | static LLVMValueRef ir_render_prefetch(CodeGen *g, Stage1Air *executable, Stage1AirInstPrefetch *instruction) { | ||
| 5921 | static_assert(PrefetchRwRead == 0, ""); | ||
| 5922 | static_assert(PrefetchRwWrite == 1, ""); | ||
| 5923 | assert(instruction->rw == PrefetchRwRead || instruction->rw == PrefetchRwWrite); | ||
| 5924 | |||
| 5925 | assert(instruction->locality >= 0 && instruction->locality <= 3); | ||
| 5926 | |||
| 5927 | static_assert(PrefetchCacheInstruction == 0, ""); | ||
| 5928 | static_assert(PrefetchCacheData == 1, ""); | ||
| 5929 | assert(instruction->cache == PrefetchCacheData || instruction->cache == PrefetchCacheInstruction); | ||
| 5930 | |||
| 5931 | // LLVM fails during codegen of instruction cache prefetchs for these architectures. | ||
| 5932 | // This is an LLVM bug as the prefetch intrinsic should be a noop if not supported by the target. | ||
| 5933 | // To work around this, simply don't emit llvm.prefetch in this case. | ||
| 5934 | // See https://bugs.llvm.org/show_bug.cgi?id=21037 | ||
| 5935 | if (instruction->cache == PrefetchCacheInstruction) { | ||
| 5936 | switch (g->zig_target->arch) { | ||
| 5937 | case ZigLLVM_x86: | ||
| 5938 | case ZigLLVM_x86_64: | ||
| 5939 | return nullptr; | ||
| 5940 | default: | ||
| 5941 | break; | ||
| 5942 | } | ||
| 5943 | } | ||
| 5944 | |||
| 5945 | // Another case of the same LLVM bug described above | ||
| 5946 | if (instruction->rw == PrefetchRwWrite && instruction->cache == PrefetchCacheInstruction) { | ||
| 5947 | switch (g->zig_target->arch) { | ||
| 5948 | case ZigLLVM_arm: | ||
| 5949 | return nullptr; | ||
| 5950 | default: | ||
| 5951 | break; | ||
| 5952 | } | ||
| 5953 | |||
| 5954 | } | ||
| 5955 | |||
| 5956 | LLVMValueRef params[] = { | ||
| 5957 | LLVMBuildBitCast(g->builder, ir_llvm_value(g, instruction->ptr), LLVMPointerType(LLVMInt8Type(), 0), ""), | ||
| 5958 | LLVMConstInt(LLVMInt32Type(), instruction->rw, false), | ||
| 5959 | LLVMConstInt(LLVMInt32Type(), instruction->locality, false), | ||
| 5960 | LLVMConstInt(LLVMInt32Type(), instruction->cache, false), | ||
| 5961 | }; | ||
| 5962 | LLVMValueRef val = LLVMBuildCall(g->builder, gen_prefetch(g), params, 4, ""); | ||
| 5963 | return val; | ||
| 5964 | } | ||
| 5965 | |||
| 5902 | static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1AirInstSlice *instruction) { | 5966 | static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1AirInstSlice *instruction) { |
| 5903 | Error err; | 5967 | Error err; |
| 5904 | 5968 | ||
| ... | @@ -7150,6 +7214,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, Stage1Air *executable, Sta | ... | @@ -7150,6 +7214,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, Stage1Air *executable, Sta |
| 7150 | return ir_render_wasm_memory_grow(g, executable, (Stage1AirInstWasmMemoryGrow *) instruction); | 7214 | return ir_render_wasm_memory_grow(g, executable, (Stage1AirInstWasmMemoryGrow *) instruction); |
| 7151 | case Stage1AirInstIdExtern: | 7215 | case Stage1AirInstIdExtern: |
| 7152 | return ir_render_extern(g, executable, (Stage1AirInstExtern *) instruction); | 7216 | return ir_render_extern(g, executable, (Stage1AirInstExtern *) instruction); |
| 7217 | case Stage1AirInstIdPrefetch: | ||
| 7218 | return ir_render_prefetch(g, executable, (Stage1AirInstPrefetch *) instruction); | ||
| 7153 | } | 7219 | } |
| 7154 | zig_unreachable(); | 7220 | zig_unreachable(); |
| 7155 | } | 7221 | } |
| ... | @@ -9120,6 +9186,7 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -9120,6 +9186,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 9120 | create_builtin_fn(g, BuiltinFnIdReduce, "reduce", 2); | 9186 | create_builtin_fn(g, BuiltinFnIdReduce, "reduce", 2); |
| 9121 | create_builtin_fn(g, BuiltinFnIdMaximum, "maximum", 2); | 9187 | create_builtin_fn(g, BuiltinFnIdMaximum, "maximum", 2); |
| 9122 | create_builtin_fn(g, BuiltinFnIdMinimum, "minimum", 2); | 9188 | create_builtin_fn(g, BuiltinFnIdMinimum, "minimum", 2); |
| 9189 | create_builtin_fn(g, BuiltinFnIdPrefetch, "prefetch", 2); | ||
| 9123 | } | 9190 | } |
| 9124 | 9191 | ||
| 9125 | static const char *bool_to_str(bool b) { | 9192 | static const char *bool_to_str(bool b) { |
src/stage1/ir.cpp+56| ... | @@ -467,6 +467,8 @@ void destroy_instruction_gen(Stage1AirInst *inst) { | ... | @@ -467,6 +467,8 @@ void destroy_instruction_gen(Stage1AirInst *inst) { |
| 467 | return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstWasmMemoryGrow *>(inst)); | 467 | return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstWasmMemoryGrow *>(inst)); |
| 468 | case Stage1AirInstIdExtern: | 468 | case Stage1AirInstIdExtern: |
| 469 | return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstExtern *>(inst)); | 469 | return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstExtern *>(inst)); |
| 470 | case Stage1AirInstIdPrefetch: | ||
| 471 | return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstPrefetch *>(inst)); | ||
| 470 | } | 472 | } |
| 471 | zig_unreachable(); | 473 | zig_unreachable(); |
| 472 | } | 474 | } |
| ... | @@ -1115,6 +1117,10 @@ static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstExtern *) { | ... | @@ -1115,6 +1117,10 @@ static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstExtern *) { |
| 1115 | return Stage1AirInstIdExtern; | 1117 | return Stage1AirInstIdExtern; |
| 1116 | } | 1118 | } |
| 1117 | 1119 | ||
| 1120 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstPrefetch *) { | ||
| 1121 | return Stage1AirInstIdPrefetch; | ||
| 1122 | } | ||
| 1123 | |||
| 1118 | template<typename T> | 1124 | template<typename T> |
| 1119 | static T *ir_create_inst_gen(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { | 1125 | static T *ir_create_inst_gen(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { |
| 1120 | T *special_instruction = heap::c_allocator.create<T>(); | 1126 | T *special_instruction = heap::c_allocator.create<T>(); |
| ... | @@ -24853,6 +24859,52 @@ static Stage1AirInst *ir_analyze_instruction_src(IrAnalyze *ira, Stage1ZirInstSr | ... | @@ -24853,6 +24859,52 @@ static Stage1AirInst *ir_analyze_instruction_src(IrAnalyze *ira, Stage1ZirInstSr |
| 24853 | return ir_const_move(ira, instruction->base.scope, instruction->base.source_node, result); | 24859 | return ir_const_move(ira, instruction->base.scope, instruction->base.source_node, result); |
| 24854 | } | 24860 | } |
| 24855 | 24861 | ||
| 24862 | static Stage1AirInst *ir_analyze_instruction_prefetch(IrAnalyze *ira, Stage1ZirInstPrefetch *instruction) { | ||
| 24863 | Stage1AirInst *ptr = instruction->ptr->child; | ||
| 24864 | if (type_is_invalid(ptr->value->type)) | ||
| 24865 | return ira->codegen->invalid_inst_gen; | ||
| 24866 | |||
| 24867 | Stage1AirInst *raw_options_inst = instruction->options->child; | ||
| 24868 | if (type_is_invalid(raw_options_inst->value->type)) | ||
| 24869 | return ira->codegen->invalid_inst_gen; | ||
| 24870 | |||
| 24871 | ZigType *options_type = get_builtin_type(ira->codegen, "PrefetchOptions"); | ||
| 24872 | Stage1AirInst *options_inst = ir_implicit_cast(ira, raw_options_inst, options_type); | ||
| 24873 | if (type_is_invalid(options_inst->value->type)) | ||
| 24874 | return ira->codegen->invalid_inst_gen; | ||
| 24875 | |||
| 24876 | ZigValue *options_val = ir_resolve_const(ira, options_inst, UndefBad); | ||
| 24877 | if (options_val == nullptr) | ||
| 24878 | return ira->codegen->invalid_inst_gen; | ||
| 24879 | |||
| 24880 | ZigValue *rw_val = get_const_field(ira, options_inst->source_node, options_val, "rw", 0); | ||
| 24881 | if (rw_val == nullptr) | ||
| 24882 | return ira->codegen->invalid_inst_gen; | ||
| 24883 | PrefetchRw rw = (PrefetchRw)bigint_as_u8(&rw_val->data.x_enum_tag); | ||
| 24884 | |||
| 24885 | ZigValue *locality_val = get_const_field(ira, options_inst->source_node, options_val, "locality", 1); | ||
| 24886 | if (locality_val == nullptr) | ||
| 24887 | return ira->codegen->invalid_inst_gen; | ||
| 24888 | uint8_t locality = bigint_as_u8(&locality_val->data.x_bigint); | ||
| 24889 | assert(locality <= 3); | ||
| 24890 | |||
| 24891 | ZigValue *cache_val = get_const_field(ira, options_inst->source_node, options_val, "cache", 2); | ||
| 24892 | if (cache_val == nullptr) | ||
| 24893 | return ira->codegen->invalid_inst_gen; | ||
| 24894 | PrefetchCache cache = (PrefetchCache)bigint_as_u8(&cache_val->data.x_enum_tag); | ||
| 24895 | |||
| 24896 | Stage1AirInstPrefetch *air_instruction = ir_build_inst_void<Stage1AirInstPrefetch>(&ira->new_irb, | ||
| 24897 | instruction->base.scope, instruction->base.source_node); | ||
| 24898 | air_instruction->ptr = ptr; | ||
| 24899 | air_instruction->rw = rw; | ||
| 24900 | air_instruction->locality = locality; | ||
| 24901 | air_instruction->cache = cache; | ||
| 24902 | |||
| 24903 | ir_ref_inst_gen(ptr); | ||
| 24904 | |||
| 24905 | return &air_instruction->base; | ||
| 24906 | } | ||
| 24907 | |||
| 24856 | static Stage1AirInst *ir_analyze_instruction_base(IrAnalyze *ira, Stage1ZirInst *instruction) { | 24908 | static Stage1AirInst *ir_analyze_instruction_base(IrAnalyze *ira, Stage1ZirInst *instruction) { |
| 24857 | switch (instruction->id) { | 24909 | switch (instruction->id) { |
| 24858 | case Stage1ZirInstIdInvalid: | 24910 | case Stage1ZirInstIdInvalid: |
| ... | @@ -25138,6 +25190,8 @@ static Stage1AirInst *ir_analyze_instruction_base(IrAnalyze *ira, Stage1ZirInst | ... | @@ -25138,6 +25190,8 @@ static Stage1AirInst *ir_analyze_instruction_base(IrAnalyze *ira, Stage1ZirInst |
| 25138 | return ir_analyze_instruction_wasm_memory_grow(ira, (Stage1ZirInstWasmMemoryGrow *)instruction); | 25190 | return ir_analyze_instruction_wasm_memory_grow(ira, (Stage1ZirInstWasmMemoryGrow *)instruction); |
| 25139 | case Stage1ZirInstIdSrc: | 25191 | case Stage1ZirInstIdSrc: |
| 25140 | return ir_analyze_instruction_src(ira, (Stage1ZirInstSrc *)instruction); | 25192 | return ir_analyze_instruction_src(ira, (Stage1ZirInstSrc *)instruction); |
| 25193 | case Stage1ZirInstIdPrefetch: | ||
| 25194 | return ir_analyze_instruction_prefetch(ira, (Stage1ZirInstPrefetch *)instruction); | ||
| 25141 | } | 25195 | } |
| 25142 | zig_unreachable(); | 25196 | zig_unreachable(); |
| 25143 | } | 25197 | } |
| ... | @@ -25305,6 +25359,7 @@ bool ir_inst_gen_has_side_effects(Stage1AirInst *instruction) { | ... | @@ -25305,6 +25359,7 @@ bool ir_inst_gen_has_side_effects(Stage1AirInst *instruction) { |
| 25305 | case Stage1AirInstIdSpillBegin: | 25359 | case Stage1AirInstIdSpillBegin: |
| 25306 | case Stage1AirInstIdWasmMemoryGrow: | 25360 | case Stage1AirInstIdWasmMemoryGrow: |
| 25307 | case Stage1AirInstIdExtern: | 25361 | case Stage1AirInstIdExtern: |
| 25362 | case Stage1AirInstIdPrefetch: | ||
| 25308 | return true; | 25363 | return true; |
| 25309 | 25364 | ||
| 25310 | case Stage1AirInstIdPhi: | 25365 | case Stage1AirInstIdPhi: |
| ... | @@ -25444,6 +25499,7 @@ bool ir_inst_src_has_side_effects(Stage1ZirInst *instruction) { | ... | @@ -25444,6 +25499,7 @@ bool ir_inst_src_has_side_effects(Stage1ZirInst *instruction) { |
| 25444 | case Stage1ZirInstIdAwait: | 25499 | case Stage1ZirInstIdAwait: |
| 25445 | case Stage1ZirInstIdSpillBegin: | 25500 | case Stage1ZirInstIdSpillBegin: |
| 25446 | case Stage1ZirInstIdWasmMemoryGrow: | 25501 | case Stage1ZirInstIdWasmMemoryGrow: |
| 25502 | case Stage1ZirInstIdPrefetch: | ||
| 25447 | return true; | 25503 | return true; |
| 25448 | 25504 | ||
| 25449 | case Stage1ZirInstIdPhi: | 25505 | case Stage1ZirInstIdPhi: |
src/stage1/ir_print.cpp+22| ... | @@ -371,6 +371,8 @@ const char* ir_inst_src_type_str(Stage1ZirInstId id) { | ... | @@ -371,6 +371,8 @@ const char* ir_inst_src_type_str(Stage1ZirInstId id) { |
| 371 | return "SrcWasmMemoryGrow"; | 371 | return "SrcWasmMemoryGrow"; |
| 372 | case Stage1ZirInstIdSrc: | 372 | case Stage1ZirInstIdSrc: |
| 373 | return "SrcSrc"; | 373 | return "SrcSrc"; |
| 374 | case Stage1ZirInstIdPrefetch: | ||
| 375 | return "SrcPrefetch"; | ||
| 374 | } | 376 | } |
| 375 | zig_unreachable(); | 377 | zig_unreachable(); |
| 376 | } | 378 | } |
| ... | @@ -559,6 +561,8 @@ const char* ir_inst_gen_type_str(Stage1AirInstId id) { | ... | @@ -559,6 +561,8 @@ const char* ir_inst_gen_type_str(Stage1AirInstId id) { |
| 559 | return "GenWasmMemoryGrow"; | 561 | return "GenWasmMemoryGrow"; |
| 560 | case Stage1AirInstIdExtern: | 562 | case Stage1AirInstIdExtern: |
| 561 | return "GenExtern"; | 563 | return "GenExtern"; |
| 564 | case Stage1AirInstIdPrefetch: | ||
| 565 | return "GenPrefetch"; | ||
| 562 | } | 566 | } |
| 563 | zig_unreachable(); | 567 | zig_unreachable(); |
| 564 | } | 568 | } |
| ... | @@ -2436,6 +2440,18 @@ static void ir_print_extern(IrPrintSrc *irp, Stage1ZirInstExtern *instruction) { | ... | @@ -2436,6 +2440,18 @@ static void ir_print_extern(IrPrintSrc *irp, Stage1ZirInstExtern *instruction) { |
| 2436 | fprintf(irp->f, ")"); | 2440 | fprintf(irp->f, ")"); |
| 2437 | } | 2441 | } |
| 2438 | 2442 | ||
| 2443 | static void ir_print_prefetch(IrPrintSrc *irp, Stage1ZirInstPrefetch *instruction) { | ||
| 2444 | fprintf(irp->f, "@prefetch("); | ||
| 2445 | ir_print_other_inst_src(irp, instruction->ptr); | ||
| 2446 | fprintf(irp->f, ","); | ||
| 2447 | ir_print_other_inst_src(irp, instruction->options); | ||
| 2448 | fprintf(irp->f, ")"); | ||
| 2449 | } | ||
| 2450 | |||
| 2451 | static void ir_print_prefetch(IrPrintGen *irp, Stage1AirInstPrefetch *instruction) { | ||
| 2452 | fprintf(irp->f, "@prefetch(...)"); | ||
| 2453 | } | ||
| 2454 | |||
| 2439 | static void ir_print_error_return_trace(IrPrintSrc *irp, Stage1ZirInstErrorReturnTrace *instruction) { | 2455 | static void ir_print_error_return_trace(IrPrintSrc *irp, Stage1ZirInstErrorReturnTrace *instruction) { |
| 2440 | fprintf(irp->f, "@errorReturnTrace("); | 2456 | fprintf(irp->f, "@errorReturnTrace("); |
| 2441 | switch (instruction->optional) { | 2457 | switch (instruction->optional) { |
| ... | @@ -3108,6 +3124,9 @@ static void ir_print_inst_src(IrPrintSrc *irp, Stage1ZirInst *instruction, bool | ... | @@ -3108,6 +3124,9 @@ static void ir_print_inst_src(IrPrintSrc *irp, Stage1ZirInst *instruction, bool |
| 3108 | case Stage1ZirInstIdSrc: | 3124 | case Stage1ZirInstIdSrc: |
| 3109 | ir_print_builtin_src(irp, (Stage1ZirInstSrc *)instruction); | 3125 | ir_print_builtin_src(irp, (Stage1ZirInstSrc *)instruction); |
| 3110 | break; | 3126 | break; |
| 3127 | case Stage1ZirInstIdPrefetch: | ||
| 3128 | ir_print_prefetch(irp, (Stage1ZirInstPrefetch *)instruction); | ||
| 3129 | break; | ||
| 3111 | } | 3130 | } |
| 3112 | fprintf(irp->f, "\n"); | 3131 | fprintf(irp->f, "\n"); |
| 3113 | } | 3132 | } |
| ... | @@ -3387,6 +3406,9 @@ static void ir_print_inst_gen(IrPrintGen *irp, Stage1AirInst *instruction, bool | ... | @@ -3387,6 +3406,9 @@ static void ir_print_inst_gen(IrPrintGen *irp, Stage1AirInst *instruction, bool |
| 3387 | case Stage1AirInstIdExtern: | 3406 | case Stage1AirInstIdExtern: |
| 3388 | ir_print_extern(irp, (Stage1AirInstExtern *)instruction); | 3407 | ir_print_extern(irp, (Stage1AirInstExtern *)instruction); |
| 3389 | break; | 3408 | break; |
| 3409 | case Stage1AirInstIdPrefetch: | ||
| 3410 | ir_print_prefetch(irp, (Stage1AirInstPrefetch *)instruction); | ||
| 3411 | break; | ||
| 3390 | 3412 | ||
| 3391 | } | 3413 | } |
| 3392 | fprintf(irp->f, "\n"); | 3414 | fprintf(irp->f, "\n"); |
src/type.zig+19| ... | @@ -123,6 +123,7 @@ pub const Type = extern union { | ... | @@ -123,6 +123,7 @@ pub const Type = extern union { |
| 123 | .empty_struct_literal, | 123 | .empty_struct_literal, |
| 124 | .@"struct", | 124 | .@"struct", |
| 125 | .call_options, | 125 | .call_options, |
| 126 | .prefetch_options, | ||
| 126 | .export_options, | 127 | .export_options, |
| 127 | .extern_options, | 128 | .extern_options, |
| 128 | => return .Struct, | 129 | => return .Struct, |
| ... | @@ -798,6 +799,7 @@ pub const Type = extern union { | ... | @@ -798,6 +799,7 @@ pub const Type = extern union { |
| 798 | .float_mode, | 799 | .float_mode, |
| 799 | .reduce_op, | 800 | .reduce_op, |
| 800 | .call_options, | 801 | .call_options, |
| 802 | .prefetch_options, | ||
| 801 | .export_options, | 803 | .export_options, |
| 802 | .extern_options, | 804 | .extern_options, |
| 803 | .type_info, | 805 | .type_info, |
| ... | @@ -1027,6 +1029,7 @@ pub const Type = extern union { | ... | @@ -1027,6 +1029,7 @@ pub const Type = extern union { |
| 1027 | .float_mode => return writer.writeAll("std.builtin.FloatMode"), | 1029 | .float_mode => return writer.writeAll("std.builtin.FloatMode"), |
| 1028 | .reduce_op => return writer.writeAll("std.builtin.ReduceOp"), | 1030 | .reduce_op => return writer.writeAll("std.builtin.ReduceOp"), |
| 1029 | .call_options => return writer.writeAll("std.builtin.CallOptions"), | 1031 | .call_options => return writer.writeAll("std.builtin.CallOptions"), |
| 1032 | .prefetch_options => return writer.writeAll("std.builtin.PrefetchOptions"), | ||
| 1030 | .export_options => return writer.writeAll("std.builtin.ExportOptions"), | 1033 | .export_options => return writer.writeAll("std.builtin.ExportOptions"), |
| 1031 | .extern_options => return writer.writeAll("std.builtin.ExternOptions"), | 1034 | .extern_options => return writer.writeAll("std.builtin.ExternOptions"), |
| 1032 | .type_info => return writer.writeAll("std.builtin.TypeInfo"), | 1035 | .type_info => return writer.writeAll("std.builtin.TypeInfo"), |
| ... | @@ -1318,6 +1321,7 @@ pub const Type = extern union { | ... | @@ -1318,6 +1321,7 @@ pub const Type = extern union { |
| 1318 | .float_mode => return "FloatMode", | 1321 | .float_mode => return "FloatMode", |
| 1319 | .reduce_op => return "ReduceOp", | 1322 | .reduce_op => return "ReduceOp", |
| 1320 | .call_options => return "CallOptions", | 1323 | .call_options => return "CallOptions", |
| 1324 | .prefetch_options => return "PrefetchOptions", | ||
| 1321 | .export_options => return "ExportOptions", | 1325 | .export_options => return "ExportOptions", |
| 1322 | .extern_options => return "ExternOptions", | 1326 | .extern_options => return "ExternOptions", |
| 1323 | .type_info => return "TypeInfo", | 1327 | .type_info => return "TypeInfo", |
| ... | @@ -1376,6 +1380,7 @@ pub const Type = extern union { | ... | @@ -1376,6 +1380,7 @@ pub const Type = extern union { |
| 1376 | .float_mode, | 1380 | .float_mode, |
| 1377 | .reduce_op, | 1381 | .reduce_op, |
| 1378 | .call_options, | 1382 | .call_options, |
| 1383 | .prefetch_options, | ||
| 1379 | .export_options, | 1384 | .export_options, |
| 1380 | .extern_options, | 1385 | .extern_options, |
| 1381 | .manyptr_u8, | 1386 | .manyptr_u8, |
| ... | @@ -1502,6 +1507,7 @@ pub const Type = extern union { | ... | @@ -1502,6 +1507,7 @@ pub const Type = extern union { |
| 1502 | .float_mode => return Value.initTag(.float_mode_type), | 1507 | .float_mode => return Value.initTag(.float_mode_type), |
| 1503 | .reduce_op => return Value.initTag(.reduce_op_type), | 1508 | .reduce_op => return Value.initTag(.reduce_op_type), |
| 1504 | .call_options => return Value.initTag(.call_options_type), | 1509 | .call_options => return Value.initTag(.call_options_type), |
| 1510 | .prefetch_options => return Value.initTag(.prefetch_options_type), | ||
| 1505 | .export_options => return Value.initTag(.export_options_type), | 1511 | .export_options => return Value.initTag(.export_options_type), |
| 1506 | .extern_options => return Value.initTag(.extern_options_type), | 1512 | .extern_options => return Value.initTag(.extern_options_type), |
| 1507 | .type_info => return Value.initTag(.type_info_type), | 1513 | .type_info => return Value.initTag(.type_info_type), |
| ... | @@ -1563,6 +1569,7 @@ pub const Type = extern union { | ... | @@ -1563,6 +1569,7 @@ pub const Type = extern union { |
| 1563 | .float_mode, | 1569 | .float_mode, |
| 1564 | .reduce_op, | 1570 | .reduce_op, |
| 1565 | .call_options, | 1571 | .call_options, |
| 1572 | .prefetch_options, | ||
| 1566 | .export_options, | 1573 | .export_options, |
| 1567 | .extern_options, | 1574 | .extern_options, |
| 1568 | .@"anyframe", | 1575 | .@"anyframe", |
| ... | @@ -1750,6 +1757,7 @@ pub const Type = extern union { | ... | @@ -1750,6 +1757,7 @@ pub const Type = extern union { |
| 1750 | .float_mode, | 1757 | .float_mode, |
| 1751 | .reduce_op, | 1758 | .reduce_op, |
| 1752 | .call_options, | 1759 | .call_options, |
| 1760 | .prefetch_options, | ||
| 1753 | .export_options, | 1761 | .export_options, |
| 1754 | .extern_options, | 1762 | .extern_options, |
| 1755 | => return 1, | 1763 | => return 1, |
| ... | @@ -1929,6 +1937,7 @@ pub const Type = extern union { | ... | @@ -1929,6 +1937,7 @@ pub const Type = extern union { |
| 1929 | .var_args_param => unreachable, | 1937 | .var_args_param => unreachable, |
| 1930 | .generic_poison => unreachable, | 1938 | .generic_poison => unreachable, |
| 1931 | .call_options => unreachable, // missing call to resolveTypeFields | 1939 | .call_options => unreachable, // missing call to resolveTypeFields |
| 1940 | .prefetch_options => unreachable, // missing call to resolveTypeFields | ||
| 1932 | .export_options => unreachable, // missing call to resolveTypeFields | 1941 | .export_options => unreachable, // missing call to resolveTypeFields |
| 1933 | .extern_options => unreachable, // missing call to resolveTypeFields | 1942 | .extern_options => unreachable, // missing call to resolveTypeFields |
| 1934 | .type_info => unreachable, // missing call to resolveTypeFields | 1943 | .type_info => unreachable, // missing call to resolveTypeFields |
| ... | @@ -2269,6 +2278,7 @@ pub const Type = extern union { | ... | @@ -2269,6 +2278,7 @@ pub const Type = extern union { |
| 2269 | .float_mode, | 2278 | .float_mode, |
| 2270 | .reduce_op, | 2279 | .reduce_op, |
| 2271 | .call_options, | 2280 | .call_options, |
| 2281 | .prefetch_options, | ||
| 2272 | .export_options, | 2282 | .export_options, |
| 2273 | .extern_options, | 2283 | .extern_options, |
| 2274 | .type_info, | 2284 | .type_info, |
| ... | @@ -2794,6 +2804,7 @@ pub const Type = extern union { | ... | @@ -2794,6 +2804,7 @@ pub const Type = extern union { |
| 2794 | .float_mode, | 2804 | .float_mode, |
| 2795 | .reduce_op, | 2805 | .reduce_op, |
| 2796 | .call_options, | 2806 | .call_options, |
| 2807 | .prefetch_options, | ||
| 2797 | .export_options, | 2808 | .export_options, |
| 2798 | .extern_options, | 2809 | .extern_options, |
| 2799 | .type_info, | 2810 | .type_info, |
| ... | @@ -3294,6 +3305,7 @@ pub const Type = extern union { | ... | @@ -3294,6 +3305,7 @@ pub const Type = extern union { |
| 3294 | .float_mode, | 3305 | .float_mode, |
| 3295 | .reduce_op, | 3306 | .reduce_op, |
| 3296 | .call_options, | 3307 | .call_options, |
| 3308 | .prefetch_options, | ||
| 3297 | .export_options, | 3309 | .export_options, |
| 3298 | .extern_options, | 3310 | .extern_options, |
| 3299 | .type_info, | 3311 | .type_info, |
| ... | @@ -3502,6 +3514,7 @@ pub const Type = extern union { | ... | @@ -3502,6 +3514,7 @@ pub const Type = extern union { |
| 3502 | .float_mode, | 3514 | .float_mode, |
| 3503 | .reduce_op, | 3515 | .reduce_op, |
| 3504 | .call_options, | 3516 | .call_options, |
| 3517 | .prefetch_options, | ||
| 3505 | .export_options, | 3518 | .export_options, |
| 3506 | .extern_options, | 3519 | .extern_options, |
| 3507 | => @panic("TODO resolve std.builtin types"), | 3520 | => @panic("TODO resolve std.builtin types"), |
| ... | @@ -3577,6 +3590,7 @@ pub const Type = extern union { | ... | @@ -3577,6 +3590,7 @@ pub const Type = extern union { |
| 3577 | .float_mode, | 3590 | .float_mode, |
| 3578 | .reduce_op, | 3591 | .reduce_op, |
| 3579 | .call_options, | 3592 | .call_options, |
| 3593 | .prefetch_options, | ||
| 3580 | .export_options, | 3594 | .export_options, |
| 3581 | .extern_options, | 3595 | .extern_options, |
| 3582 | => @panic("TODO resolve std.builtin types"), | 3596 | => @panic("TODO resolve std.builtin types"), |
| ... | @@ -3701,6 +3715,7 @@ pub const Type = extern union { | ... | @@ -3701,6 +3715,7 @@ pub const Type = extern union { |
| 3701 | .float_mode, | 3715 | .float_mode, |
| 3702 | .reduce_op, | 3716 | .reduce_op, |
| 3703 | .call_options, | 3717 | .call_options, |
| 3718 | .prefetch_options, | ||
| 3704 | .export_options, | 3719 | .export_options, |
| 3705 | .extern_options, | 3720 | .extern_options, |
| 3706 | .type_info, | 3721 | .type_info, |
| ... | @@ -3741,6 +3756,7 @@ pub const Type = extern union { | ... | @@ -3741,6 +3756,7 @@ pub const Type = extern union { |
| 3741 | .float_mode, | 3756 | .float_mode, |
| 3742 | .reduce_op, | 3757 | .reduce_op, |
| 3743 | .call_options, | 3758 | .call_options, |
| 3759 | .prefetch_options, | ||
| 3744 | .export_options, | 3760 | .export_options, |
| 3745 | .extern_options, | 3761 | .extern_options, |
| 3746 | .type_info, | 3762 | .type_info, |
| ... | @@ -3801,6 +3817,7 @@ pub const Type = extern union { | ... | @@ -3801,6 +3817,7 @@ pub const Type = extern union { |
| 3801 | .float_mode, | 3817 | .float_mode, |
| 3802 | .reduce_op, | 3818 | .reduce_op, |
| 3803 | .call_options, | 3819 | .call_options, |
| 3820 | .prefetch_options, | ||
| 3804 | .export_options, | 3821 | .export_options, |
| 3805 | .extern_options, | 3822 | .extern_options, |
| 3806 | => @panic("TODO resolve std.builtin types"), | 3823 | => @panic("TODO resolve std.builtin types"), |
| ... | @@ -3862,6 +3879,7 @@ pub const Type = extern union { | ... | @@ -3862,6 +3879,7 @@ pub const Type = extern union { |
| 3862 | float_mode, | 3879 | float_mode, |
| 3863 | reduce_op, | 3880 | reduce_op, |
| 3864 | call_options, | 3881 | call_options, |
| 3882 | prefetch_options, | ||
| 3865 | export_options, | 3883 | export_options, |
| 3866 | extern_options, | 3884 | extern_options, |
| 3867 | type_info, | 3885 | type_info, |
| ... | @@ -3989,6 +4007,7 @@ pub const Type = extern union { | ... | @@ -3989,6 +4007,7 @@ pub const Type = extern union { |
| 3989 | .float_mode, | 4007 | .float_mode, |
| 3990 | .reduce_op, | 4008 | .reduce_op, |
| 3991 | .call_options, | 4009 | .call_options, |
| 4010 | .prefetch_options, | ||
| 3992 | .export_options, | 4011 | .export_options, |
| 3993 | .extern_options, | 4012 | .extern_options, |
| 3994 | .type_info, | 4013 | .type_info, |
src/value.zig+5| ... | @@ -67,6 +67,7 @@ pub const Value = extern union { | ... | @@ -67,6 +67,7 @@ pub const Value = extern union { |
| 67 | float_mode_type, | 67 | float_mode_type, |
| 68 | reduce_op_type, | 68 | reduce_op_type, |
| 69 | call_options_type, | 69 | call_options_type, |
| 70 | prefetch_options_type, | ||
| 70 | export_options_type, | 71 | export_options_type, |
| 71 | extern_options_type, | 72 | extern_options_type, |
| 72 | type_info_type, | 73 | type_info_type, |
| ... | @@ -244,6 +245,7 @@ pub const Value = extern union { | ... | @@ -244,6 +245,7 @@ pub const Value = extern union { |
| 244 | .float_mode_type, | 245 | .float_mode_type, |
| 245 | .reduce_op_type, | 246 | .reduce_op_type, |
| 246 | .call_options_type, | 247 | .call_options_type, |
| 248 | .prefetch_options_type, | ||
| 247 | .export_options_type, | 249 | .export_options_type, |
| 248 | .extern_options_type, | 250 | .extern_options_type, |
| 249 | .type_info_type, | 251 | .type_info_type, |
| ... | @@ -434,6 +436,7 @@ pub const Value = extern union { | ... | @@ -434,6 +436,7 @@ pub const Value = extern union { |
| 434 | .float_mode_type, | 436 | .float_mode_type, |
| 435 | .reduce_op_type, | 437 | .reduce_op_type, |
| 436 | .call_options_type, | 438 | .call_options_type, |
| 439 | .prefetch_options_type, | ||
| 437 | .export_options_type, | 440 | .export_options_type, |
| 438 | .extern_options_type, | 441 | .extern_options_type, |
| 439 | .type_info_type, | 442 | .type_info_type, |
| ... | @@ -652,6 +655,7 @@ pub const Value = extern union { | ... | @@ -652,6 +655,7 @@ pub const Value = extern union { |
| 652 | .float_mode_type => return out_stream.writeAll("std.builtin.FloatMode"), | 655 | .float_mode_type => return out_stream.writeAll("std.builtin.FloatMode"), |
| 653 | .reduce_op_type => return out_stream.writeAll("std.builtin.ReduceOp"), | 656 | .reduce_op_type => return out_stream.writeAll("std.builtin.ReduceOp"), |
| 654 | .call_options_type => return out_stream.writeAll("std.builtin.CallOptions"), | 657 | .call_options_type => return out_stream.writeAll("std.builtin.CallOptions"), |
| 658 | .prefetch_options_type => return out_stream.writeAll("std.builtin.PrefetchOptions"), | ||
| 655 | .export_options_type => return out_stream.writeAll("std.builtin.ExportOptions"), | 659 | .export_options_type => return out_stream.writeAll("std.builtin.ExportOptions"), |
| 656 | .extern_options_type => return out_stream.writeAll("std.builtin.ExternOptions"), | 660 | .extern_options_type => return out_stream.writeAll("std.builtin.ExternOptions"), |
| 657 | .type_info_type => return out_stream.writeAll("std.builtin.TypeInfo"), | 661 | .type_info_type => return out_stream.writeAll("std.builtin.TypeInfo"), |
| ... | @@ -829,6 +833,7 @@ pub const Value = extern union { | ... | @@ -829,6 +833,7 @@ pub const Value = extern union { |
| 829 | .float_mode_type => Type.initTag(.float_mode), | 833 | .float_mode_type => Type.initTag(.float_mode), |
| 830 | .reduce_op_type => Type.initTag(.reduce_op), | 834 | .reduce_op_type => Type.initTag(.reduce_op), |
| 831 | .call_options_type => Type.initTag(.call_options), | 835 | .call_options_type => Type.initTag(.call_options), |
| 836 | .prefetch_options_type => Type.initTag(.prefetch_options), | ||
| 832 | .export_options_type => Type.initTag(.export_options), | 837 | .export_options_type => Type.initTag(.export_options), |
| 833 | .extern_options_type => Type.initTag(.extern_options), | 838 | .extern_options_type => Type.initTag(.extern_options), |
| 834 | .type_info_type => Type.initTag(.type_info), | 839 | .type_info_type => Type.initTag(.type_info), |
test/behavior.zig+1| ... | @@ -169,6 +169,7 @@ test { | ... | @@ -169,6 +169,7 @@ test { |
| 169 | _ = @import("behavior/optional_stage1.zig"); | 169 | _ = @import("behavior/optional_stage1.zig"); |
| 170 | _ = @import("behavior/pointers_stage1.zig"); | 170 | _ = @import("behavior/pointers_stage1.zig"); |
| 171 | _ = @import("behavior/popcount_stage1.zig"); | 171 | _ = @import("behavior/popcount_stage1.zig"); |
| 172 | _ = @import("behavior/prefetch.zig"); | ||
| 172 | _ = @import("behavior/ptrcast_stage1.zig"); | 173 | _ = @import("behavior/ptrcast_stage1.zig"); |
| 173 | _ = @import("behavior/reflection.zig"); | 174 | _ = @import("behavior/reflection.zig"); |
| 174 | _ = @import("behavior/saturating_arithmetic_stage1.zig"); | 175 | _ = @import("behavior/saturating_arithmetic_stage1.zig"); |
test/behavior/prefetch.zig created+27| ... | @@ -0,0 +1,27 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | test "@prefetch()" { | ||
| 4 | var a: u32 = 42; | ||
| 5 | |||
| 6 | @prefetch(&a, .{}); | ||
| 7 | |||
| 8 | @prefetch(&a, .{ .rw = .read, .locality = 3, .cache = .data }); | ||
| 9 | @prefetch(&a, .{ .rw = .read, .locality = 2, .cache = .data }); | ||
| 10 | @prefetch(&a, .{ .rw = .read, .locality = 1, .cache = .data }); | ||
| 11 | @prefetch(&a, .{ .rw = .read, .locality = 0, .cache = .data }); | ||
| 12 | |||
| 13 | @prefetch(&a, .{ .rw = .write, .locality = 3, .cache = .data }); | ||
| 14 | @prefetch(&a, .{ .rw = .write, .locality = 2, .cache = .data }); | ||
| 15 | @prefetch(&a, .{ .rw = .write, .locality = 1, .cache = .data }); | ||
| 16 | @prefetch(&a, .{ .rw = .write, .locality = 0, .cache = .data }); | ||
| 17 | |||
| 18 | @prefetch(&a, .{ .rw = .read, .locality = 3, .cache = .instruction }); | ||
| 19 | @prefetch(&a, .{ .rw = .read, .locality = 2, .cache = .instruction }); | ||
| 20 | @prefetch(&a, .{ .rw = .read, .locality = 1, .cache = .instruction }); | ||
| 21 | @prefetch(&a, .{ .rw = .read, .locality = 0, .cache = .instruction }); | ||
| 22 | |||
| 23 | @prefetch(&a, .{ .rw = .write, .locality = 3, .cache = .instruction }); | ||
| 24 | @prefetch(&a, .{ .rw = .write, .locality = 2, .cache = .instruction }); | ||
| 25 | @prefetch(&a, .{ .rw = .write, .locality = 1, .cache = .instruction }); | ||
| 26 | @prefetch(&a, .{ .rw = .write, .locality = 0, .cache = .instruction }); | ||
| 27 | } | ||