diff --git a/CMakeLists.txt b/CMakeLists.txt index 47a0cdf578..2695412028 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -608,25 +608,25 @@ else() set(LIBUSERLAND_RELEASE_MODE "true") endif() -set(BUILD_LIBUSERLAND_COMMAND zig0 build - --override-lib-dir "${CMAKE_SOURCE_DIR}/lib" - "-Doutput-dir=${CMAKE_BINARY_DIR}" - "-Drelease=${LIBUSERLAND_RELEASE_MODE}" - "-Dlib-files-only" - --prefix "${CMAKE_INSTALL_PREFIX}" - libuserland +set(BUILD_LIBUSERLAND_ARGS "build" + --override-lib-dir "${CMAKE_SOURCE_DIR}/lib" + "-Doutput-dir=${CMAKE_BINARY_DIR}" + "-Drelease=${LIBUSERLAND_RELEASE_MODE}" + "-Dlib-files-only" + --prefix "${CMAKE_INSTALL_PREFIX}" + libuserland ) # When using Visual Studio build system generator we default to libuserland install. if(MSVC) set(ZIG_SKIP_INSTALL_LIB_FILES off CACHE BOOL "Disable copying lib/ files to install prefix") if(NOT ZIG_SKIP_INSTALL_LIB_FILES) - set(BUILD_LIBUSERLAND_COMMAND ${BUILD_LIBUSERLAND_COMMAND} install) + set(BUILD_LIBUSERLAND_ARGS ${BUILD_LIBUSERLAND_ARGS} install) endif() endif() add_custom_target(zig_build_libuserland ALL - COMMAND ${BUILD_LIBUSERLAND_COMMAND} + COMMAND zig0 ${BUILD_LIBUSERLAND_ARGS} DEPENDS zig0 BYPRODUCTS "${LIBUSERLAND}" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" @@ -647,6 +647,12 @@ add_dependencies(zig zig_build_libuserland) install(TARGETS zig DESTINATION bin) -# CODE has no effect with Visual Studio build system generator -install(CODE "message(\"-- Installing: /opt/zig/lib\")") -install(CODE "execute_process(COMMAND ${BUILD_LIBUSERLAND_COMMAND} install)") +# CODE has no effect with Visual Studio build system generator. +if(NOT MSVC) + get_target_property(zig0_BINARY_DIR zig0 BINARY_DIR) + install(CODE "set(zig0_EXE \"${zig0_BINARY_DIR}/zig0\")") + install(CODE "set(INSTALL_LIBUSERLAND_ARGS \"${BUILD_LIBUSERLAND_ARGS}\" install)") + install(CODE "set(BUILD_LIBUSERLAND_ARGS \"${BUILD_LIBUSERLAND_ARGS}\")") + install(CODE "set(CMAKE_SOURCE_DIR \"${CMAKE_SOURCE_DIR}\")") + install(SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/cmake/install.cmake) +endif() diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a5aeeb9e21..62b8083222 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -51,23 +51,28 @@ knowledge of Zig internals.** ### Editing Source Code -First, build the Stage 1 compiler as described in [the Building section](#building). +First, build the Stage 1 compiler as described in [Building from Source](README.md#Building-from-Source). -One modification you may want to make is adding `-DZIG_SKIP_INSTALL_LIB_FILES=ON` -to the cmake line. If you use the build directory as a working directory to run -tests with, zig will find the lib files in the source directory, and they will not -be "installed" every time you run `make`. This will allow you to make modifications -directly to the standard library, for example, and have them effective immediately. -Note that if you already ran `make` or `make install` with the default cmake -settings, there will already be a `lib/` directory in your build directory. When -executed from the build directory, zig will find this instead of the source lib/ -directory. Remove the unwanted directory so that the desired one can be found. +Zig locates lib files relative to executable path by searching up the +filesystem tree for a sub-path of `lib/zig/std/std.zig` or `lib/std/std.zig`. +Typically the former is an install and the latter a git working tree which +contains the build directory. + +During development it is not necessary to perform installs when modifying +stage1 or userland sources and in fact it is faster and simpler to run, +test and debug from a git working tree. + +- `make` is typically sufficient to build zig during development iterations. +- `make install` performs a build __and__ install. +- `msbuild -p:Configuration=Release INSTALL.vcxproj` on Windows performs a +build and install. To avoid install, pass cmake option `-DZIG_SKIP_INSTALL_LIB_FILES=ON`. To test changes, do the following from the build directory: -1. Run `make install` (on POSIX) or +1. Run `make` (on POSIX) or `msbuild -p:Configuration=Release INSTALL.vcxproj` (on Windows). -2. `bin/zig build test` (on POSIX) or `bin\zig.exe build test` (on Windows). +2. `$BUILD_DIR/zig build test` (on POSIX) or + `$BUILD_DIR/Release\zig.exe build test` (on Windows). That runs the whole test suite, which does a lot of extra testing that you likely won't always need, and can take upwards of 1 hour. This is what the @@ -85,8 +90,8 @@ Another example is choosing a different set of things to test. For example, not the other ones. Combining this suggestion with the previous one, you could do this: -`bin/zig build test-std -Dskip-release` (on POSIX) or -`bin\zig.exe build test-std -Dskip-release` (on Windows). +`$BUILD_DIR/bin/zig build test-std -Dskip-release` (on POSIX) or +`$BUILD_DIR/Release\zig.exe build test-std -Dskip-release` (on Windows). This will run only the standard library tests, in debug mode only, for all targets (it will cross-compile the tests for non-native targets but not run diff --git a/cmake/install.cmake b/cmake/install.cmake new file mode 100644 index 0000000000..415a088d6a --- /dev/null +++ b/cmake/install.cmake @@ -0,0 +1,37 @@ +message("-- Installing: ${CMAKE_INSTALL_PREFIX}/lib") + +if(NOT EXISTS ${zig0_EXE}) + message("::") + message(":: ERROR: Executable not found") + message(":: (execute_process)") + message("::") + message(":: executable: ${zig0_EXE}") + message("::") + message(FATAL_ERROR) +endif() + +execute_process(COMMAND ${zig0_EXE} ${INSTALL_LIBUSERLAND_ARGS} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE _result +) +if(_result) + message("::") + message(":: ERROR: ${_result}") + message(":: (execute_process)") + + string(REPLACE ";" " " s_INSTALL_LIBUSERLAND_ARGS "${INSTALL_LIBUSERLAND_ARGS}") + message("::") + message(":: argv: ${zig0_EXE} ${s_INSTALL_LIBUSERLAND_ARGS} install") + + set(_args ${zig0_EXE} ${INSTALL_LIBUSERLAND_ARGS}) + list(LENGTH _args _len) + math(EXPR _len "${_len} - 1") + message("::") + foreach(_i RANGE 0 ${_len}) + list(GET _args ${_i} _arg) + message(":: argv[${_i}]: ${_arg}") + endforeach() + + message("::") + message(FATAL_ERROR) +endif() diff --git a/doc/langref.html.in b/doc/langref.html.in index 88e6b41983..5231cc9f9d 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2893,6 +2893,47 @@ test "switch using enum literals" { } {#code_end#} {#header_close#} + + {#header_open|Non-exhaustive enum#} +

+ A Non-exhaustive enum can be created by adding a trailing '_' field. + It must specify a tag type and cannot consume every enumeration value. +

+

+ {#link|@intToEnum#} on a non-exhaustive enum cannot fail. +

+

+ A switch on a non-exhaustive enum can include a '_' prong as an alternative to an {#syntax#}else{#endsyntax#} prong + with the difference being that it makes it a compile error if all the known tag names are not handled by the switch. +

+ {#code_begin|test#} +const std = @import("std"); +const assert = std.debug.assert; + +const Number = enum(u8) { + One, + Two, + Three, + _, +}; + +test "switch on non-exhaustive enum" { + const number = Number.One; + const result = switch (number) { + .One => true, + .Two, + .Three => false, + _ => false, + }; + assert(result); + const is_one = switch (number) { + .One => true, + else => false, + }; + assert(is_one); +} + {#code_end#} + {#header_close#} {#header_close#} {#header_open|union#} diff --git a/lib/std/buffer.zig b/lib/std/buffer.zig index 6313d693b7..42bf8e8142 100644 --- a/lib/std/buffer.zig +++ b/lib/std/buffer.zig @@ -57,11 +57,11 @@ pub const Buffer = struct { /// The caller owns the returned memory. The Buffer becomes null and /// is safe to `deinit`. - pub fn toOwnedSlice(self: *Buffer) []u8 { + pub fn toOwnedSlice(self: *Buffer) [:0]u8 { const allocator = self.list.allocator; - const result = allocator.shrink(self.list.items, self.len()); + const result = self.list.toOwnedSlice(); self.* = initNull(allocator); - return result; + return result[0 .. result.len - 1 :0]; } pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: var) !Buffer { diff --git a/lib/std/build.zig b/lib/std/build.zig index ad4be9e4ca..560f82961c 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -484,6 +484,7 @@ pub const Builder = struct { .arch = builtin.arch, .os = builtin.os, .abi = builtin.abi, + .cpu_features = builtin.cpu_features, }, }).linuxTriple(self.allocator); @@ -1375,6 +1376,7 @@ pub const LibExeObjStep = struct { .arch = target_arch, .os = target_os, .abi = target_abi, + .cpu_features = target_arch.getBaselineCpuFeatures(), }, }); } @@ -1687,7 +1689,9 @@ pub const LibExeObjStep = struct { } pub fn addAssemblyFile(self: *LibExeObjStep, path: []const u8) void { - self.link_objects.append(LinkObject{ .AssemblyFile = self.builder.dupe(path) }) catch unreachable; + self.link_objects.append(LinkObject{ + .AssemblyFile = .{ .path = self.builder.dupe(path) }, + }) catch unreachable; } pub fn addAssemblyFileFromWriteFileStep(self: *LibExeObjStep, wfs: *WriteFileStep, basename: []const u8) void { @@ -1968,9 +1972,46 @@ pub const LibExeObjStep = struct { switch (self.target) { .Native => {}, - .Cross => { + .Cross => |cross| { try zig_args.append("-target"); try zig_args.append(self.target.zigTriple(builder.allocator) catch unreachable); + + const all_features = self.target.getArch().allFeaturesList(); + var populated_cpu_features = cross.cpu_features.cpu.features; + populated_cpu_features.populateDependencies(all_features); + + if (populated_cpu_features.eql(cross.cpu_features.features)) { + // The CPU name alone is sufficient. + // If it is the baseline CPU, no command line args are required. + if (cross.cpu_features.cpu != self.target.getArch().getBaselineCpuFeatures().cpu) { + try zig_args.append("-target-cpu"); + try zig_args.append(cross.cpu_features.cpu.name); + } + } else { + try zig_args.append("-target-cpu"); + try zig_args.append(cross.cpu_features.cpu.name); + + try zig_args.append("-target-feature"); + var feature_str_buffer = try std.Buffer.initSize(builder.allocator, 0); + for (all_features) |feature, i_usize| { + const i = @intCast(Target.Cpu.Feature.Set.Index, i_usize); + const in_cpu_set = populated_cpu_features.isEnabled(i); + const in_actual_set = cross.cpu_features.features.isEnabled(i); + if (in_cpu_set and !in_actual_set) { + try feature_str_buffer.appendByte('-'); + try feature_str_buffer.append(feature.name); + try feature_str_buffer.appendByte(','); + } else if (!in_cpu_set and in_actual_set) { + try feature_str_buffer.appendByte('+'); + try feature_str_buffer.append(feature.name); + try feature_str_buffer.appendByte(','); + } + } + if (mem.endsWith(u8, feature_str_buffer.toSliceConst(), ",")) { + feature_str_buffer.shrink(feature_str_buffer.len() - 1); + } + try zig_args.append(feature_str_buffer.toSliceConst()); + } }, } diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 65604a5b20..17918f3f73 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -1,5 +1,8 @@ pub usingnamespace @import("builtin"); +/// Deprecated: use `std.Target.Os`. +pub const Target = std.Target; + /// Deprecated: use `std.Target.Os`. pub const Os = std.Target.Os; @@ -15,6 +18,12 @@ pub const ObjectFormat = std.Target.ObjectFormat; /// Deprecated: use `std.Target.SubSystem`. pub const SubSystem = std.Target.SubSystem; +/// Deprecated: use `std.Target.CpuFeatures`. +pub const CpuFeatures = std.Target.CpuFeatures; + +/// Deprecated: use `std.Target.Cpu`. +pub const Cpu = std.Target.Cpu; + /// `explicit_subsystem` is missing when the subsystem is automatically detected, /// so Zig standard library has the subsystem detection logic here. This should generally be /// used rather than `explicit_subsystem`. @@ -254,6 +263,7 @@ pub const TypeInfo = union(enum) { tag_type: type, fields: []EnumField, decls: []Declaration, + is_exhaustive: bool, }; /// This data structure is used by the Zig language code generation and diff --git a/lib/std/c.zig b/lib/std/c.zig index 45d0b4db03..c912c72418 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -185,7 +185,7 @@ pub extern "c" fn getaddrinfo( noalias service: [*:0]const u8, noalias hints: *const addrinfo, noalias res: **addrinfo, -) c_int; +) EAI; pub extern "c" fn freeaddrinfo(res: *addrinfo) void; @@ -197,9 +197,9 @@ pub extern "c" fn getnameinfo( noalias serv: [*]u8, servlen: socklen_t, flags: u32, -) c_int; +) EAI; -pub extern "c" fn gai_strerror(errcode: c_int) [*:0]const u8; +pub extern "c" fn gai_strerror(errcode: EAI) [*:0]const u8; pub extern "c" fn poll(fds: [*]pollfd, nfds: nfds_t, timeout: c_int) c_int; diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig index bcb5a38ba3..524c82211e 100644 --- a/lib/std/c/darwin.zig +++ b/lib/std/c/darwin.zig @@ -7,7 +7,10 @@ usingnamespace @import("../os/bits.zig"); extern "c" fn __error() *c_int; pub extern "c" fn _NSGetExecutablePath(buf: [*]u8, bufsize: *u32) c_int; +pub extern "c" fn _dyld_image_count() u32; pub extern "c" fn _dyld_get_image_header(image_index: u32) ?*mach_header; +pub extern "c" fn _dyld_get_image_vmaddr_slide(image_index: u32) usize; +pub extern "c" fn _dyld_get_image_name(image_index: u32) [*:0]const u8; pub extern "c" fn __getdirentries64(fd: c_int, buf_ptr: [*]u8, buf_len: usize, basep: *i64) isize; @@ -70,47 +73,52 @@ pub const AI_NUMERICHOST = 0x00000004; /// prevent service name resolution pub const AI_NUMERICSERV = 0x00001000; -/// address family for hostname not supported -pub const EAI_ADDRFAMILY = 1; +pub const EAI = extern enum(c_int) { + /// address family for hostname not supported + ADDRFAMILY = 1, -/// temporary failure in name resolution -pub const EAI_AGAIN = 2; + /// temporary failure in name resolution + AGAIN = 2, -/// invalid value for ai_flags -pub const EAI_BADFLAGS = 3; + /// invalid value for ai_flags + BADFLAGS = 3, -/// non-recoverable failure in name resolution -pub const EAI_FAIL = 4; + /// non-recoverable failure in name resolution + FAIL = 4, -/// ai_family not supported -pub const EAI_FAMILY = 5; + /// ai_family not supported + FAMILY = 5, -/// memory allocation failure -pub const EAI_MEMORY = 6; + /// memory allocation failure + MEMORY = 6, -/// no address associated with hostname -pub const EAI_NODATA = 7; + /// no address associated with hostname + NODATA = 7, -/// hostname nor servname provided, or not known -pub const EAI_NONAME = 8; + /// hostname nor servname provided, or not known + NONAME = 8, -/// servname not supported for ai_socktype -pub const EAI_SERVICE = 9; + /// servname not supported for ai_socktype + SERVICE = 9, -/// ai_socktype not supported -pub const EAI_SOCKTYPE = 10; + /// ai_socktype not supported + SOCKTYPE = 10, -/// system error returned in errno -pub const EAI_SYSTEM = 11; + /// system error returned in errno + SYSTEM = 11, -/// invalid value for hints -pub const EAI_BADHINTS = 12; + /// invalid value for hints + BADHINTS = 12, -/// resolved protocol is unknown -pub const EAI_PROTOCOL = 13; + /// resolved protocol is unknown + PROTOCOL = 13, + + /// argument buffer overflow + OVERFLOW = 14, + + _, +}; -/// argument buffer overflow -pub const EAI_OVERFLOW = 14; pub const EAI_MAX = 15; pub const pthread_mutex_t = extern struct { diff --git a/lib/std/c/freebsd.zig b/lib/std/c/freebsd.zig index 95e27a7d92..4c6614c978 100644 --- a/lib/std/c/freebsd.zig +++ b/lib/std/c/freebsd.zig @@ -23,47 +23,51 @@ pub const pthread_attr_t = extern struct { __align: c_long, }; -/// address family for hostname not supported -pub const EAI_ADDRFAMILY = 1; +pub const EAI = extern enum(c_int) { + /// address family for hostname not supported + ADDRFAMILY = 1, -/// name could not be resolved at this time -pub const EAI_AGAIN = 2; + /// name could not be resolved at this time + AGAIN = 2, -/// flags parameter had an invalid value -pub const EAI_BADFLAGS = 3; + /// flags parameter had an invalid value + BADFLAGS = 3, -/// non-recoverable failure in name resolution -pub const EAI_FAIL = 4; + /// non-recoverable failure in name resolution + FAIL = 4, -/// address family not recognized -pub const EAI_FAMILY = 5; + /// address family not recognized + FAMILY = 5, -/// memory allocation failure -pub const EAI_MEMORY = 6; + /// memory allocation failure + MEMORY = 6, -/// no address associated with hostname -pub const EAI_NODATA = 7; + /// no address associated with hostname + NODATA = 7, -/// name does not resolve -pub const EAI_NONAME = 8; + /// name does not resolve + NONAME = 8, -/// service not recognized for socket type -pub const EAI_SERVICE = 9; + /// service not recognized for socket type + SERVICE = 9, -/// intended socket type was not recognized -pub const EAI_SOCKTYPE = 10; + /// intended socket type was not recognized + SOCKTYPE = 10, -/// system error returned in errno -pub const EAI_SYSTEM = 11; + /// system error returned in errno + SYSTEM = 11, -/// invalid value for hints -pub const EAI_BADHINTS = 12; + /// invalid value for hints + BADHINTS = 12, -/// resolved protocol is unknown -pub const EAI_PROTOCOL = 13; + /// resolved protocol is unknown + PROTOCOL = 13, -/// argument buffer overflow -pub const EAI_OVERFLOW = 14; + /// argument buffer overflow + OVERFLOW = 14, + + _, +}; pub const EAI_MAX = 15; diff --git a/lib/std/c/linux.zig b/lib/std/c/linux.zig index 9969474097..0f7abaaaa0 100644 --- a/lib/std/c/linux.zig +++ b/lib/std/c/linux.zig @@ -32,25 +32,29 @@ pub const NI_NAMEREQD = 0x08; pub const NI_DGRAM = 0x10; pub const NI_NUMERICSCOPE = 0x100; -pub const EAI_BADFLAGS = -1; -pub const EAI_NONAME = -2; -pub const EAI_AGAIN = -3; -pub const EAI_FAIL = -4; -pub const EAI_FAMILY = -6; -pub const EAI_SOCKTYPE = -7; -pub const EAI_SERVICE = -8; -pub const EAI_MEMORY = -10; -pub const EAI_SYSTEM = -11; -pub const EAI_OVERFLOW = -12; +pub const EAI = extern enum(c_int) { + BADFLAGS = -1, + NONAME = -2, + AGAIN = -3, + FAIL = -4, + FAMILY = -6, + SOCKTYPE = -7, + SERVICE = -8, + MEMORY = -10, + SYSTEM = -11, + OVERFLOW = -12, -pub const EAI_NODATA = -5; -pub const EAI_ADDRFAMILY = -9; -pub const EAI_INPROGRESS = -100; -pub const EAI_CANCELED = -101; -pub const EAI_NOTCANCELED = -102; -pub const EAI_ALLDONE = -103; -pub const EAI_INTR = -104; -pub const EAI_IDN_ENCODE = -105; + NODATA = -5, + ADDRFAMILY = -9, + INPROGRESS = -100, + CANCELED = -101, + NOTCANCELED = -102, + ALLDONE = -103, + INTR = -104, + IDN_ENCODE = -105, + + _, +}; pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize; pub extern "c" fn sched_getaffinity(pid: c_int, size: usize, set: *cpu_set_t) c_int; diff --git a/lib/std/debug.zig b/lib/std/debug.zig index dfdaca6d3f..d035707a54 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -81,10 +81,20 @@ pub fn getSelfDebugInfo() !*DebugInfo { } } -fn wantTtyColor() bool { +pub fn detectTTYConfig() TTY.Config { var bytes: [128]u8 = undefined; const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator; - return if (process.getEnvVarOwned(allocator, "ZIG_DEBUG_COLOR")) |_| true else |_| stderr_file.isTty(); + if (process.getEnvVarOwned(allocator, "ZIG_DEBUG_COLOR")) |_| { + return .escape_codes; + } else |_| { + if (stderr_file.supportsAnsiEscapeCodes()) { + return .escape_codes; + } else if (builtin.os == .windows and stderr_file.isTty()) { + return .windows_api; + } else { + return .no_color; + } + } } /// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned. @@ -99,7 +109,7 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void { stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return; return; }; - writeCurrentStackTrace(stderr, debug_info, wantTtyColor(), start_addr) catch |err| { + writeCurrentStackTrace(stderr, debug_info, detectTTYConfig(), start_addr) catch |err| { stderr.print("Unable to dump stack trace: {}\n", .{@errorName(err)}) catch return; return; }; @@ -118,16 +128,16 @@ pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void { stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return; return; }; - const tty_color = wantTtyColor(); - printSourceAtAddress(debug_info, stderr, ip, tty_color) catch return; + const tty_config = detectTTYConfig(); + printSourceAtAddress(debug_info, stderr, ip, tty_config) catch return; const first_return_address = @intToPtr(*const usize, bp + @sizeOf(usize)).*; - printSourceAtAddress(debug_info, stderr, first_return_address - 1, tty_color) catch return; + printSourceAtAddress(debug_info, stderr, first_return_address - 1, tty_config) catch return; var it = StackIterator{ .first_addr = null, .fp = bp, }; while (it.next()) |return_address| { - printSourceAtAddress(debug_info, stderr, return_address - 1, tty_color) catch return; + printSourceAtAddress(debug_info, stderr, return_address - 1, tty_config) catch return; } } @@ -191,7 +201,7 @@ pub fn dumpStackTrace(stack_trace: builtin.StackTrace) void { stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return; return; }; - writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, wantTtyColor()) catch |err| { + writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, detectTTYConfig()) catch |err| { stderr.print("Unable to dump stack trace: {}\n", .{@errorName(err)}) catch return; return; }; @@ -264,7 +274,7 @@ pub fn writeStackTrace( out_stream: var, allocator: *mem.Allocator, debug_info: *DebugInfo, - tty_color: bool, + tty_config: TTY.Config, ) !void { if (builtin.strip_debug_info) return error.MissingDebugInfo; var frame_index: usize = 0; @@ -275,7 +285,7 @@ pub fn writeStackTrace( frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len; }) { const return_address = stack_trace.instruction_addresses[frame_index]; - try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_color); + try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_config); } } @@ -319,20 +329,25 @@ pub const StackIterator = struct { } }; -pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void { +pub fn writeCurrentStackTrace( + out_stream: var, + debug_info: *DebugInfo, + tty_config: TTY.Config, + start_addr: ?usize, +) !void { if (builtin.os == .windows) { - return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr); + return writeCurrentStackTraceWindows(out_stream, debug_info, tty_config, start_addr); } var it = StackIterator.init(start_addr); while (it.next()) |return_address| { - try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_color); + try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_config); } } pub fn writeCurrentStackTraceWindows( out_stream: var, debug_info: *DebugInfo, - tty_color: bool, + tty_config: TTY.Config, start_addr: ?usize, ) !void { var addr_buf: [1024]usize = undefined; @@ -345,23 +360,28 @@ pub fn writeCurrentStackTraceWindows( return; } else 0; for (addrs[start_i..]) |addr| { - try printSourceAtAddress(debug_info, out_stream, addr, tty_color); + try printSourceAtAddress(debug_info, out_stream, addr - 1, tty_config); } } /// TODO once https://github.com/ziglang/zig/issues/3157 is fully implemented, /// make this `noasync fn` and remove the individual noasync calls. -pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void { +pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void { if (builtin.os == .windows) { - return noasync printSourceAtAddressWindows(debug_info, out_stream, address, tty_color); + return noasync printSourceAtAddressWindows(debug_info, out_stream, address, tty_config); } if (comptime std.Target.current.isDarwin()) { - return noasync printSourceAtAddressMacOs(debug_info, out_stream, address, tty_color); + return noasync printSourceAtAddressMacOs(debug_info, out_stream, address, tty_config); } - return noasync printSourceAtAddressPosix(debug_info, out_stream, address, tty_color); + return noasync printSourceAtAddressPosix(debug_info, out_stream, address, tty_config); } -fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_address: usize, tty_color: bool) !void { +fn printSourceAtAddressWindows( + di: *DebugInfo, + out_stream: var, + relocated_address: usize, + tty_config: TTY.Config, +) !void { const allocator = getDebugInfoAllocator(); const base_address = process.getBaseAddress(); const relative_address = relocated_address - base_address; @@ -379,16 +399,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres } } else { // we have no information to add to the address - if (tty_color) { - try out_stream.print("???:?:?: ", .{}); - setTtyColor(TtyColor.Dim); - try out_stream.print("0x{x} in ??? (???)", .{relocated_address}); - setTtyColor(TtyColor.Reset); - try out_stream.print("\n\n\n", .{}); - } else { - try out_stream.print("???:?:?: 0x{x} in ??? (???)\n\n\n", .{relocated_address}); - } - return; + return printLineInfo(out_stream, null, relocated_address, "???", "???", tty_config, printLineFromFileAnyOs); }; const mod = &di.modules[mod_index]; @@ -401,7 +412,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres if (prefix.RecordLen < 2) return error.InvalidDebugInfo; switch (prefix.RecordKind) { - pdb.SymbolKind.S_LPROC32 => { + .S_LPROC32, .S_GPROC32 => { const proc_sym = @ptrCast(*pdb.ProcSym, &mod.symbols[symbol_i + @sizeOf(pdb.RecordPrefix)]); const vaddr_start = coff_section.header.virtual_address + proc_sym.CodeOffset; const vaddr_end = vaddr_start + proc_sym.CodeSize; @@ -510,138 +521,87 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres } }; - if (tty_color) { - setTtyColor(TtyColor.White); - if (opt_line_info) |li| { - try out_stream.print("{}:{}:{}", .{ li.file_name, li.line, li.column }); - } else { - try out_stream.print("???:?:?", .{}); - } - setTtyColor(TtyColor.Reset); - try out_stream.print(": ", .{}); - setTtyColor(TtyColor.Dim); - try out_stream.print("0x{x} in {} ({})", .{ relocated_address, symbol_name, obj_basename }); - setTtyColor(TtyColor.Reset); + try printLineInfo( + out_stream, + opt_line_info, + relocated_address, + symbol_name, + obj_basename, + tty_config, + printLineFromFileAnyOs, + ); +} - if (opt_line_info) |line_info| { - try out_stream.print("\n", .{}); - if (printLineFromFileAnyOs(out_stream, line_info)) { - if (line_info.column == 0) { - try out_stream.write("\n"); - } else { - { - var col_i: usize = 1; - while (col_i < line_info.column) : (col_i += 1) { - try out_stream.writeByte(' '); - } - } - setTtyColor(TtyColor.Green); - try out_stream.write("^"); - setTtyColor(TtyColor.Reset); - try out_stream.write("\n"); - } - } else |err| switch (err) { - error.EndOfFile => {}, - error.FileNotFound => { - setTtyColor(TtyColor.Dim); - try out_stream.write("file not found\n\n"); - setTtyColor(TtyColor.White); +pub const TTY = struct { + pub const Color = enum { + Red, + Green, + Cyan, + White, + Dim, + Bold, + Reset, + }; + + pub const Config = enum { + no_color, + escape_codes, + // TODO give this a payload of file handle + windows_api, + + fn setColor(conf: Config, out_stream: var, color: Color) void { + switch (conf) { + .no_color => return, + .escape_codes => switch (color) { + .Red => out_stream.write(RED) catch return, + .Green => out_stream.write(GREEN) catch return, + .Cyan => out_stream.write(CYAN) catch return, + .White, .Bold => out_stream.write(WHITE) catch return, + .Dim => out_stream.write(DIM) catch return, + .Reset => out_stream.write(RESET) catch return, + }, + .windows_api => if (builtin.os == .windows) { + const S = struct { + var attrs: windows.WORD = undefined; + var init_attrs = false; + }; + if (!S.init_attrs) { + S.init_attrs = true; + var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; + // TODO handle error + _ = windows.kernel32.GetConsoleScreenBufferInfo(stderr_file.handle, &info); + S.attrs = info.wAttributes; + } + + // TODO handle errors + switch (color) { + .Red => { + _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_INTENSITY) catch {}; + }, + .Green => { + _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY) catch {}; + }, + .Cyan => { + _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {}; + }, + .White, .Bold => { + _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {}; + }, + .Dim => { + _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_INTENSITY) catch {}; + }, + .Reset => { + _ = windows.SetConsoleTextAttribute(stderr_file.handle, S.attrs) catch {}; + }, + } + } else { + unreachable; }, - else => return err, } - } else { - try out_stream.print("\n\n\n", .{}); } - } else { - if (opt_line_info) |li| { - try out_stream.print("{}:{}:{}: 0x{x} in {} ({})\n\n\n", .{ - li.file_name, - li.line, - li.column, - relocated_address, - symbol_name, - obj_basename, - }); - } else { - try out_stream.print("???:?:?: 0x{x} in {} ({})\n\n\n", .{ - relocated_address, - symbol_name, - obj_basename, - }); - } - } -} - -const TtyColor = enum { - Red, - Green, - Cyan, - White, - Dim, - Bold, - Reset, + }; }; -/// TODO this is a special case hack right now. clean it up and maybe make it part of std.fmt -fn setTtyColor(tty_color: TtyColor) void { - if (stderr_file.supportsAnsiEscapeCodes()) { - switch (tty_color) { - TtyColor.Red => { - stderr_file.write(RED) catch return; - }, - TtyColor.Green => { - stderr_file.write(GREEN) catch return; - }, - TtyColor.Cyan => { - stderr_file.write(CYAN) catch return; - }, - TtyColor.White, TtyColor.Bold => { - stderr_file.write(WHITE) catch return; - }, - TtyColor.Dim => { - stderr_file.write(DIM) catch return; - }, - TtyColor.Reset => { - stderr_file.write(RESET) catch return; - }, - } - } else { - const S = struct { - var attrs: windows.WORD = undefined; - var init_attrs = false; - }; - if (!S.init_attrs) { - S.init_attrs = true; - var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; - // TODO handle error - _ = windows.kernel32.GetConsoleScreenBufferInfo(stderr_file.handle, &info); - S.attrs = info.wAttributes; - } - - // TODO handle errors - switch (tty_color) { - TtyColor.Red => { - _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_INTENSITY) catch {}; - }, - TtyColor.Green => { - _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY) catch {}; - }, - TtyColor.Cyan => { - _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {}; - }, - TtyColor.White, TtyColor.Bold => { - _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {}; - }, - TtyColor.Dim => { - _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_INTENSITY) catch {}; - }, - TtyColor.Reset => { - _ = windows.SetConsoleTextAttribute(stderr_file.handle, S.attrs) catch {}; - }, - } - } -} - fn populateModule(di: *DebugInfo, mod: *Module) !void { if (mod.populated) return; @@ -706,17 +666,12 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach return null; } -fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void { +fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void { const base_addr = process.getBaseAddress(); const adjusted_addr = 0x100000000 + (address - base_addr); const symbol = machoSearchSymbols(di.symbols, adjusted_addr) orelse { - if (tty_color) { - try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? (???)" ++ RESET ++ "\n\n\n", .{address}); - } else { - try out_stream.print("???:?:?: 0x{x} in ??? (???)\n\n\n", .{address}); - } - return; + return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs); }; const symbol_name = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + symbol.nlist.n_strx)); @@ -724,78 +679,70 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt const ofile_path = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + ofile.n_strx)); break :blk fs.path.basename(ofile_path); } else "???"; - if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| { - defer line_info.deinit(); - try printLineInfo( - out_stream, - line_info, - address, - symbol_name, - compile_unit_name, - tty_color, - printLineFromFileAnyOs, - ); - } else |err| switch (err) { - error.MissingDebugInfo, error.InvalidDebugInfo => { - if (tty_color) { - try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in {} ({})" ++ RESET ++ "\n\n\n", .{ - address, symbol_name, compile_unit_name, - }); - } else { - try out_stream.print("???:?:?: 0x{x} in {} ({})\n\n\n", .{ address, symbol_name, compile_unit_name }); - } - }, + + const line_info = getLineNumberInfoMacOs(di, symbol.*, adjusted_addr) catch |err| switch (err) { + error.MissingDebugInfo, error.InvalidDebugInfo => null, else => return err, - } + }; + defer if (line_info) |li| li.deinit(); + + try printLineInfo( + out_stream, + line_info, + address, + symbol_name, + compile_unit_name, + tty_config, + printLineFromFileAnyOs, + ); } -pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void { - return debug_info.printSourceAtAddress(out_stream, address, tty_color, printLineFromFileAnyOs); +pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void { + return debug_info.printSourceAtAddress(out_stream, address, tty_config, printLineFromFileAnyOs); } fn printLineInfo( out_stream: var, - line_info: LineInfo, + line_info: ?LineInfo, address: usize, symbol_name: []const u8, compile_unit_name: []const u8, - tty_color: bool, + tty_config: TTY.Config, comptime printLineFromFile: var, ) !void { - if (tty_color) { - try out_stream.print(WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++ DIM ++ "0x{x} in {} ({})" ++ RESET ++ "\n", .{ - line_info.file_name, - line_info.line, - line_info.column, - address, - symbol_name, - compile_unit_name, - }); - if (printLineFromFile(out_stream, line_info)) { - if (line_info.column == 0) { - try out_stream.write("\n"); - } else { - { - var col_i: usize = 1; - while (col_i < line_info.column) : (col_i += 1) { - try out_stream.writeByte(' '); - } - } - try out_stream.write(GREEN ++ "^" ++ RESET ++ "\n"); + tty_config.setColor(out_stream, .White); + + if (line_info) |*li| { + try out_stream.print("{}:{}:{}", .{ li.file_name, li.line, li.column }); + } else { + try out_stream.print("???:?:?", .{}); + } + + tty_config.setColor(out_stream, .Reset); + try out_stream.write(": "); + tty_config.setColor(out_stream, .Dim); + try out_stream.print("0x{x} in {} ({})", .{ address, symbol_name, compile_unit_name }); + tty_config.setColor(out_stream, .Reset); + try out_stream.write("\n"); + + // Show the matching source code line if possible + if (line_info) |li| { + if (noasync printLineFromFile(out_stream, li)) { + if (li.column > 0) { + // The caret already takes one char + const space_needed = @intCast(usize, li.column - 1); + + try out_stream.writeByteNTimes(' ', space_needed); + tty_config.setColor(out_stream, .Green); + try out_stream.write("^"); + tty_config.setColor(out_stream, .Reset); } + try out_stream.write("\n"); } else |err| switch (err) { error.EndOfFile, error.FileNotFound => {}, + error.BadPathName => {}, else => return err, } - } else { - try out_stream.print("{}:{}:{}: 0x{x} in {} ({})\n", .{ - line_info.file_name, - line_info.line, - line_info.column, - address, - symbol_name, - compile_unit_name, - }); } } @@ -1016,59 +963,61 @@ pub fn openDwarfDebugInfo(di: *DwarfInfo, allocator: *mem.Allocator) !void { pub fn openElfDebugInfo( allocator: *mem.Allocator, - elf_seekable_stream: *DwarfSeekableStream, - elf_in_stream: *DwarfInStream, + data: []u8, ) !DwarfInfo { - var efile = try elf.Elf.openStream(allocator, elf_seekable_stream, elf_in_stream); - errdefer efile.close(); + var seekable_stream = io.SliceSeekableInStream.init(data); + var efile = try elf.Elf.openStream( + allocator, + @ptrCast(*DwarfSeekableStream, &seekable_stream.seekable_stream), + @ptrCast(*DwarfInStream, &seekable_stream.stream), + ); + defer efile.close(); + + const debug_info = (try efile.findSection(".debug_info")) orelse + return error.MissingDebugInfo; + const debug_abbrev = (try efile.findSection(".debug_abbrev")) orelse + return error.MissingDebugInfo; + const debug_str = (try efile.findSection(".debug_str")) orelse + return error.MissingDebugInfo; + const debug_line = (try efile.findSection(".debug_line")) orelse + return error.MissingDebugInfo; + const opt_debug_ranges = try efile.findSection(".debug_ranges"); var di = DwarfInfo{ - .dwarf_seekable_stream = elf_seekable_stream, - .dwarf_in_stream = elf_in_stream, .endian = efile.endian, - .debug_info = (try findDwarfSectionFromElf(&efile, ".debug_info")) orelse return error.MissingDebugInfo, - .debug_abbrev = (try findDwarfSectionFromElf(&efile, ".debug_abbrev")) orelse return error.MissingDebugInfo, - .debug_str = (try findDwarfSectionFromElf(&efile, ".debug_str")) orelse return error.MissingDebugInfo, - .debug_line = (try findDwarfSectionFromElf(&efile, ".debug_line")) orelse return error.MissingDebugInfo, - .debug_ranges = (try findDwarfSectionFromElf(&efile, ".debug_ranges")), - .abbrev_table_list = undefined, - .compile_unit_list = undefined, - .func_list = undefined, + .debug_info = (data[@intCast(usize, debug_info.offset)..@intCast(usize, debug_info.offset + debug_info.size)]), + .debug_abbrev = (data[@intCast(usize, debug_abbrev.offset)..@intCast(usize, debug_abbrev.offset + debug_abbrev.size)]), + .debug_str = (data[@intCast(usize, debug_str.offset)..@intCast(usize, debug_str.offset + debug_str.size)]), + .debug_line = (data[@intCast(usize, debug_line.offset)..@intCast(usize, debug_line.offset + debug_line.size)]), + .debug_ranges = if (opt_debug_ranges) |debug_ranges| + data[@intCast(usize, debug_ranges.offset)..@intCast(usize, debug_ranges.offset + debug_ranges.size)] + else + null, }; + + efile.close(); + try openDwarfDebugInfo(&di, allocator); return di; } fn openSelfDebugInfoPosix(allocator: *mem.Allocator) !DwarfInfo { - const S = struct { - var self_exe_file: File = undefined; - var self_exe_mmap_seekable: io.SliceSeekableInStream = undefined; - }; + var exe_file = try fs.openSelfExe(); + errdefer exe_file.close(); - S.self_exe_file = try fs.openSelfExe(); - errdefer S.self_exe_file.close(); - - const self_exe_len = math.cast(usize, try S.self_exe_file.getEndPos()) catch return error.DebugInfoTooLarge; - const self_exe_mmap_len = mem.alignForward(self_exe_len, mem.page_size); - const self_exe_mmap = try os.mmap( + const exe_len = math.cast(usize, try exe_file.getEndPos()) catch + return error.DebugInfoTooLarge; + const exe_mmap = try os.mmap( null, - self_exe_mmap_len, + exe_len, os.PROT_READ, os.MAP_SHARED, - S.self_exe_file.handle, + exe_file.handle, 0, ); - errdefer os.munmap(self_exe_mmap); + errdefer os.munmap(exe_mmap); - S.self_exe_mmap_seekable = io.SliceSeekableInStream.init(self_exe_mmap); - - return openElfDebugInfo( - allocator, - // TODO https://github.com/ziglang/zig/issues/764 - @ptrCast(*DwarfSeekableStream, &S.self_exe_mmap_seekable.seekable_stream), - // TODO https://github.com/ziglang/zig/issues/764 - @ptrCast(*DwarfInStream, &S.self_exe_mmap_seekable.stream), - ); + return openElfDebugInfo(allocator, exe_mmap); } fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo { @@ -1195,83 +1144,56 @@ const MachoSymbol = struct { } }; -const MachOFile = struct { - bytes: []align(@alignOf(macho.mach_header_64)) const u8, - sect_debug_info: ?*const macho.section_64, - sect_debug_line: ?*const macho.section_64, -}; - pub const DwarfSeekableStream = io.SeekableStream(anyerror, anyerror); pub const DwarfInStream = io.InStream(anyerror); pub const DwarfInfo = struct { - dwarf_seekable_stream: *DwarfSeekableStream, - dwarf_in_stream: *DwarfInStream, endian: builtin.Endian, - debug_info: Section, - debug_abbrev: Section, - debug_str: Section, - debug_line: Section, - debug_ranges: ?Section, - abbrev_table_list: ArrayList(AbbrevTableHeader), - compile_unit_list: ArrayList(CompileUnit), - func_list: ArrayList(Func), - - pub const Section = struct { - offset: u64, - size: u64, - }; + // No memory is owned by the DwarfInfo + debug_info: []u8, + debug_abbrev: []u8, + debug_str: []u8, + debug_line: []u8, + debug_ranges: ?[]u8, + // Filled later by the initializer + abbrev_table_list: ArrayList(AbbrevTableHeader) = undefined, + compile_unit_list: ArrayList(CompileUnit) = undefined, + func_list: ArrayList(Func) = undefined, pub fn allocator(self: DwarfInfo) *mem.Allocator { return self.abbrev_table_list.allocator; } - pub fn readString(self: *DwarfInfo) ![]u8 { - return readStringRaw(self.allocator(), self.dwarf_in_stream); - } - /// This function works in freestanding mode. /// fn printLineFromFile(out_stream: var, line_info: LineInfo) !void pub fn printSourceAtAddress( self: *DwarfInfo, out_stream: var, address: usize, - tty_color: bool, + tty_config: TTY.Config, comptime printLineFromFile: var, ) !void { const compile_unit = self.findCompileUnit(address) catch { - if (tty_color) { - try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? (???)" ++ RESET ++ "\n\n\n", .{address}); - } else { - try out_stream.print("???:?:?: 0x{x} in ??? (???)\n\n\n", .{address}); - } - return; + return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFile); }; + const compile_unit_name = try compile_unit.die.getAttrString(self, DW.AT_name); - if (self.getLineNumberInfo(compile_unit.*, address)) |line_info| { - defer line_info.deinit(); - const symbol_name = self.getSymbolName(address) orelse "???"; - try printLineInfo( - out_stream, - line_info, - address, - symbol_name, - compile_unit_name, - tty_color, - printLineFromFile, - ); - } else |err| switch (err) { - error.MissingDebugInfo, error.InvalidDebugInfo => { - if (tty_color) { - try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? ({})" ++ RESET ++ "\n\n\n", .{ - address, compile_unit_name, - }); - } else { - try out_stream.print("???:?:?: 0x{x} in ??? ({})\n\n\n", .{ address, compile_unit_name }); - } - }, + const symbol_name = self.getSymbolName(address) orelse "???"; + const line_info = self.getLineNumberInfo(compile_unit.*, address) catch |err| switch (err) { + error.MissingDebugInfo, error.InvalidDebugInfo => null, else => return err, - } + }; + defer if (line_info) |li| li.deinit(); + + try printLineInfo( + out_stream, + line_info, + address, + symbol_name, + compile_unit_name, + tty_config, + printLineFromFile, + ); } fn getSymbolName(di: *DwarfInfo, address: u64) ?[]const u8 { @@ -1287,35 +1209,38 @@ pub const DwarfInfo = struct { } fn scanAllFunctions(di: *DwarfInfo) !void { - const debug_info_end = di.debug_info.offset + di.debug_info.size; - var this_unit_offset = di.debug_info.offset; + var s = io.SliceSeekableInStream.init(di.debug_info); + var this_unit_offset: u64 = 0; - while (this_unit_offset < debug_info_end) { - try di.dwarf_seekable_stream.seekTo(this_unit_offset); + while (true) { + s.seekable_stream.seekTo(this_unit_offset) catch |err| switch (err) { + error.EndOfStream => return, + else => return err, + }; var is_64: bool = undefined; - const unit_length = try readInitialLength(@TypeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64); + const unit_length = try readInitialLength(@TypeOf(s.stream.readFn).ReturnType.ErrorSet, &s.stream, &is_64); if (unit_length == 0) return; const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4)); - const version = try di.dwarf_in_stream.readInt(u16, di.endian); + const version = try s.stream.readInt(u16, di.endian); if (version < 2 or version > 5) return error.InvalidDebugInfo; - const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian); + const debug_abbrev_offset = if (is_64) try s.stream.readInt(u64, di.endian) else try s.stream.readInt(u32, di.endian); - const address_size = try di.dwarf_in_stream.readByte(); + const address_size = try s.stream.readByte(); if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; - const compile_unit_pos = try di.dwarf_seekable_stream.getPos(); + const compile_unit_pos = try s.seekable_stream.getPos(); const abbrev_table = try di.getAbbrevTable(debug_abbrev_offset); - try di.dwarf_seekable_stream.seekTo(compile_unit_pos); + try s.seekable_stream.seekTo(compile_unit_pos); const next_unit_pos = this_unit_offset + next_offset; - while ((try di.dwarf_seekable_stream.getPos()) < next_unit_pos) { - const die_obj = (try di.parseDie(abbrev_table, is_64)) orelse continue; - const after_die_offset = try di.dwarf_seekable_stream.getPos(); + while ((try s.seekable_stream.getPos()) < next_unit_pos) { + const die_obj = (try di.parseDie(&s.stream, abbrev_table, is_64)) orelse continue; + const after_die_offset = try s.seekable_stream.getPos(); switch (die_obj.tag_id) { DW.TAG_subprogram, DW.TAG_inlined_subroutine, DW.TAG_subroutine, DW.TAG_entry_point => { @@ -1331,14 +1256,14 @@ pub const DwarfInfo = struct { // Follow the DIE it points to and repeat const ref_offset = try this_die_obj.getAttrRef(DW.AT_abstract_origin); if (ref_offset > next_offset) return error.InvalidDebugInfo; - try di.dwarf_seekable_stream.seekTo(this_unit_offset + ref_offset); - this_die_obj = (try di.parseDie(abbrev_table, is_64)) orelse return error.InvalidDebugInfo; + try s.seekable_stream.seekTo(this_unit_offset + ref_offset); + this_die_obj = (try di.parseDie(&s.stream, abbrev_table, is_64)) orelse return error.InvalidDebugInfo; } else if (this_die_obj.getAttr(DW.AT_specification)) |ref| { // Follow the DIE it points to and repeat const ref_offset = try this_die_obj.getAttrRef(DW.AT_specification); if (ref_offset > next_offset) return error.InvalidDebugInfo; - try di.dwarf_seekable_stream.seekTo(this_unit_offset + ref_offset); - this_die_obj = (try di.parseDie(abbrev_table, is_64)) orelse return error.InvalidDebugInfo; + try s.seekable_stream.seekTo(this_unit_offset + ref_offset); + this_die_obj = (try di.parseDie(&s.stream, abbrev_table, is_64)) orelse return error.InvalidDebugInfo; } else { break :x null; } @@ -1376,12 +1301,10 @@ pub const DwarfInfo = struct { .pc_range = pc_range, }); }, - else => { - continue; - }, + else => {}, } - try di.dwarf_seekable_stream.seekTo(after_die_offset); + try s.seekable_stream.seekTo(after_die_offset); } this_unit_offset += next_offset; @@ -1389,32 +1312,35 @@ pub const DwarfInfo = struct { } fn scanAllCompileUnits(di: *DwarfInfo) !void { - const debug_info_end = di.debug_info.offset + di.debug_info.size; - var this_unit_offset = di.debug_info.offset; + var s = io.SliceSeekableInStream.init(di.debug_info); + var this_unit_offset: u64 = 0; - while (this_unit_offset < debug_info_end) { - try di.dwarf_seekable_stream.seekTo(this_unit_offset); + while (true) { + s.seekable_stream.seekTo(this_unit_offset) catch |err| switch (err) { + error.EndOfStream => return, + else => return err, + }; var is_64: bool = undefined; - const unit_length = try readInitialLength(@TypeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64); + const unit_length = try readInitialLength(@TypeOf(s.stream.readFn).ReturnType.ErrorSet, &s.stream, &is_64); if (unit_length == 0) return; const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4)); - const version = try di.dwarf_in_stream.readInt(u16, di.endian); + const version = try s.stream.readInt(u16, di.endian); if (version < 2 or version > 5) return error.InvalidDebugInfo; - const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian); + const debug_abbrev_offset = if (is_64) try s.stream.readInt(u64, di.endian) else try s.stream.readInt(u32, di.endian); - const address_size = try di.dwarf_in_stream.readByte(); + const address_size = try s.stream.readByte(); if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; - const compile_unit_pos = try di.dwarf_seekable_stream.getPos(); + const compile_unit_pos = try s.seekable_stream.getPos(); const abbrev_table = try di.getAbbrevTable(debug_abbrev_offset); - try di.dwarf_seekable_stream.seekTo(compile_unit_pos); + try s.seekable_stream.seekTo(compile_unit_pos); const compile_unit_die = try di.allocator().create(Die); - compile_unit_die.* = (try di.parseDie(abbrev_table, is_64)) orelse return error.InvalidDebugInfo; + compile_unit_die.* = (try di.parseDie(&s.stream, abbrev_table, is_64)) orelse return error.InvalidDebugInfo; if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo; @@ -1458,28 +1384,38 @@ pub const DwarfInfo = struct { if (compile_unit.pc_range) |range| { if (target_address >= range.start and target_address < range.end) return compile_unit; } - if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| { - var base_address: usize = 0; - if (di.debug_ranges) |debug_ranges| { - try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset); + if (di.debug_ranges) |debug_ranges| { + if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| { + var s = io.SliceSeekableInStream.init(debug_ranges); + + // All the addresses in the list are relative to the value + // specified by DW_AT_low_pc or to some other value encoded + // in the list itself + var base_address = try compile_unit.die.getAttrAddr(DW.AT_low_pc); + + try s.seekable_stream.seekTo(ranges_offset); + while (true) { - const begin_addr = try di.dwarf_in_stream.readIntLittle(usize); - const end_addr = try di.dwarf_in_stream.readIntLittle(usize); + const begin_addr = try s.stream.readIntLittle(usize); + const end_addr = try s.stream.readIntLittle(usize); if (begin_addr == 0 and end_addr == 0) { break; } + // This entry selects a new value for the base address if (begin_addr == maxInt(usize)) { - base_address = begin_addr; + base_address = end_addr; continue; } - if (target_address >= begin_addr and target_address < end_addr) { + if (target_address >= base_address + begin_addr and target_address < base_address + end_addr) { return compile_unit; } } + + return error.InvalidDebugInfo; + } else |err| { + if (err != error.MissingDebugInfo) return err; + continue; } - } else |err| { - if (err != error.MissingDebugInfo) return err; - continue; } } return error.MissingDebugInfo; @@ -1493,30 +1429,33 @@ pub const DwarfInfo = struct { return &header.table; } } - try di.dwarf_seekable_stream.seekTo(di.debug_abbrev.offset + abbrev_offset); try di.abbrev_table_list.append(AbbrevTableHeader{ .offset = abbrev_offset, - .table = try di.parseAbbrevTable(), + .table = try di.parseAbbrevTable(abbrev_offset), }); return &di.abbrev_table_list.items[di.abbrev_table_list.len - 1].table; } - fn parseAbbrevTable(di: *DwarfInfo) !AbbrevTable { + fn parseAbbrevTable(di: *DwarfInfo, offset: u64) !AbbrevTable { + var s = io.SliceSeekableInStream.init(di.debug_abbrev); + + try s.seekable_stream.seekTo(offset); var result = AbbrevTable.init(di.allocator()); + errdefer result.deinit(); while (true) { - const abbrev_code = try leb.readULEB128(u64, di.dwarf_in_stream); + const abbrev_code = try leb.readULEB128(u64, &s.stream); if (abbrev_code == 0) return result; try result.append(AbbrevTableEntry{ .abbrev_code = abbrev_code, - .tag_id = try leb.readULEB128(u64, di.dwarf_in_stream), - .has_children = (try di.dwarf_in_stream.readByte()) == DW.CHILDREN_yes, + .tag_id = try leb.readULEB128(u64, &s.stream), + .has_children = (try s.stream.readByte()) == DW.CHILDREN_yes, .attrs = ArrayList(AbbrevAttr).init(di.allocator()), }); const attrs = &result.items[result.len - 1].attrs; while (true) { - const attr_id = try leb.readULEB128(u64, di.dwarf_in_stream); - const form_id = try leb.readULEB128(u64, di.dwarf_in_stream); + const attr_id = try leb.readULEB128(u64, &s.stream); + const form_id = try leb.readULEB128(u64, &s.stream); if (attr_id == 0 and form_id == 0) break; try attrs.append(AbbrevAttr{ .attr_id = attr_id, @@ -1526,8 +1465,8 @@ pub const DwarfInfo = struct { } } - fn parseDie(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !?Die { - const abbrev_code = try leb.readULEB128(u64, di.dwarf_in_stream); + fn parseDie(di: *DwarfInfo, in_stream: var, abbrev_table: *const AbbrevTable, is_64: bool) !?Die { + const abbrev_code = try leb.readULEB128(u64, in_stream); if (abbrev_code == 0) return null; const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo; @@ -1540,63 +1479,63 @@ pub const DwarfInfo = struct { for (table_entry.attrs.toSliceConst()) |attr, i| { result.attrs.items[i] = Die.Attr{ .id = attr.attr_id, - .value = try parseFormValue(di.allocator(), di.dwarf_in_stream, attr.form_id, is_64), + .value = try parseFormValue(di.allocator(), in_stream, attr.form_id, is_64), }; } return result; } fn getLineNumberInfo(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo { + var s = io.SliceSeekableInStream.init(di.debug_line); + const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir); const line_info_offset = try compile_unit.die.getAttrSecOffset(DW.AT_stmt_list); - assert(line_info_offset < di.debug_line.size); - - try di.dwarf_seekable_stream.seekTo(di.debug_line.offset + line_info_offset); + try s.seekable_stream.seekTo(line_info_offset); var is_64: bool = undefined; - const unit_length = try readInitialLength(@TypeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64); + const unit_length = try readInitialLength(@TypeOf(s.stream.readFn).ReturnType.ErrorSet, &s.stream, &is_64); if (unit_length == 0) { return error.MissingDebugInfo; } const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4)); - const version = try di.dwarf_in_stream.readInt(u16, di.endian); + const version = try s.stream.readInt(u16, di.endian); // TODO support 3 and 5 if (version != 2 and version != 4) return error.InvalidDebugInfo; - const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian); - const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length; + const prologue_length = if (is_64) try s.stream.readInt(u64, di.endian) else try s.stream.readInt(u32, di.endian); + const prog_start_offset = (try s.seekable_stream.getPos()) + prologue_length; - const minimum_instruction_length = try di.dwarf_in_stream.readByte(); + const minimum_instruction_length = try s.stream.readByte(); if (minimum_instruction_length == 0) return error.InvalidDebugInfo; if (version >= 4) { // maximum_operations_per_instruction - _ = try di.dwarf_in_stream.readByte(); + _ = try s.stream.readByte(); } - const default_is_stmt = (try di.dwarf_in_stream.readByte()) != 0; - const line_base = try di.dwarf_in_stream.readByteSigned(); + const default_is_stmt = (try s.stream.readByte()) != 0; + const line_base = try s.stream.readByteSigned(); - const line_range = try di.dwarf_in_stream.readByte(); + const line_range = try s.stream.readByte(); if (line_range == 0) return error.InvalidDebugInfo; - const opcode_base = try di.dwarf_in_stream.readByte(); + const opcode_base = try s.stream.readByte(); const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1); { var i: usize = 0; while (i < opcode_base - 1) : (i += 1) { - standard_opcode_lengths[i] = try di.dwarf_in_stream.readByte(); + standard_opcode_lengths[i] = try s.stream.readByte(); } } var include_directories = ArrayList([]u8).init(di.allocator()); try include_directories.append(compile_unit_cwd); while (true) { - const dir = try di.readString(); + const dir = try readStringRaw(di.allocator(), &s.stream); if (dir.len == 0) break; try include_directories.append(dir); } @@ -1605,11 +1544,11 @@ pub const DwarfInfo = struct { var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), &file_entries, target_address); while (true) { - const file_name = try di.readString(); + const file_name = try readStringRaw(di.allocator(), &s.stream); if (file_name.len == 0) break; - const dir_index = try leb.readULEB128(usize, di.dwarf_in_stream); - const mtime = try leb.readULEB128(usize, di.dwarf_in_stream); - const len_bytes = try leb.readULEB128(usize, di.dwarf_in_stream); + const dir_index = try leb.readULEB128(usize, &s.stream); + const mtime = try leb.readULEB128(usize, &s.stream); + const len_bytes = try leb.readULEB128(usize, &s.stream); try file_entries.append(FileEntry{ .file_name = file_name, .dir_index = dir_index, @@ -1618,30 +1557,32 @@ pub const DwarfInfo = struct { }); } - try di.dwarf_seekable_stream.seekTo(prog_start_offset); + try s.seekable_stream.seekTo(prog_start_offset); - while (true) { - const opcode = try di.dwarf_in_stream.readByte(); + const next_unit_pos = line_info_offset + next_offset; + + while ((try s.seekable_stream.getPos()) < next_unit_pos) { + const opcode = try s.stream.readByte(); if (opcode == DW.LNS_extended_op) { - const op_size = try leb.readULEB128(u64, di.dwarf_in_stream); + const op_size = try leb.readULEB128(u64, &s.stream); if (op_size < 1) return error.InvalidDebugInfo; - var sub_op = try di.dwarf_in_stream.readByte(); + var sub_op = try s.stream.readByte(); switch (sub_op) { DW.LNE_end_sequence => { prog.end_sequence = true; if (try prog.checkLineMatch()) |info| return info; - return error.MissingDebugInfo; + prog.reset(); }, DW.LNE_set_address => { - const addr = try di.dwarf_in_stream.readInt(usize, di.endian); + const addr = try s.stream.readInt(usize, di.endian); prog.address = addr; }, DW.LNE_define_file => { - const file_name = try di.readString(); - const dir_index = try leb.readULEB128(usize, di.dwarf_in_stream); - const mtime = try leb.readULEB128(usize, di.dwarf_in_stream); - const len_bytes = try leb.readULEB128(usize, di.dwarf_in_stream); + const file_name = try readStringRaw(di.allocator(), &s.stream); + const dir_index = try leb.readULEB128(usize, &s.stream); + const mtime = try leb.readULEB128(usize, &s.stream); + const len_bytes = try leb.readULEB128(usize, &s.stream); try file_entries.append(FileEntry{ .file_name = file_name, .dir_index = dir_index, @@ -1651,7 +1592,7 @@ pub const DwarfInfo = struct { }, else => { const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo; - try di.dwarf_seekable_stream.seekBy(fwd_amt); + try s.seekable_stream.seekBy(fwd_amt); }, } } else if (opcode >= opcode_base) { @@ -1670,19 +1611,19 @@ pub const DwarfInfo = struct { prog.basic_block = false; }, DW.LNS_advance_pc => { - const arg = try leb.readULEB128(usize, di.dwarf_in_stream); + const arg = try leb.readULEB128(usize, &s.stream); prog.address += arg * minimum_instruction_length; }, DW.LNS_advance_line => { - const arg = try leb.readILEB128(i64, di.dwarf_in_stream); + const arg = try leb.readILEB128(i64, &s.stream); prog.line += arg; }, DW.LNS_set_file => { - const arg = try leb.readULEB128(usize, di.dwarf_in_stream); + const arg = try leb.readULEB128(usize, &s.stream); prog.file = arg; }, DW.LNS_set_column => { - const arg = try leb.readULEB128(u64, di.dwarf_in_stream); + const arg = try leb.readULEB128(u64, &s.stream); prog.column = arg; }, DW.LNS_negate_stmt => { @@ -1696,14 +1637,14 @@ pub const DwarfInfo = struct { prog.address += inc_addr; }, DW.LNS_fixed_advance_pc => { - const arg = try di.dwarf_in_stream.readInt(u16, di.endian); + const arg = try s.stream.readInt(u16, di.endian); prog.address += arg; }, DW.LNS_set_prologue_end => {}, else => { if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo; const len_bytes = standard_opcode_lengths[opcode - 1]; - try di.dwarf_seekable_stream.seekBy(len_bytes); + try s.seekable_stream.seekBy(len_bytes); }, } } @@ -1713,9 +1654,17 @@ pub const DwarfInfo = struct { } fn getString(di: *DwarfInfo, offset: u64) ![]u8 { - const pos = di.debug_str.offset + offset; - try di.dwarf_seekable_stream.seekTo(pos); - return di.readString(); + if (offset > di.debug_str.len) + return error.InvalidDebugInfo; + const casted_offset = math.cast(usize, offset) catch + return error.InvalidDebugInfo; + + // Valid strings always have a terminating zero byte + if (mem.indexOfScalarPos(u8, di.debug_str, casted_offset, 0)) |last| { + return di.debug_str[casted_offset..last]; + } + + return error.InvalidDebugInfo; } }; @@ -1727,7 +1676,7 @@ pub const DebugInfo = switch (builtin.os) { const OFileTable = std.HashMap( *macho.nlist_64, - MachOFile, + DwarfInfo, std.hash_map.getHashPtrAddrFn(*macho.nlist_64), std.hash_map.getTrivialEqlFn(*macho.nlist_64), ); @@ -1888,6 +1837,7 @@ const LineNumberProgram = struct { basic_block: bool, end_sequence: bool, + default_is_stmt: bool, target_address: usize, include_dirs: []const []const u8, file_entries: *ArrayList(FileEntry), @@ -1900,6 +1850,25 @@ const LineNumberProgram = struct { prev_basic_block: bool, prev_end_sequence: bool, + // Reset the state machine following the DWARF specification + pub fn reset(self: *LineNumberProgram) void { + self.address = 0; + self.file = 1; + self.line = 1; + self.column = 0; + self.is_stmt = self.default_is_stmt; + self.basic_block = false; + self.end_sequence = false; + // Invalidate all the remaining fields + self.prev_address = 0; + self.prev_file = undefined; + self.prev_line = undefined; + self.prev_column = undefined; + self.prev_is_stmt = undefined; + self.prev_basic_block = undefined; + self.prev_end_sequence = undefined; + } + pub fn init(is_stmt: bool, include_dirs: []const []const u8, file_entries: *ArrayList(FileEntry), target_address: usize) LineNumberProgram { return LineNumberProgram{ .address = 0, @@ -1911,6 +1880,7 @@ const LineNumberProgram = struct { .end_sequence = false, .include_dirs = include_dirs, .file_entries = file_entries, + .default_is_stmt = is_stmt, .target_address = target_address, .prev_address = 0, .prev_file = undefined, @@ -2100,24 +2070,32 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con return null; } -fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: usize) !LineInfo { +fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, address: usize) !LineInfo { const ofile = symbol.ofile orelse return error.MissingDebugInfo; const gop = try di.ofiles.getOrPut(ofile); - const mach_o_file = if (gop.found_existing) &gop.kv.value else blk: { + const dwarf_info = if (gop.found_existing) &gop.kv.value else blk: { errdefer _ = di.ofiles.remove(ofile); const ofile_path = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + ofile.n_strx)); - gop.kv.value = MachOFile{ - .bytes = try std.fs.cwd().readFileAllocAligned( - di.ofiles.allocator, - ofile_path, - maxInt(usize), - @alignOf(macho.mach_header_64), - ), - .sect_debug_info = null, - .sect_debug_line = null, - }; - const hdr = @ptrCast(*const macho.mach_header_64, gop.kv.value.bytes.ptr); + var exe_file = try std.fs.openFileAbsoluteC(ofile_path, .{}); + errdefer exe_file.close(); + + const exe_len = math.cast(usize, try exe_file.getEndPos()) catch + return error.DebugInfoTooLarge; + const exe_mmap = try os.mmap( + null, + exe_len, + os.PROT_READ, + os.MAP_SHARED, + exe_file.handle, + 0, + ); + errdefer os.munmap(exe_mmap); + + const hdr = @ptrCast( + *const macho.mach_header_64, + @alignCast(@alignOf(macho.mach_header_64), exe_mmap.ptr), + ); if (hdr.magic != std.macho.MH_MAGIC_64) return error.InvalidDebugInfo; const hdr_base = @ptrCast([*]const u8, hdr); @@ -2126,181 +2104,75 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u const segcmd = while (ncmd != 0) : (ncmd -= 1) { const lc = @ptrCast(*const std.macho.load_command, ptr); switch (lc.cmd) { - std.macho.LC_SEGMENT_64 => break @ptrCast(*const std.macho.segment_command_64, @alignCast(@alignOf(std.macho.segment_command_64), ptr)), + std.macho.LC_SEGMENT_64 => { + break @ptrCast( + *const std.macho.segment_command_64, + @alignCast(@alignOf(std.macho.segment_command_64), ptr), + ); + }, else => {}, } ptr = @alignCast(@alignOf(std.macho.load_command), ptr + lc.cmdsize); } else { return error.MissingDebugInfo; }; + + var opt_debug_line: ?*const macho.section_64 = null; + var opt_debug_info: ?*const macho.section_64 = null; + var opt_debug_abbrev: ?*const macho.section_64 = null; + var opt_debug_str: ?*const macho.section_64 = null; + var opt_debug_ranges: ?*const macho.section_64 = null; + const sections = @ptrCast([*]const macho.section_64, @alignCast(@alignOf(macho.section_64), ptr + @sizeOf(std.macho.segment_command_64)))[0..segcmd.nsects]; for (sections) |*sect| { - if (sect.flags & macho.SECTION_TYPE == macho.S_REGULAR and - (sect.flags & macho.SECTION_ATTRIBUTES) & macho.S_ATTR_DEBUG == macho.S_ATTR_DEBUG) - { - const sect_name = mem.toSliceConst(u8, @ptrCast([*:0]const u8, §.sectname)); - if (mem.eql(u8, sect_name, "__debug_line")) { - gop.kv.value.sect_debug_line = sect; - } else if (mem.eql(u8, sect_name, "__debug_info")) { - gop.kv.value.sect_debug_info = sect; - } + // The section name may not exceed 16 chars and a trailing null may + // not be present + const name = if (mem.indexOfScalar(u8, sect.sectname[0..], 0)) |last| + sect.sectname[0..last] + else + sect.sectname[0..]; + + if (mem.eql(u8, name, "__debug_line")) { + opt_debug_line = sect; + } else if (mem.eql(u8, name, "__debug_info")) { + opt_debug_info = sect; + } else if (mem.eql(u8, name, "__debug_abbrev")) { + opt_debug_abbrev = sect; + } else if (mem.eql(u8, name, "__debug_str")) { + opt_debug_str = sect; + } else if (mem.eql(u8, name, "__debug_ranges")) { + opt_debug_ranges = sect; } } + var debug_line = opt_debug_line orelse + return error.MissingDebugInfo; + var debug_info = opt_debug_info orelse + return error.MissingDebugInfo; + var debug_str = opt_debug_str orelse + return error.MissingDebugInfo; + var debug_abbrev = opt_debug_abbrev orelse + return error.MissingDebugInfo; + + gop.kv.value = DwarfInfo{ + .endian = .Little, + .debug_info = exe_mmap[@intCast(usize, debug_info.offset)..@intCast(usize, debug_info.offset + debug_info.size)], + .debug_abbrev = exe_mmap[@intCast(usize, debug_abbrev.offset)..@intCast(usize, debug_abbrev.offset + debug_abbrev.size)], + .debug_str = exe_mmap[@intCast(usize, debug_str.offset)..@intCast(usize, debug_str.offset + debug_str.size)], + .debug_line = exe_mmap[@intCast(usize, debug_line.offset)..@intCast(usize, debug_line.offset + debug_line.size)], + .debug_ranges = if (opt_debug_ranges) |debug_ranges| + exe_mmap[@intCast(usize, debug_ranges.offset)..@intCast(usize, debug_ranges.offset + debug_ranges.size)] + else + null, + }; + try openDwarfDebugInfo(&gop.kv.value, di.allocator()); + break :blk &gop.kv.value; }; - const sect_debug_line = mach_o_file.sect_debug_line orelse return error.MissingDebugInfo; - var ptr = mach_o_file.bytes.ptr + sect_debug_line.offset; - - var is_64: bool = undefined; - const unit_length = try readInitialLengthMem(&ptr, &is_64); - if (unit_length == 0) return error.MissingDebugInfo; - - const version = readIntMem(&ptr, u16, builtin.Endian.Little); - // TODO support 3 and 5 - if (version != 2 and version != 4) return error.InvalidDebugInfo; - - const prologue_length = if (is_64) - readIntMem(&ptr, u64, builtin.Endian.Little) - else - readIntMem(&ptr, u32, builtin.Endian.Little); - const prog_start = ptr + prologue_length; - - const minimum_instruction_length = readByteMem(&ptr); - if (minimum_instruction_length == 0) return error.InvalidDebugInfo; - - if (version >= 4) { - // maximum_operations_per_instruction - ptr += 1; - } - - const default_is_stmt = readByteMem(&ptr) != 0; - const line_base = readByteSignedMem(&ptr); - - const line_range = readByteMem(&ptr); - if (line_range == 0) return error.InvalidDebugInfo; - - const opcode_base = readByteMem(&ptr); - - const standard_opcode_lengths = ptr[0 .. opcode_base - 1]; - ptr += opcode_base - 1; - - var include_directories = ArrayList([]const u8).init(di.allocator()); - try include_directories.append(""); - while (true) { - const dir = readStringMem(&ptr); - if (dir.len == 0) break; - try include_directories.append(dir); - } - - var file_entries = ArrayList(FileEntry).init(di.allocator()); - var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), &file_entries, target_address); - - while (true) { - const file_name = readStringMem(&ptr); - if (file_name.len == 0) break; - const dir_index = try leb.readULEB128Mem(usize, &ptr); - const mtime = try leb.readULEB128Mem(usize, &ptr); - const len_bytes = try leb.readULEB128Mem(usize, &ptr); - try file_entries.append(FileEntry{ - .file_name = file_name, - .dir_index = dir_index, - .mtime = mtime, - .len_bytes = len_bytes, - }); - } - - ptr = prog_start; - while (true) { - const opcode = readByteMem(&ptr); - - if (opcode == DW.LNS_extended_op) { - const op_size = try leb.readULEB128Mem(u64, &ptr); - if (op_size < 1) return error.InvalidDebugInfo; - var sub_op = readByteMem(&ptr); - switch (sub_op) { - DW.LNE_end_sequence => { - prog.end_sequence = true; - if (try prog.checkLineMatch()) |info| return info; - return error.MissingDebugInfo; - }, - DW.LNE_set_address => { - const addr = readIntMem(&ptr, usize, builtin.Endian.Little); - prog.address = symbol.reloc + addr; - }, - DW.LNE_define_file => { - const file_name = readStringMem(&ptr); - const dir_index = try leb.readULEB128Mem(usize, &ptr); - const mtime = try leb.readULEB128Mem(usize, &ptr); - const len_bytes = try leb.readULEB128Mem(usize, &ptr); - try file_entries.append(FileEntry{ - .file_name = file_name, - .dir_index = dir_index, - .mtime = mtime, - .len_bytes = len_bytes, - }); - }, - else => { - ptr += op_size - 1; - }, - } - } else if (opcode >= opcode_base) { - // special opcodes - const adjusted_opcode = opcode - opcode_base; - const inc_addr = minimum_instruction_length * (adjusted_opcode / line_range); - const inc_line = @as(i32, line_base) + @as(i32, adjusted_opcode % line_range); - prog.line += inc_line; - prog.address += inc_addr; - if (try prog.checkLineMatch()) |info| return info; - prog.basic_block = false; - } else { - switch (opcode) { - DW.LNS_copy => { - if (try prog.checkLineMatch()) |info| return info; - prog.basic_block = false; - }, - DW.LNS_advance_pc => { - const arg = try leb.readULEB128Mem(usize, &ptr); - prog.address += arg * minimum_instruction_length; - }, - DW.LNS_advance_line => { - const arg = try leb.readILEB128Mem(i64, &ptr); - prog.line += arg; - }, - DW.LNS_set_file => { - const arg = try leb.readULEB128Mem(usize, &ptr); - prog.file = arg; - }, - DW.LNS_set_column => { - const arg = try leb.readULEB128Mem(u64, &ptr); - prog.column = arg; - }, - DW.LNS_negate_stmt => { - prog.is_stmt = !prog.is_stmt; - }, - DW.LNS_set_basic_block => { - prog.basic_block = true; - }, - DW.LNS_const_add_pc => { - const inc_addr = minimum_instruction_length * ((255 - opcode_base) / line_range); - prog.address += inc_addr; - }, - DW.LNS_fixed_advance_pc => { - const arg = readIntMem(&ptr, u16, builtin.Endian.Little); - prog.address += arg; - }, - DW.LNS_set_prologue_end => {}, - else => { - if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo; - const len_bytes = standard_opcode_lengths[opcode - 1]; - ptr += len_bytes; - }, - } - } - } - - return error.MissingDebugInfo; + const o_file_address = address - symbol.reloc; + const compile_unit = try dwarf_info.findCompileUnit(o_file_address); + return dwarf_info.getLineNumberInfo(compile_unit.*, o_file_address); } const Func = struct { @@ -2308,47 +2180,6 @@ const Func = struct { name: ?[]u8, }; -fn readIntMem(ptr: *[*]const u8, comptime T: type, endian: builtin.Endian) T { - // TODO https://github.com/ziglang/zig/issues/863 - const size = (T.bit_count + 7) / 8; - const result = mem.readIntSlice(T, ptr.*[0..size], endian); - ptr.* += size; - return result; -} - -fn readByteMem(ptr: *[*]const u8) u8 { - const result = ptr.*[0]; - ptr.* += 1; - return result; -} - -fn readByteSignedMem(ptr: *[*]const u8) i8 { - return @bitCast(i8, readByteMem(ptr)); -} - -fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 { - // TODO this code can be improved with https://github.com/ziglang/zig/issues/863 - const first_32_bits = mem.readIntSliceLittle(u32, ptr.*[0..4]); - is_64.* = (first_32_bits == 0xffffffff); - if (is_64.*) { - ptr.* += 4; - const result = mem.readIntSliceLittle(u64, ptr.*[0..8]); - ptr.* += 8; - return result; - } else { - if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo; - ptr.* += 4; - // TODO this cast should not be needed - return @as(u64, first_32_bits); - } -} - -fn readStringMem(ptr: *[*]const u8) [:0]const u8 { - const result = mem.toSliceConst(u8, @ptrCast([*:0]const u8, ptr.*)); - ptr.* += result.len + 1; - return result; -} - fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 { const first_32_bits = try in_stream.readIntLittle(u32); is_64.* = (first_32_bits == 0xffffffff); diff --git a/lib/std/dynamic_library.zig b/lib/std/dynamic_library.zig index db912ec922..ef64870b8d 100644 --- a/lib/std/dynamic_library.zig +++ b/lib/std/dynamic_library.zig @@ -277,7 +277,7 @@ pub const WindowsDynLib = struct { } pub fn openC(path_c: [*:0]const u8) !WindowsDynLib { - const path_w = try windows.cStrToPrefixedFileW(path); + const path_w = try windows.cStrToPrefixedFileW(path_c); return openW(&path_w); } diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 548ef8ccce..cf3322a995 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -431,7 +431,7 @@ pub fn formatType( }, else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }), }, - .Many => { + .Many, .C => { if (ptr_info.child == u8) { if (fmt.len > 0 and fmt[0] == 's') { const len = mem.len(u8, value); @@ -449,9 +449,6 @@ pub fn formatType( } return format(context, Errors, output, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) }); }, - .C => { - return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }); - }, }, .Array => |info| { const Slice = @Type(builtin.TypeInfo{ @@ -1138,6 +1135,11 @@ fn countSize(size: *usize, bytes: []const u8) (error{}!void) { size.* += bytes.len; } +pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 { + const result = try allocPrint(allocator, fmt ++ "\x00", args); + return result[0 .. result.len - 1 :0]; +} + test "bufPrintInt" { var buffer: [100]u8 = undefined; const buf = buffer[0..]; @@ -1285,8 +1287,16 @@ test "pointer" { } test "cstr" { - try testFmt("cstr: Test C\n", "cstr: {s}\n", .{"Test C"}); - try testFmt("cstr: Test C \n", "cstr: {s:10}\n", .{"Test C"}); + try testFmt( + "cstr: Test C\n", + "cstr: {s}\n", + .{@ptrCast([*c]const u8, "Test C")}, + ); + try testFmt( + "cstr: Test C \n", + "cstr: {s:10}\n", + .{@ptrCast([*c]const u8, "Test C")}, + ); } test "filesize" { diff --git a/lib/std/fmt/parse_float.zig b/lib/std/fmt/parse_float.zig index 2c480852ac..1456dd8e57 100644 --- a/lib/std/fmt/parse_float.zig +++ b/lib/std/fmt/parse_float.zig @@ -382,6 +382,10 @@ pub fn parseFloat(comptime T: type, s: []const u8) !T { } test "fmt.parseFloat" { + if (std.Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } const testing = std.testing; const expect = testing.expect; const expectEqual = testing.expectEqual; diff --git a/lib/std/hash/benchmark.zig b/lib/std/hash/benchmark.zig index ce9ed75b58..c792013e06 100644 --- a/lib/std/hash/benchmark.zig +++ b/lib/std/hash/benchmark.zig @@ -47,11 +47,11 @@ const hashes = [_]Hash{ .name = "adler32", }, Hash{ - .ty = hash.crc.Crc32WithPoly(hash.crc.Polynomial.IEEE), + .ty = hash.crc.Crc32WithPoly(.IEEE), .name = "crc32-slicing-by-8", }, Hash{ - .ty = hash.crc.Crc32SmallWithPoly(hash.crc.Polynomial.IEEE), + .ty = hash.crc.Crc32SmallWithPoly(.IEEE), .name = "crc32-half-byte-lookup", }, Hash{ diff --git a/lib/std/hash/crc.zig b/lib/std/hash/crc.zig index 6176ded81d..506d8c8aed 100644 --- a/lib/std/hash/crc.zig +++ b/lib/std/hash/crc.zig @@ -9,17 +9,18 @@ const std = @import("../std.zig"); const debug = std.debug; const testing = std.testing; -pub const Polynomial = struct { - pub const IEEE = 0xedb88320; - pub const Castagnoli = 0x82f63b78; - pub const Koopman = 0xeb31d82e; +pub const Polynomial = enum(u32) { + IEEE = 0xedb88320, + Castagnoli = 0x82f63b78, + Koopman = 0xeb31d82e, + _, }; // IEEE is by far the most common CRC and so is aliased by default. -pub const Crc32 = Crc32WithPoly(Polynomial.IEEE); +pub const Crc32 = Crc32WithPoly(.IEEE); // slicing-by-8 crc32 implementation. -pub fn Crc32WithPoly(comptime poly: u32) type { +pub fn Crc32WithPoly(comptime poly: Polynomial) type { return struct { const Self = @This(); const lookup_tables = comptime block: { @@ -31,7 +32,7 @@ pub fn Crc32WithPoly(comptime poly: u32) type { var j: usize = 0; while (j < 8) : (j += 1) { if (crc & 1 == 1) { - crc = (crc >> 1) ^ poly; + crc = (crc >> 1) ^ @enumToInt(poly); } else { crc = (crc >> 1); } @@ -100,7 +101,7 @@ pub fn Crc32WithPoly(comptime poly: u32) type { } test "crc32 ieee" { - const Crc32Ieee = Crc32WithPoly(Polynomial.IEEE); + const Crc32Ieee = Crc32WithPoly(.IEEE); testing.expect(Crc32Ieee.hash("") == 0x00000000); testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43); @@ -108,7 +109,7 @@ test "crc32 ieee" { } test "crc32 castagnoli" { - const Crc32Castagnoli = Crc32WithPoly(Polynomial.Castagnoli); + const Crc32Castagnoli = Crc32WithPoly(.Castagnoli); testing.expect(Crc32Castagnoli.hash("") == 0x00000000); testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330); @@ -116,7 +117,7 @@ test "crc32 castagnoli" { } // half-byte lookup table implementation. -pub fn Crc32SmallWithPoly(comptime poly: u32) type { +pub fn Crc32SmallWithPoly(comptime poly: Polynomial) type { return struct { const Self = @This(); const lookup_table = comptime block: { @@ -127,7 +128,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { var j: usize = 0; while (j < 8) : (j += 1) { if (crc & 1 == 1) { - crc = (crc >> 1) ^ poly; + crc = (crc >> 1) ^ @enumToInt(poly); } else { crc = (crc >> 1); } @@ -164,7 +165,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { } test "small crc32 ieee" { - const Crc32Ieee = Crc32SmallWithPoly(Polynomial.IEEE); + const Crc32Ieee = Crc32SmallWithPoly(.IEEE); testing.expect(Crc32Ieee.hash("") == 0x00000000); testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43); @@ -172,7 +173,7 @@ test "small crc32 ieee" { } test "small crc32 castagnoli" { - const Crc32Castagnoli = Crc32SmallWithPoly(Polynomial.Castagnoli); + const Crc32Castagnoli = Crc32SmallWithPoly(.Castagnoli); testing.expect(Crc32Castagnoli.hash("") == 0x00000000); testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330); diff --git a/lib/std/http/headers.zig b/lib/std/http/headers.zig index b1d047aeec..dfe53fe750 100644 --- a/lib/std/http/headers.zig +++ b/lib/std/http/headers.zig @@ -172,7 +172,7 @@ pub const Headers = struct { var dex = HeaderIndexList.init(self.allocator); try dex.append(n - 1); errdefer dex.deinit(); - _ = try self.index.put(name, dex); + _ = try self.index.put(name_dup, dex); } self.data.appendAssumeCapacity(entry); } diff --git a/lib/std/io/out_stream.zig b/lib/std/io/out_stream.zig index b8f5db6fff..265be066a1 100644 --- a/lib/std/io/out_stream.zig +++ b/lib/std/io/out_stream.zig @@ -45,10 +45,14 @@ pub fn OutStream(comptime WriteError: type) type { } pub fn writeByteNTimes(self: *Self, byte: u8, n: usize) Error!void { - const slice = @as(*const [1]u8, &byte)[0..]; - var i: usize = 0; - while (i < n) : (i += 1) { - try self.writeFn(self, slice); + var bytes: [256]u8 = undefined; + mem.set(u8, bytes[0..], byte); + + var remaining: usize = n; + while (remaining > 0) { + const to_write = std.math.min(remaining, bytes.len); + try self.writeFn(self, bytes[0..to_write]); + remaining -= to_write; } } diff --git a/lib/std/io/test.zig b/lib/std/io/test.zig index 92259fd6e9..21ebd723c4 100644 --- a/lib/std/io/test.zig +++ b/lib/std/io/test.zig @@ -547,6 +547,10 @@ fn testSerializerDeserializer(comptime endian: builtin.Endian, comptime packing: } test "Serializer/Deserializer generic" { + if (std.Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } try testSerializerDeserializer(builtin.Endian.Big, .Byte); try testSerializerDeserializer(builtin.Endian.Little, .Byte); try testSerializerDeserializer(builtin.Endian.Big, .Bit); diff --git a/lib/std/math/fabs.zig b/lib/std/math/fabs.zig index a659e35ca2..61692283e6 100644 --- a/lib/std/math/fabs.zig +++ b/lib/std/math/fabs.zig @@ -95,6 +95,10 @@ test "math.fabs64.special" { } test "math.fabs128.special" { + if (std.Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } expect(math.isPositiveInf(fabs(math.inf(f128)))); expect(math.isPositiveInf(fabs(-math.inf(f128)))); expect(math.isNan(fabs(math.nan(f128)))); diff --git a/lib/std/math/isinf.zig b/lib/std/math/isinf.zig index 6eacab52ad..eeac61915c 100644 --- a/lib/std/math/isinf.zig +++ b/lib/std/math/isinf.zig @@ -74,6 +74,10 @@ pub fn isNegativeInf(x: var) bool { } test "math.isInf" { + if (std.Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } expect(!isInf(@as(f16, 0.0))); expect(!isInf(@as(f16, -0.0))); expect(!isInf(@as(f32, 0.0))); @@ -93,6 +97,10 @@ test "math.isInf" { } test "math.isPositiveInf" { + if (std.Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } expect(!isPositiveInf(@as(f16, 0.0))); expect(!isPositiveInf(@as(f16, -0.0))); expect(!isPositiveInf(@as(f32, 0.0))); @@ -112,6 +120,10 @@ test "math.isPositiveInf" { } test "math.isNegativeInf" { + if (std.Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } expect(!isNegativeInf(@as(f16, 0.0))); expect(!isNegativeInf(@as(f16, -0.0))); expect(!isNegativeInf(@as(f32, 0.0))); diff --git a/lib/std/math/isnan.zig b/lib/std/math/isnan.zig index ac865f0d0c..4b7e69490a 100644 --- a/lib/std/math/isnan.zig +++ b/lib/std/math/isnan.zig @@ -16,6 +16,10 @@ pub fn isSignalNan(x: var) bool { } test "math.isNan" { + if (std.Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } expect(isNan(math.nan(f16))); expect(isNan(math.nan(f32))); expect(isNan(math.nan(f64))); diff --git a/lib/std/mem.zig b/lib/std/mem.zig index f7b2bf261d..46f23c84fe 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -175,6 +175,7 @@ pub const Allocator = struct { const old_byte_slice = @sliceToBytes(old_mem); const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return Error.OutOfMemory; + // Note: can't set shrunk memory to undefined as memory shouldn't be modified on realloc failure const byte_slice = try self.reallocFn(self, old_byte_slice, Slice.alignment, byte_count, new_alignment); assert(byte_slice.len == byte_count); if (new_n > old_mem.len) { @@ -221,6 +222,7 @@ pub const Allocator = struct { const byte_count = @sizeOf(T) * new_n; const old_byte_slice = @sliceToBytes(old_mem); + @memset(old_byte_slice.ptr + byte_count, undefined, old_byte_slice.len - byte_count); const byte_slice = self.shrinkFn(self, old_byte_slice, Slice.alignment, byte_count, new_alignment); assert(byte_slice.len == byte_count); return @bytesToSlice(T, @alignCast(new_alignment, byte_slice)); @@ -234,6 +236,7 @@ pub const Allocator = struct { const bytes_len = bytes.len + @boolToInt(Slice.sentinel != null); if (bytes_len == 0) return; const non_const_ptr = @intToPtr([*]u8, @ptrToInt(bytes.ptr)); + @memset(non_const_ptr, undefined, bytes_len); const shrink_result = self.shrinkFn(self, non_const_ptr[0..bytes_len], Slice.alignment, 0, 1); assert(shrink_result.len == 0); } diff --git a/lib/std/meta.zig b/lib/std/meta.zig index 5e5850e393..5cb9c6589c 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -556,3 +556,21 @@ pub fn refAllDecls(comptime T: type) void { if (!builtin.is_test) return; _ = declarations(T); } + +/// Returns a slice of pointers to public declarations of a namespace. +pub fn declList(comptime Namespace: type, comptime Decl: type) []const *const Decl { + const S = struct { + fn declNameLessThan(lhs: *const Decl, rhs: *const Decl) bool { + return mem.lessThan(u8, lhs.name, rhs.name); + } + }; + comptime { + const decls = declarations(Namespace); + var array: [decls.len]*const Decl = undefined; + for (decls) |decl, i| { + array[i] = &@field(Namespace, decl.name); + } + std.sort.sort(*const Decl, &array, S.declNameLessThan); + return &array; + } +} diff --git a/lib/std/net.zig b/lib/std/net.zig index 47ce95c99f..c113462855 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -452,18 +452,18 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !* }; var res: *os.addrinfo = undefined; switch (os.system.getaddrinfo(name_c.ptr, @ptrCast([*:0]const u8, port_c.ptr), &hints, &res)) { - 0 => {}, - c.EAI_ADDRFAMILY => return error.HostLacksNetworkAddresses, - c.EAI_AGAIN => return error.TemporaryNameServerFailure, - c.EAI_BADFLAGS => unreachable, // Invalid hints - c.EAI_FAIL => return error.NameServerFailure, - c.EAI_FAMILY => return error.AddressFamilyNotSupported, - c.EAI_MEMORY => return error.OutOfMemory, - c.EAI_NODATA => return error.HostLacksNetworkAddresses, - c.EAI_NONAME => return error.UnknownHostName, - c.EAI_SERVICE => return error.ServiceUnavailable, - c.EAI_SOCKTYPE => unreachable, // Invalid socket type requested in hints - c.EAI_SYSTEM => switch (os.errno(-1)) { + @intToEnum(os.system.EAI, 0) => {}, + .ADDRFAMILY => return error.HostLacksNetworkAddresses, + .AGAIN => return error.TemporaryNameServerFailure, + .BADFLAGS => unreachable, // Invalid hints + .FAIL => return error.NameServerFailure, + .FAMILY => return error.AddressFamilyNotSupported, + .MEMORY => return error.OutOfMemory, + .NODATA => return error.HostLacksNetworkAddresses, + .NONAME => return error.UnknownHostName, + .SERVICE => return error.ServiceUnavailable, + .SOCKTYPE => unreachable, // Invalid socket type requested in hints + .SYSTEM => switch (os.errno(-1)) { else => |e| return os.unexpectedErrno(e), }, else => unreachable, diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig index 51ea49005e..f4024e1f1d 100644 --- a/lib/std/os/bits/linux.zig +++ b/lib/std/os/bits/linux.zig @@ -18,7 +18,7 @@ pub usingnamespace switch (builtin.arch) { else => struct {}, }; -const is_mips = builtin.arch == .mipsel; +const is_mips = builtin.arch.isMIPS(); pub const pid_t = i32; pub const fd_t = i32; diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index efb1e5fe04..5dbdafb60a 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -211,7 +211,7 @@ pub fn initTLS() ?*elf.Phdr { if (tls_phdr) |phdr| { // If the cpu is arm-based, check if it supports the TLS register - if (builtin.arch == builtin.Arch.arm and at_hwcap & std.os.linux.HWCAP_TLS == 0) { + if (builtin.arch == .arm and at_hwcap & std.os.linux.HWCAP_TLS == 0) { // If the CPU does not support TLS via a coprocessor register, // a kernel helper function can be used instead on certain linux kernels. // See linux/arch/arm/include/asm/tls.h and musl/src/thread/arm/__set_thread_area.c. diff --git a/lib/std/special/compiler_rt.zig b/lib/std/special/compiler_rt.zig index cf255804aa..f5e83b5278 100644 --- a/lib/std/special/compiler_rt.zig +++ b/lib/std/special/compiler_rt.zig @@ -16,42 +16,42 @@ comptime { else => {}, } - @export(@import("compiler_rt/comparesf2.zig").__lesf2, .{ .name = "__lesf2", .linkage = linkage }); - @export(@import("compiler_rt/comparedf2.zig").__ledf2, .{ .name = "__ledf2", .linkage = linkage }); - @export(@import("compiler_rt/comparetf2.zig").__letf2, .{ .name = "__letf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__lesf2, .{ .name = "__lesf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__ledf2, .{ .name = "__ledf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__letf2, .{ .name = "__letf2", .linkage = linkage }); - @export(@import("compiler_rt/comparesf2.zig").__gesf2, .{ .name = "__gesf2", .linkage = linkage }); - @export(@import("compiler_rt/comparedf2.zig").__gedf2, .{ .name = "__gedf2", .linkage = linkage }); - @export(@import("compiler_rt/comparetf2.zig").__getf2, .{ .name = "__getf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__gesf2, .{ .name = "__gesf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__gedf2, .{ .name = "__gedf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__getf2, .{ .name = "__getf2", .linkage = linkage }); if (!is_test) { - @export(@import("compiler_rt/comparesf2.zig").__lesf2, .{ .name = "__cmpsf2", .linkage = linkage }); - @export(@import("compiler_rt/comparedf2.zig").__ledf2, .{ .name = "__cmpdf2", .linkage = linkage }); - @export(@import("compiler_rt/comparetf2.zig").__letf2, .{ .name = "__cmptf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__lesf2, .{ .name = "__cmpsf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__ledf2, .{ .name = "__cmpdf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__letf2, .{ .name = "__cmptf2", .linkage = linkage }); - @export(@import("compiler_rt/comparesf2.zig").__eqsf2, .{ .name = "__eqsf2", .linkage = linkage }); - @export(@import("compiler_rt/comparedf2.zig").__eqdf2, .{ .name = "__eqdf2", .linkage = linkage }); - @export(@import("compiler_rt/comparetf2.zig").__letf2, .{ .name = "__eqtf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__eqsf2, .{ .name = "__eqsf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__eqdf2, .{ .name = "__eqdf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__letf2, .{ .name = "__eqtf2", .linkage = linkage }); - @export(@import("compiler_rt/comparesf2.zig").__ltsf2, .{ .name = "__ltsf2", .linkage = linkage }); - @export(@import("compiler_rt/comparedf2.zig").__ltdf2, .{ .name = "__ltdf2", .linkage = linkage }); - @export(@import("compiler_rt/comparetf2.zig").__letf2, .{ .name = "__lttf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__ltsf2, .{ .name = "__ltsf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__ltdf2, .{ .name = "__ltdf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__letf2, .{ .name = "__lttf2", .linkage = linkage }); - @export(@import("compiler_rt/comparesf2.zig").__nesf2, .{ .name = "__nesf2", .linkage = linkage }); - @export(@import("compiler_rt/comparedf2.zig").__nedf2, .{ .name = "__nedf2", .linkage = linkage }); - @export(@import("compiler_rt/comparetf2.zig").__letf2, .{ .name = "__netf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__nesf2, .{ .name = "__nesf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__nedf2, .{ .name = "__nedf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__letf2, .{ .name = "__netf2", .linkage = linkage }); - @export(@import("compiler_rt/comparesf2.zig").__gtsf2, .{ .name = "__gtsf2", .linkage = linkage }); - @export(@import("compiler_rt/comparedf2.zig").__gtdf2, .{ .name = "__gtdf2", .linkage = linkage }); - @export(@import("compiler_rt/comparetf2.zig").__getf2, .{ .name = "__gttf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__gtsf2, .{ .name = "__gtsf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__gtdf2, .{ .name = "__gtdf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__getf2, .{ .name = "__gttf2", .linkage = linkage }); @export(@import("compiler_rt/extendXfYf2.zig").__extendhfsf2, .{ .name = "__gnu_h2f_ieee", .linkage = linkage }); @export(@import("compiler_rt/truncXfYf2.zig").__truncsfhf2, .{ .name = "__gnu_f2h_ieee", .linkage = linkage }); } - @export(@import("compiler_rt/comparesf2.zig").__unordsf2, .{ .name = "__unordsf2", .linkage = linkage }); - @export(@import("compiler_rt/comparedf2.zig").__unorddf2, .{ .name = "__unorddf2", .linkage = linkage }); - @export(@import("compiler_rt/comparetf2.zig").__unordtf2, .{ .name = "__unordtf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__unordsf2, .{ .name = "__unordsf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__unorddf2, .{ .name = "__unorddf2", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__unordtf2, .{ .name = "__unordtf2", .linkage = linkage }); @export(@import("compiler_rt/addXf3.zig").__addsf3, .{ .name = "__addsf3", .linkage = linkage }); @export(@import("compiler_rt/addXf3.zig").__adddf3, .{ .name = "__adddf3", .linkage = linkage }); @@ -130,6 +130,7 @@ comptime { @export(@import("compiler_rt/int.zig").__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = linkage }); @export(@import("compiler_rt/popcountdi2.zig").__popcountdi2, .{ .name = "__popcountdi2", .linkage = linkage }); + @export(@import("compiler_rt/int.zig").__mulsi3, .{ .name = "__mulsi3", .linkage = linkage }); @export(@import("compiler_rt/muldi3.zig").__muldi3, .{ .name = "__muldi3", .linkage = linkage }); @export(@import("compiler_rt/int.zig").__divmoddi4, .{ .name = "__divmoddi4", .linkage = linkage }); @export(@import("compiler_rt/int.zig").__divsi3, .{ .name = "__divsi3", .linkage = linkage }); @@ -146,7 +147,9 @@ comptime { @export(@import("compiler_rt/negXf2.zig").__negsf2, .{ .name = "__negsf2", .linkage = linkage }); @export(@import("compiler_rt/negXf2.zig").__negdf2, .{ .name = "__negdf2", .linkage = linkage }); - if (is_arm_arch and !is_arm_64 and !is_test) { + @export(@import("compiler_rt/clzsi2.zig").__clzsi2, .{ .name = "__clzsi2", .linkage = linkage }); + + if (builtin.arch.isARM() and !is_test) { @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = linkage }); @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = linkage }); @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = linkage }); @@ -177,7 +180,9 @@ comptime { @export(@import("compiler_rt/arm.zig").__aeabi_memclr, .{ .name = "__aeabi_memclr4", .linkage = linkage }); @export(@import("compiler_rt/arm.zig").__aeabi_memclr, .{ .name = "__aeabi_memclr8", .linkage = linkage }); - @export(@import("compiler_rt/arm.zig").__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = linkage }); + if (builtin.os == .linux) { + @export(@import("compiler_rt/arm.zig").__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = linkage }); + } @export(@import("compiler_rt/extendXfYf2.zig").__aeabi_f2d, .{ .name = "__aeabi_f2d", .linkage = linkage }); @export(@import("compiler_rt/floatsiXf.zig").__aeabi_i2d, .{ .name = "__aeabi_i2d", .linkage = linkage }); @@ -222,20 +227,29 @@ comptime { @export(@import("compiler_rt/divsf3.zig").__aeabi_fdiv, .{ .name = "__aeabi_fdiv", .linkage = linkage }); @export(@import("compiler_rt/divdf3.zig").__aeabi_ddiv, .{ .name = "__aeabi_ddiv", .linkage = linkage }); - @export(@import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmpeq, .{ .name = "__aeabi_fcmpeq", .linkage = linkage }); - @export(@import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmplt, .{ .name = "__aeabi_fcmplt", .linkage = linkage }); - @export(@import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmple, .{ .name = "__aeabi_fcmple", .linkage = linkage }); - @export(@import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmpge, .{ .name = "__aeabi_fcmpge", .linkage = linkage }); - @export(@import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmpgt, .{ .name = "__aeabi_fcmpgt", .linkage = linkage }); - @export(@import("compiler_rt/comparesf2.zig").__aeabi_fcmpun, .{ .name = "__aeabi_fcmpun", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmpeq, .{ .name = "__aeabi_fcmpeq", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmplt, .{ .name = "__aeabi_fcmplt", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmple, .{ .name = "__aeabi_fcmple", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmpge, .{ .name = "__aeabi_fcmpge", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmpgt, .{ .name = "__aeabi_fcmpgt", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmpun, .{ .name = "__aeabi_fcmpun", .linkage = linkage }); - @export(@import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmpeq, .{ .name = "__aeabi_dcmpeq", .linkage = linkage }); - @export(@import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmplt, .{ .name = "__aeabi_dcmplt", .linkage = linkage }); - @export(@import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmple, .{ .name = "__aeabi_dcmple", .linkage = linkage }); - @export(@import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmpge, .{ .name = "__aeabi_dcmpge", .linkage = linkage }); - @export(@import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmpgt, .{ .name = "__aeabi_dcmpgt", .linkage = linkage }); - @export(@import("compiler_rt/comparedf2.zig").__aeabi_dcmpun, .{ .name = "__aeabi_dcmpun", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmpeq, .{ .name = "__aeabi_dcmpeq", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmplt, .{ .name = "__aeabi_dcmplt", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmple, .{ .name = "__aeabi_dcmple", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmpge, .{ .name = "__aeabi_dcmpge", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmpgt, .{ .name = "__aeabi_dcmpgt", .linkage = linkage }); + @export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmpun, .{ .name = "__aeabi_dcmpun", .linkage = linkage }); } + + if (builtin.arch == .i386 and builtin.abi == .msvc) { + // Don't let LLVM apply the stdcall name mangling on those MSVC builtins + @export(@import("compiler_rt/aulldiv.zig")._alldiv, .{ .name = "\x01__alldiv", .linkage = strong_linkage }); + @export(@import("compiler_rt/aulldiv.zig")._aulldiv, .{ .name = "\x01__aulldiv", .linkage = strong_linkage }); + @export(@import("compiler_rt/aullrem.zig")._allrem, .{ .name = "\x01__allrem", .linkage = strong_linkage }); + @export(@import("compiler_rt/aullrem.zig")._aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage }); + } + if (builtin.os == .windows) { // Default stack-probe functions emitted by LLVM if (is_mingw) { @@ -254,13 +268,6 @@ comptime { switch (builtin.arch) { .i386 => { - // Don't let LLVM apply the stdcall name mangling on those MSVC - // builtin functions - @export(@import("compiler_rt/aulldiv.zig")._alldiv, .{ .name = "\x01__alldiv", .linkage = strong_linkage }); - @export(@import("compiler_rt/aulldiv.zig")._aulldiv, .{ .name = "\x01__aulldiv", .linkage = strong_linkage }); - @export(@import("compiler_rt/aullrem.zig")._allrem, .{ .name = "\x01__allrem", .linkage = strong_linkage }); - @export(@import("compiler_rt/aullrem.zig")._aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage }); - @export(@import("compiler_rt/divti3.zig").__divti3, .{ .name = "__divti3", .linkage = linkage }); @export(@import("compiler_rt/modti3.zig").__modti3, .{ .name = "__modti3", .linkage = linkage }); @export(@import("compiler_rt/multi3.zig").__multi3, .{ .name = "__multi3", .linkage = linkage }); @@ -295,16 +302,12 @@ comptime { @export(@import("compiler_rt/mulodi4.zig").__mulodi4, .{ .name = "__mulodi4", .linkage = linkage }); } -const std = @import("std"); -const assert = std.debug.assert; -const testing = std.testing; - // Avoid dragging in the runtime safety mechanisms into this .o file, // unless we're trying to test this file. pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn { @setCold(true); if (is_test) { - std.debug.panic("{}", .{msg}); + @import("std").debug.panic("{}", .{msg}); } else { unreachable; } @@ -320,23 +323,3 @@ extern var __stack_chk_guard: usize = blk: { buf[@sizeOf(usize) - 2] = '\n'; break :blk @bitCast(usize, buf); }; - -const is_arm_64 = switch (builtin.arch) { - builtin.Arch.aarch64, - builtin.Arch.aarch64_be, - => true, - else => false, -}; - -const is_arm_arch = switch (builtin.arch) { - builtin.Arch.arm, - builtin.Arch.armeb, - builtin.Arch.aarch64, - builtin.Arch.aarch64_be, - builtin.Arch.thumb, - builtin.Arch.thumbeb, - => true, - else => false, -}; - -const is_arm_32 = is_arm_arch and !is_arm_64; diff --git a/lib/std/special/compiler_rt/addXf3_test.zig b/lib/std/special/compiler_rt/addXf3_test.zig index af991b37e9..402bb5a43c 100644 --- a/lib/std/special/compiler_rt/addXf3_test.zig +++ b/lib/std/special/compiler_rt/addXf3_test.zig @@ -31,6 +31,10 @@ fn test__addtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) void { } test "addtf3" { + if (@import("std").Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } test__addtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); // NaN + any = NaN @@ -71,6 +75,10 @@ fn test__subtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) void { } test "subtf3" { + if (@import("std").Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } // qNaN - any = qNaN test__subtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); diff --git a/lib/std/special/compiler_rt/arm/aeabi_dcmp.zig b/lib/std/special/compiler_rt/arm/aeabi_dcmp.zig deleted file mode 100644 index a8ed182901..0000000000 --- a/lib/std/special/compiler_rt/arm/aeabi_dcmp.zig +++ /dev/null @@ -1,95 +0,0 @@ -// Ported from: -// -// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/arm/aeabi_dcmp.S - -const ConditionalOperator = enum { - Eq, - Lt, - Le, - Ge, - Gt, -}; - -pub fn __aeabi_dcmpeq() callconv(.Naked) noreturn { - @setRuntimeSafety(false); - @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Eq}); - unreachable; -} - -pub fn __aeabi_dcmplt() callconv(.Naked) noreturn { - @setRuntimeSafety(false); - @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Lt}); - unreachable; -} - -pub fn __aeabi_dcmple() callconv(.Naked) noreturn { - @setRuntimeSafety(false); - @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Le}); - unreachable; -} - -pub fn __aeabi_dcmpge() callconv(.Naked) noreturn { - @setRuntimeSafety(false); - @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Ge}); - unreachable; -} - -pub fn __aeabi_dcmpgt() callconv(.Naked) noreturn { - @setRuntimeSafety(false); - @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Gt}); - unreachable; -} - -fn aeabi_dcmp(comptime cond: ConditionalOperator) void { - @setRuntimeSafety(false); - asm volatile ( - \\ push { r4, lr } - ); - - switch (cond) { - .Eq => asm volatile ( - \\ bl __eqdf2 - \\ cmp r0, #0 - \\ beq 1f - \\ movs r0, #0 - \\ pop { r4, pc } - \\ 1: - ), - .Lt => asm volatile ( - \\ bl __ltdf2 - \\ cmp r0, #0 - \\ blt 1f - \\ movs r0, #0 - \\ pop { r4, pc } - \\ 1: - ), - .Le => asm volatile ( - \\ bl __ledf2 - \\ cmp r0, #0 - \\ ble 1f - \\ movs r0, #0 - \\ pop { r4, pc } - \\ 1: - ), - .Ge => asm volatile ( - \\ bl __ltdf2 - \\ cmp r0, #0 - \\ bge 1f - \\ movs r0, #0 - \\ pop { r4, pc } - \\ 1: - ), - .Gt => asm volatile ( - \\ bl __gtdf2 - \\ cmp r0, #0 - \\ bgt 1f - \\ movs r0, #0 - \\ pop { r4, pc } - \\ 1: - ), - } - asm volatile ( - \\ movs r0, #1 - \\ pop { r4, pc } - ); -} diff --git a/lib/std/special/compiler_rt/arm/aeabi_fcmp.zig b/lib/std/special/compiler_rt/arm/aeabi_fcmp.zig deleted file mode 100644 index 0b4c0f0d41..0000000000 --- a/lib/std/special/compiler_rt/arm/aeabi_fcmp.zig +++ /dev/null @@ -1,95 +0,0 @@ -// Ported from: -// -// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/arm/aeabi_fcmp.S - -const ConditionalOperator = enum { - Eq, - Lt, - Le, - Ge, - Gt, -}; - -pub fn __aeabi_fcmpeq() callconv(.Naked) noreturn { - @setRuntimeSafety(false); - @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Eq}); - unreachable; -} - -pub fn __aeabi_fcmplt() callconv(.Naked) noreturn { - @setRuntimeSafety(false); - @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Lt}); - unreachable; -} - -pub fn __aeabi_fcmple() callconv(.Naked) noreturn { - @setRuntimeSafety(false); - @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Le}); - unreachable; -} - -pub fn __aeabi_fcmpge() callconv(.Naked) noreturn { - @setRuntimeSafety(false); - @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Ge}); - unreachable; -} - -pub fn __aeabi_fcmpgt() callconv(.Naked) noreturn { - @setRuntimeSafety(false); - @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Gt}); - unreachable; -} - -fn aeabi_fcmp(comptime cond: ConditionalOperator) void { - @setRuntimeSafety(false); - asm volatile ( - \\ push { r4, lr } - ); - - switch (cond) { - .Eq => asm volatile ( - \\ bl __eqsf2 - \\ cmp r0, #0 - \\ beq 1f - \\ movs r0, #0 - \\ pop { r4, pc } - \\ 1: - ), - .Lt => asm volatile ( - \\ bl __ltsf2 - \\ cmp r0, #0 - \\ blt 1f - \\ movs r0, #0 - \\ pop { r4, pc } - \\ 1: - ), - .Le => asm volatile ( - \\ bl __lesf2 - \\ cmp r0, #0 - \\ ble 1f - \\ movs r0, #0 - \\ pop { r4, pc } - \\ 1: - ), - .Ge => asm volatile ( - \\ bl __ltsf2 - \\ cmp r0, #0 - \\ bge 1f - \\ movs r0, #0 - \\ pop { r4, pc } - \\ 1: - ), - .Gt => asm volatile ( - \\ bl __gtsf2 - \\ cmp r0, #0 - \\ bgt 1f - \\ movs r0, #0 - \\ pop { r4, pc } - \\ 1: - ), - } - asm volatile ( - \\ movs r0, #1 - \\ pop { r4, pc } - ); -} diff --git a/lib/std/special/compiler_rt/clzsi2.zig b/lib/std/special/compiler_rt/clzsi2.zig new file mode 100644 index 0000000000..6a69ae75f1 --- /dev/null +++ b/lib/std/special/compiler_rt/clzsi2.zig @@ -0,0 +1,116 @@ +const builtin = @import("builtin"); + +fn __clzsi2_generic(a: i32) callconv(.C) i32 { + @setRuntimeSafety(builtin.is_test); + + var x = @bitCast(u32, a); + var n: i32 = 32; + + // Count first bit set using binary search, from Hacker's Delight + var y: u32 = 0; + inline for ([_]i32{ 16, 8, 4, 2, 1 }) |shift| { + y = x >> shift; + if (y != 0) { + n = n - shift; + x = y; + } + } + + return n - @bitCast(i32, x); +} + +fn __clzsi2_thumb1() callconv(.Naked) void { + @setRuntimeSafety(builtin.is_test); + + // Similar to the generic version with the last two rounds replaced by a LUT + asm volatile ( + \\ movs r1, #32 + \\ lsrs r2, r0, #16 + \\ beq 1f + \\ subs r1, #16 + \\ movs r0, r2 + \\ 1: + \\ lsrs r2, r0, #8 + \\ beq 1f + \\ subs r1, #8 + \\ movs r0, r2 + \\ 1: + \\ lsrs r2, r0, #4 + \\ beq 1f + \\ subs r1, #4 + \\ movs r0, r2 + \\ 1: + \\ ldr r3, =LUT + \\ ldrb r0, [r3, r0] + \\ subs r0, r1, r0 + \\ bx lr + \\ .p2align 2 + \\ LUT: + \\ .byte 4,3,2,2,1,1,1,1,0,0,0,0,0,0,0,0 + ); + + unreachable; +} + +fn __clzsi2_arm32() callconv(.Naked) void { + @setRuntimeSafety(builtin.is_test); + + asm volatile ( + \\ // Assumption: n != 0 + \\ // r0: n + \\ // r1: count of leading zeros in n + 1 + \\ // r2: scratch register for shifted r0 + \\ mov r1, #1 + \\ + \\ // Basic block: + \\ // if ((r0 >> SHIFT) == 0) + \\ // r1 += SHIFT; + \\ // else + \\ // r0 >>= SHIFT; + \\ // for descending powers of two as SHIFT. + \\ lsrs r2, r0, #16 + \\ movne r0, r2 + \\ addeq r1, #16 + \\ + \\ lsrs r2, r0, #8 + \\ movne r0, r2 + \\ addeq r1, #8 + \\ + \\ lsrs r2, r0, #4 + \\ movne r0, r2 + \\ addeq r1, #4 + \\ + \\ lsrs r2, r0, #2 + \\ movne r0, r2 + \\ addeq r1, #2 + \\ + \\ // The basic block invariants at this point are (r0 >> 2) == 0 and + \\ // r0 != 0. This means 1 <= r0 <= 3 and 0 <= (r0 >> 1) <= 1. + \\ // + \\ // r0 | (r0 >> 1) == 0 | (r0 >> 1) == 1 | -(r0 >> 1) | 1 - (r0 >> 1)f + \\ // ---+----------------+----------------+------------+-------------- + \\ // 1 | 1 | 0 | 0 | 1 + \\ // 2 | 0 | 1 | -1 | 0 + \\ // 3 | 0 | 1 | -1 | 0 + \\ // + \\ // The r1's initial value of 1 compensates for the 1 here. + \\ sub r0, r1, r0, lsr #1 + \\ bx lr + ); + + unreachable; +} + +pub const __clzsi2 = blk: { + if (builtin.arch.isARM()) { + break :blk __clzsi2_arm32; + } else if (builtin.arch.isThumb()) { + break :blk __clzsi2_thumb1; + } else { + break :blk __clzsi2_generic; + } +}; + +test "test clzsi2" { + _ = @import("clzsi2_test.zig"); +} diff --git a/lib/std/special/compiler_rt/clzsi2_test.zig b/lib/std/special/compiler_rt/clzsi2_test.zig new file mode 100644 index 0000000000..ff94455846 --- /dev/null +++ b/lib/std/special/compiler_rt/clzsi2_test.zig @@ -0,0 +1,292 @@ +const clzsi2 = @import("clzsi2.zig"); +const testing = @import("std").testing; + +fn test__clzsi2(a: u32, expected: i32) void { + var nakedClzsi2 = clzsi2.__clzsi2; + var actualClzsi2 = @ptrCast(fn (a: i32) callconv(.C) i32, nakedClzsi2); + var x = @intCast(i32, a); + var result = actualClzsi2(x); + testing.expectEqual(expected, result); +} + +test "clzsi2" { + test__clzsi2(0x00800000, 8); + test__clzsi2(0x01000000, 7); + test__clzsi2(0x02000000, 6); + test__clzsi2(0x03000000, 6); + test__clzsi2(0x04000000, 5); + test__clzsi2(0x05000000, 5); + test__clzsi2(0x06000000, 5); + test__clzsi2(0x07000000, 5); + test__clzsi2(0x08000000, 4); + test__clzsi2(0x09000000, 4); + test__clzsi2(0x0A000000, 4); + test__clzsi2(0x0B000000, 4); + test__clzsi2(0x0C000000, 4); + test__clzsi2(0x0D000000, 4); + test__clzsi2(0x0E000000, 4); + test__clzsi2(0x0F000000, 4); + test__clzsi2(0x10000000, 3); + test__clzsi2(0x11000000, 3); + test__clzsi2(0x12000000, 3); + test__clzsi2(0x13000000, 3); + test__clzsi2(0x14000000, 3); + test__clzsi2(0x15000000, 3); + test__clzsi2(0x16000000, 3); + test__clzsi2(0x17000000, 3); + test__clzsi2(0x18000000, 3); + test__clzsi2(0x19000000, 3); + test__clzsi2(0x1A000000, 3); + test__clzsi2(0x1B000000, 3); + test__clzsi2(0x1C000000, 3); + test__clzsi2(0x1D000000, 3); + test__clzsi2(0x1E000000, 3); + test__clzsi2(0x1F000000, 3); + test__clzsi2(0x20000000, 2); + test__clzsi2(0x21000000, 2); + test__clzsi2(0x22000000, 2); + test__clzsi2(0x23000000, 2); + test__clzsi2(0x24000000, 2); + test__clzsi2(0x25000000, 2); + test__clzsi2(0x26000000, 2); + test__clzsi2(0x27000000, 2); + test__clzsi2(0x28000000, 2); + test__clzsi2(0x29000000, 2); + test__clzsi2(0x2A000000, 2); + test__clzsi2(0x2B000000, 2); + test__clzsi2(0x2C000000, 2); + test__clzsi2(0x2D000000, 2); + test__clzsi2(0x2E000000, 2); + test__clzsi2(0x2F000000, 2); + test__clzsi2(0x30000000, 2); + test__clzsi2(0x31000000, 2); + test__clzsi2(0x32000000, 2); + test__clzsi2(0x33000000, 2); + test__clzsi2(0x34000000, 2); + test__clzsi2(0x35000000, 2); + test__clzsi2(0x36000000, 2); + test__clzsi2(0x37000000, 2); + test__clzsi2(0x38000000, 2); + test__clzsi2(0x39000000, 2); + test__clzsi2(0x3A000000, 2); + test__clzsi2(0x3B000000, 2); + test__clzsi2(0x3C000000, 2); + test__clzsi2(0x3D000000, 2); + test__clzsi2(0x3E000000, 2); + test__clzsi2(0x3F000000, 2); + test__clzsi2(0x40000000, 1); + test__clzsi2(0x41000000, 1); + test__clzsi2(0x42000000, 1); + test__clzsi2(0x43000000, 1); + test__clzsi2(0x44000000, 1); + test__clzsi2(0x45000000, 1); + test__clzsi2(0x46000000, 1); + test__clzsi2(0x47000000, 1); + test__clzsi2(0x48000000, 1); + test__clzsi2(0x49000000, 1); + test__clzsi2(0x4A000000, 1); + test__clzsi2(0x4B000000, 1); + test__clzsi2(0x4C000000, 1); + test__clzsi2(0x4D000000, 1); + test__clzsi2(0x4E000000, 1); + test__clzsi2(0x4F000000, 1); + test__clzsi2(0x50000000, 1); + test__clzsi2(0x51000000, 1); + test__clzsi2(0x52000000, 1); + test__clzsi2(0x53000000, 1); + test__clzsi2(0x54000000, 1); + test__clzsi2(0x55000000, 1); + test__clzsi2(0x56000000, 1); + test__clzsi2(0x57000000, 1); + test__clzsi2(0x58000000, 1); + test__clzsi2(0x59000000, 1); + test__clzsi2(0x5A000000, 1); + test__clzsi2(0x5B000000, 1); + test__clzsi2(0x5C000000, 1); + test__clzsi2(0x5D000000, 1); + test__clzsi2(0x5E000000, 1); + test__clzsi2(0x5F000000, 1); + test__clzsi2(0x60000000, 1); + test__clzsi2(0x61000000, 1); + test__clzsi2(0x62000000, 1); + test__clzsi2(0x63000000, 1); + test__clzsi2(0x64000000, 1); + test__clzsi2(0x65000000, 1); + test__clzsi2(0x66000000, 1); + test__clzsi2(0x67000000, 1); + test__clzsi2(0x68000000, 1); + test__clzsi2(0x69000000, 1); + test__clzsi2(0x6A000000, 1); + test__clzsi2(0x6B000000, 1); + test__clzsi2(0x6C000000, 1); + test__clzsi2(0x6D000000, 1); + test__clzsi2(0x6E000000, 1); + test__clzsi2(0x6F000000, 1); + test__clzsi2(0x70000000, 1); + test__clzsi2(0x71000000, 1); + test__clzsi2(0x72000000, 1); + test__clzsi2(0x73000000, 1); + test__clzsi2(0x74000000, 1); + test__clzsi2(0x75000000, 1); + test__clzsi2(0x76000000, 1); + test__clzsi2(0x77000000, 1); + test__clzsi2(0x78000000, 1); + test__clzsi2(0x79000000, 1); + test__clzsi2(0x7A000000, 1); + test__clzsi2(0x7B000000, 1); + test__clzsi2(0x7C000000, 1); + test__clzsi2(0x7D000000, 1); + test__clzsi2(0x7E000000, 1); + test__clzsi2(0x7F000000, 1); + test__clzsi2(0x80000000, 0); + test__clzsi2(0x81000000, 0); + test__clzsi2(0x82000000, 0); + test__clzsi2(0x83000000, 0); + test__clzsi2(0x84000000, 0); + test__clzsi2(0x85000000, 0); + test__clzsi2(0x86000000, 0); + test__clzsi2(0x87000000, 0); + test__clzsi2(0x88000000, 0); + test__clzsi2(0x89000000, 0); + test__clzsi2(0x8A000000, 0); + test__clzsi2(0x8B000000, 0); + test__clzsi2(0x8C000000, 0); + test__clzsi2(0x8D000000, 0); + test__clzsi2(0x8E000000, 0); + test__clzsi2(0x8F000000, 0); + test__clzsi2(0x90000000, 0); + test__clzsi2(0x91000000, 0); + test__clzsi2(0x92000000, 0); + test__clzsi2(0x93000000, 0); + test__clzsi2(0x94000000, 0); + test__clzsi2(0x95000000, 0); + test__clzsi2(0x96000000, 0); + test__clzsi2(0x97000000, 0); + test__clzsi2(0x98000000, 0); + test__clzsi2(0x99000000, 0); + test__clzsi2(0x9A000000, 0); + test__clzsi2(0x9B000000, 0); + test__clzsi2(0x9C000000, 0); + test__clzsi2(0x9D000000, 0); + test__clzsi2(0x9E000000, 0); + test__clzsi2(0x9F000000, 0); + test__clzsi2(0xA0000000, 0); + test__clzsi2(0xA1000000, 0); + test__clzsi2(0xA2000000, 0); + test__clzsi2(0xA3000000, 0); + test__clzsi2(0xA4000000, 0); + test__clzsi2(0xA5000000, 0); + test__clzsi2(0xA6000000, 0); + test__clzsi2(0xA7000000, 0); + test__clzsi2(0xA8000000, 0); + test__clzsi2(0xA9000000, 0); + test__clzsi2(0xAA000000, 0); + test__clzsi2(0xAB000000, 0); + test__clzsi2(0xAC000000, 0); + test__clzsi2(0xAD000000, 0); + test__clzsi2(0xAE000000, 0); + test__clzsi2(0xAF000000, 0); + test__clzsi2(0xB0000000, 0); + test__clzsi2(0xB1000000, 0); + test__clzsi2(0xB2000000, 0); + test__clzsi2(0xB3000000, 0); + test__clzsi2(0xB4000000, 0); + test__clzsi2(0xB5000000, 0); + test__clzsi2(0xB6000000, 0); + test__clzsi2(0xB7000000, 0); + test__clzsi2(0xB8000000, 0); + test__clzsi2(0xB9000000, 0); + test__clzsi2(0xBA000000, 0); + test__clzsi2(0xBB000000, 0); + test__clzsi2(0xBC000000, 0); + test__clzsi2(0xBD000000, 0); + test__clzsi2(0xBE000000, 0); + test__clzsi2(0xBF000000, 0); + test__clzsi2(0xC0000000, 0); + test__clzsi2(0xC1000000, 0); + test__clzsi2(0xC2000000, 0); + test__clzsi2(0xC3000000, 0); + test__clzsi2(0xC4000000, 0); + test__clzsi2(0xC5000000, 0); + test__clzsi2(0xC6000000, 0); + test__clzsi2(0xC7000000, 0); + test__clzsi2(0xC8000000, 0); + test__clzsi2(0xC9000000, 0); + test__clzsi2(0xCA000000, 0); + test__clzsi2(0xCB000000, 0); + test__clzsi2(0xCC000000, 0); + test__clzsi2(0xCD000000, 0); + test__clzsi2(0xCE000000, 0); + test__clzsi2(0xCF000000, 0); + test__clzsi2(0xD0000000, 0); + test__clzsi2(0xD1000000, 0); + test__clzsi2(0xD2000000, 0); + test__clzsi2(0xD3000000, 0); + test__clzsi2(0xD4000000, 0); + test__clzsi2(0xD5000000, 0); + test__clzsi2(0xD6000000, 0); + test__clzsi2(0xD7000000, 0); + test__clzsi2(0xD8000000, 0); + test__clzsi2(0xD9000000, 0); + test__clzsi2(0xDA000000, 0); + test__clzsi2(0xDB000000, 0); + test__clzsi2(0xDC000000, 0); + test__clzsi2(0xDD000000, 0); + test__clzsi2(0xDE000000, 0); + test__clzsi2(0xDF000000, 0); + test__clzsi2(0xE0000000, 0); + test__clzsi2(0xE1000000, 0); + test__clzsi2(0xE2000000, 0); + test__clzsi2(0xE3000000, 0); + test__clzsi2(0xE4000000, 0); + test__clzsi2(0xE5000000, 0); + test__clzsi2(0xE6000000, 0); + test__clzsi2(0xE7000000, 0); + test__clzsi2(0xE8000000, 0); + test__clzsi2(0xE9000000, 0); + test__clzsi2(0xEA000000, 0); + test__clzsi2(0xEB000000, 0); + test__clzsi2(0xEC000000, 0); + test__clzsi2(0xED000000, 0); + test__clzsi2(0xEE000000, 0); + test__clzsi2(0xEF000000, 0); + test__clzsi2(0xF0000000, 0); + test__clzsi2(0xF1000000, 0); + test__clzsi2(0xF2000000, 0); + test__clzsi2(0xF3000000, 0); + test__clzsi2(0xF4000000, 0); + test__clzsi2(0xF5000000, 0); + test__clzsi2(0xF6000000, 0); + test__clzsi2(0xF7000000, 0); + test__clzsi2(0xF8000000, 0); + test__clzsi2(0xF9000000, 0); + test__clzsi2(0xFA000000, 0); + test__clzsi2(0xFB000000, 0); + test__clzsi2(0xFC000000, 0); + test__clzsi2(0xFD000000, 0); + test__clzsi2(0xFE000000, 0); + test__clzsi2(0xFF000000, 0); + test__clzsi2(0x00000001, 31); + test__clzsi2(0x00000002, 30); + test__clzsi2(0x00000004, 29); + test__clzsi2(0x00000008, 28); + test__clzsi2(0x00000010, 27); + test__clzsi2(0x00000020, 26); + test__clzsi2(0x00000040, 25); + test__clzsi2(0x00000080, 24); + test__clzsi2(0x00000100, 23); + test__clzsi2(0x00000200, 22); + test__clzsi2(0x00000400, 21); + test__clzsi2(0x00000800, 20); + test__clzsi2(0x00001000, 19); + test__clzsi2(0x00002000, 18); + test__clzsi2(0x00004000, 17); + test__clzsi2(0x00008000, 16); + test__clzsi2(0x00010000, 15); + test__clzsi2(0x00020000, 14); + test__clzsi2(0x00040000, 13); + test__clzsi2(0x00080000, 12); + test__clzsi2(0x00100000, 11); + test__clzsi2(0x00200000, 10); + test__clzsi2(0x00400000, 9); +} diff --git a/lib/std/special/compiler_rt/compareXf2.zig b/lib/std/special/compiler_rt/compareXf2.zig new file mode 100644 index 0000000000..15e49e3cc1 --- /dev/null +++ b/lib/std/special/compiler_rt/compareXf2.zig @@ -0,0 +1,253 @@ +// Ported from: +// +// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/comparesf2.c + +const std = @import("std"); +const builtin = @import("builtin"); + +const LE = extern enum(i32) { + Less = -1, + Equal = 0, + Greater = 1, + Unordered = 1, +}; + +const GE = extern enum(i32) { + Less = -1, + Equal = 0, + Greater = 1, + Unordered = -1, +}; + +pub fn cmp(comptime T: type, comptime RT: type, a: T, b: T) RT { + @setRuntimeSafety(builtin.is_test); + + const srep_t = @IntType(true, T.bit_count); + const rep_t = @IntType(false, T.bit_count); + + const significandBits = std.math.floatMantissaBits(T); + const exponentBits = std.math.floatExponentBits(T); + const signBit = (@as(rep_t, 1) << (significandBits + exponentBits)); + const absMask = signBit - 1; + const infRep = @bitCast(rep_t, std.math.inf(T)); + + const aInt = @bitCast(srep_t, a); + const bInt = @bitCast(srep_t, b); + const aAbs = @bitCast(rep_t, aInt) & absMask; + const bAbs = @bitCast(rep_t, bInt) & absMask; + + // If either a or b is NaN, they are unordered. + if (aAbs > infRep or bAbs > infRep) return .Unordered; + + // If a and b are both zeros, they are equal. + if ((aAbs | bAbs) == 0) return .Equal; + + // If at least one of a and b is positive, we get the same result comparing + // a and b as signed integers as we would with a fp_ting-point compare. + if ((aInt & bInt) >= 0) { + if (aInt < bInt) { + return .Less; + } else if (aInt == bInt) { + return .Equal; + } else return .Greater; + } + + // Otherwise, both are negative, so we need to flip the sense of the + // comparison to get the correct result. (This assumes a twos- or ones- + // complement integer representation; if integers are represented in a + // sign-magnitude representation, then this flip is incorrect). + else { + if (aInt > bInt) { + return .Less; + } else if (aInt == bInt) { + return .Equal; + } else return .Greater; + } +} + +pub fn unordcmp(comptime T: type, a: T, b: T) i32 { + @setRuntimeSafety(builtin.is_test); + + const rep_t = @IntType(false, T.bit_count); + + const significandBits = std.math.floatMantissaBits(T); + const exponentBits = std.math.floatExponentBits(T); + const signBit = (@as(rep_t, 1) << (significandBits + exponentBits)); + const absMask = signBit - 1; + const infRep = @bitCast(rep_t, std.math.inf(T)); + + const aAbs: rep_t = @bitCast(rep_t, a) & absMask; + const bAbs: rep_t = @bitCast(rep_t, b) & absMask; + + return @boolToInt(aAbs > infRep or bAbs > infRep); +} + +// Comparison between f32 + +pub fn __lesf2(a: f32, b: f32) callconv(.C) i32 { + @setRuntimeSafety(builtin.is_test); + return @bitCast(i32, @call(.{ .modifier = .always_inline }, cmp, .{ f32, LE, a, b })); +} + +pub fn __gesf2(a: f32, b: f32) callconv(.C) i32 { + @setRuntimeSafety(builtin.is_test); + return @bitCast(i32, @call(.{ .modifier = .always_inline }, cmp, .{ f32, GE, a, b })); +} + +pub fn __eqsf2(a: f32, b: f32) callconv(.C) i32 { + return __lesf2(a, b); +} + +pub fn __ltsf2(a: f32, b: f32) callconv(.C) i32 { + return __lesf2(a, b); +} + +pub fn __nesf2(a: f32, b: f32) callconv(.C) i32 { + return __lesf2(a, b); +} + +pub fn __gtsf2(a: f32, b: f32) callconv(.C) i32 { + return __gesf2(a, b); +} + +// Comparison between f64 + +pub fn __ledf2(a: f64, b: f64) callconv(.C) i32 { + @setRuntimeSafety(builtin.is_test); + return @bitCast(i32, @call(.{ .modifier = .always_inline }, cmp, .{ f64, LE, a, b })); +} + +pub fn __gedf2(a: f64, b: f64) callconv(.C) i32 { + @setRuntimeSafety(builtin.is_test); + return @bitCast(i32, @call(.{ .modifier = .always_inline }, cmp, .{ f64, GE, a, b })); +} + +pub fn __eqdf2(a: f64, b: f64) callconv(.C) i32 { + return __ledf2(a, b); +} + +pub fn __ltdf2(a: f64, b: f64) callconv(.C) i32 { + return __ledf2(a, b); +} + +pub fn __nedf2(a: f64, b: f64) callconv(.C) i32 { + return __ledf2(a, b); +} + +pub fn __gtdf2(a: f64, b: f64) callconv(.C) i32 { + return __gedf2(a, b); +} + +// Comparison between f128 + +pub fn __letf2(a: f128, b: f128) callconv(.C) i32 { + @setRuntimeSafety(builtin.is_test); + return @bitCast(i32, @call(.{ .modifier = .always_inline }, cmp, .{ f128, LE, a, b })); +} + +pub fn __getf2(a: f128, b: f128) callconv(.C) i32 { + @setRuntimeSafety(builtin.is_test); + return @bitCast(i32, @call(.{ .modifier = .always_inline }, cmp, .{ f128, GE, a, b })); +} + +pub fn __eqtf2(a: f128, b: f128) callconv(.C) i32 { + return __letf2(a, b); +} + +pub fn __lttf2(a: f128, b: f128) callconv(.C) i32 { + return __letf2(a, b); +} + +pub fn __netf2(a: f128, b: f128) callconv(.C) i32 { + return __letf2(a, b); +} + +pub fn __gttf2(a: f128, b: f128) callconv(.C) i32 { + return __getf2(a, b); +} + +// Unordered comparison between f32/f64/f128 + +pub fn __unordsf2(a: f32, b: f32) callconv(.C) i32 { + @setRuntimeSafety(builtin.is_test); + return @call(.{ .modifier = .always_inline }, unordcmp, .{ f32, a, b }); +} + +pub fn __unorddf2(a: f64, b: f64) callconv(.C) i32 { + @setRuntimeSafety(builtin.is_test); + return @call(.{ .modifier = .always_inline }, unordcmp, .{ f64, a, b }); +} + +pub fn __unordtf2(a: f128, b: f128) callconv(.C) i32 { + @setRuntimeSafety(builtin.is_test); + return @call(.{ .modifier = .always_inline }, unordcmp, .{ f128, a, b }); +} + +// ARM EABI intrinsics + +pub fn __aeabi_fcmpeq(a: f32, b: f32) callconv(.AAPCS) i32 { + @setRuntimeSafety(false); + return @boolToInt(@call(.{ .modifier = .always_inline }, __eqsf2, .{ a, b }) == 0); +} + +pub fn __aeabi_fcmplt(a: f32, b: f32) callconv(.AAPCS) i32 { + @setRuntimeSafety(false); + return @boolToInt(@call(.{ .modifier = .always_inline }, __ltsf2, .{ a, b }) < 0); +} + +pub fn __aeabi_fcmple(a: f32, b: f32) callconv(.AAPCS) i32 { + @setRuntimeSafety(false); + return @boolToInt(@call(.{ .modifier = .always_inline }, __lesf2, .{ a, b }) <= 0); +} + +pub fn __aeabi_fcmpge(a: f32, b: f32) callconv(.AAPCS) i32 { + @setRuntimeSafety(false); + return @boolToInt(@call(.{ .modifier = .always_inline }, __gesf2, .{ a, b }) >= 0); +} + +pub fn __aeabi_fcmpgt(a: f32, b: f32) callconv(.AAPCS) i32 { + @setRuntimeSafety(false); + return @boolToInt(@call(.{ .modifier = .always_inline }, __gtsf2, .{ a, b }) > 0); +} + +pub fn __aeabi_fcmpun(a: f32, b: f32) callconv(.AAPCS) i32 { + @setRuntimeSafety(false); + return @call(.{ .modifier = .always_inline }, __unordsf2, .{ a, b }); +} + +pub fn __aeabi_dcmpeq(a: f64, b: f64) callconv(.AAPCS) i32 { + @setRuntimeSafety(false); + return @boolToInt(@call(.{ .modifier = .always_inline }, __eqdf2, .{ a, b }) == 0); +} + +pub fn __aeabi_dcmplt(a: f64, b: f64) callconv(.AAPCS) i32 { + @setRuntimeSafety(false); + return @boolToInt(@call(.{ .modifier = .always_inline }, __ltdf2, .{ a, b }) < 0); +} + +pub fn __aeabi_dcmple(a: f64, b: f64) callconv(.AAPCS) i32 { + @setRuntimeSafety(false); + return @boolToInt(@call(.{ .modifier = .always_inline }, __ledf2, .{ a, b }) <= 0); +} + +pub fn __aeabi_dcmpge(a: f64, b: f64) callconv(.AAPCS) i32 { + @setRuntimeSafety(false); + return @boolToInt(@call(.{ .modifier = .always_inline }, __gedf2, .{ a, b }) >= 0); +} + +pub fn __aeabi_dcmpgt(a: f64, b: f64) callconv(.AAPCS) i32 { + @setRuntimeSafety(false); + return @boolToInt(@call(.{ .modifier = .always_inline }, __gtdf2, .{ a, b }) > 0); +} + +pub fn __aeabi_dcmpun(a: f64, b: f64) callconv(.AAPCS) i32 { + @setRuntimeSafety(false); + return @call(.{ .modifier = .always_inline }, __unorddf2, .{ a, b }); +} + +test "comparesf2" { + _ = @import("comparesf2_test.zig"); +} +test "comparedf2" { + _ = @import("comparedf2_test.zig"); +} diff --git a/lib/std/special/compiler_rt/comparedf2.zig b/lib/std/special/compiler_rt/comparedf2.zig deleted file mode 100644 index 98cca106f7..0000000000 --- a/lib/std/special/compiler_rt/comparedf2.zig +++ /dev/null @@ -1,127 +0,0 @@ -// Ported from: -// -// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/comparedf2.c - -const std = @import("std"); -const builtin = @import("builtin"); -const is_test = builtin.is_test; - -const fp_t = f64; -const rep_t = u64; -const srep_t = i64; - -const typeWidth = rep_t.bit_count; -const significandBits = std.math.floatMantissaBits(fp_t); -const exponentBits = std.math.floatExponentBits(fp_t); -const signBit = (@as(rep_t, 1) << (significandBits + exponentBits)); -const absMask = signBit - 1; -const implicitBit = @as(rep_t, 1) << significandBits; -const significandMask = implicitBit - 1; -const exponentMask = absMask ^ significandMask; -const infRep = @bitCast(rep_t, std.math.inf(fp_t)); - -// TODO https://github.com/ziglang/zig/issues/641 -// and then make the return types of some of these functions the enum instead of c_int -const LE_LESS = @as(c_int, -1); -const LE_EQUAL = @as(c_int, 0); -const LE_GREATER = @as(c_int, 1); -const LE_UNORDERED = @as(c_int, 1); - -pub fn __ledf2(a: fp_t, b: fp_t) callconv(.C) c_int { - @setRuntimeSafety(is_test); - const aInt: srep_t = @bitCast(srep_t, a); - const bInt: srep_t = @bitCast(srep_t, b); - const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask; - const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask; - - // If either a or b is NaN, they are unordered. - if (aAbs > infRep or bAbs > infRep) return LE_UNORDERED; - - // If a and b are both zeros, they are equal. - if ((aAbs | bAbs) == 0) return LE_EQUAL; - - // If at least one of a and b is positive, we get the same result comparing - // a and b as signed integers as we would with a fp_ting-point compare. - if ((aInt & bInt) >= 0) { - if (aInt < bInt) { - return LE_LESS; - } else if (aInt == bInt) { - return LE_EQUAL; - } else return LE_GREATER; - } - - // Otherwise, both are negative, so we need to flip the sense of the - // comparison to get the correct result. (This assumes a twos- or ones- - // complement integer representation; if integers are represented in a - // sign-magnitude representation, then this flip is incorrect). - else { - if (aInt > bInt) { - return LE_LESS; - } else if (aInt == bInt) { - return LE_EQUAL; - } else return LE_GREATER; - } -} - -// TODO https://github.com/ziglang/zig/issues/641 -// and then make the return types of some of these functions the enum instead of c_int -const GE_LESS = @as(c_int, -1); -const GE_EQUAL = @as(c_int, 0); -const GE_GREATER = @as(c_int, 1); -const GE_UNORDERED = @as(c_int, -1); // Note: different from LE_UNORDERED - -pub fn __gedf2(a: fp_t, b: fp_t) callconv(.C) c_int { - @setRuntimeSafety(is_test); - const aInt: srep_t = @bitCast(srep_t, a); - const bInt: srep_t = @bitCast(srep_t, b); - const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask; - const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask; - - if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED; - if ((aAbs | bAbs) == 0) return GE_EQUAL; - if ((aInt & bInt) >= 0) { - if (aInt < bInt) { - return GE_LESS; - } else if (aInt == bInt) { - return GE_EQUAL; - } else return GE_GREATER; - } else { - if (aInt > bInt) { - return GE_LESS; - } else if (aInt == bInt) { - return GE_EQUAL; - } else return GE_GREATER; - } -} - -pub fn __unorddf2(a: fp_t, b: fp_t) callconv(.C) c_int { - @setRuntimeSafety(is_test); - const aAbs: rep_t = @bitCast(rep_t, a) & absMask; - const bAbs: rep_t = @bitCast(rep_t, b) & absMask; - return @boolToInt(aAbs > infRep or bAbs > infRep); -} - -pub fn __eqdf2(a: fp_t, b: fp_t) callconv(.C) c_int { - return __ledf2(a, b); -} - -pub fn __ltdf2(a: fp_t, b: fp_t) callconv(.C) c_int { - return __ledf2(a, b); -} - -pub fn __nedf2(a: fp_t, b: fp_t) callconv(.C) c_int { - return __ledf2(a, b); -} - -pub fn __gtdf2(a: fp_t, b: fp_t) callconv(.C) c_int { - return __gedf2(a, b); -} - -pub fn __aeabi_dcmpun(a: fp_t, b: fp_t) callconv(.AAPCS) c_int { - @setRuntimeSafety(false); - return @call(.{ .modifier = .always_inline }, __unorddf2, .{ a, b }); -} - -test "import comparedf2" { - _ = @import("comparedf2_test.zig"); -} diff --git a/lib/std/special/compiler_rt/comparedf2_test.zig b/lib/std/special/compiler_rt/comparedf2_test.zig index b0e5757ec0..16a2a258ce 100644 --- a/lib/std/special/compiler_rt/comparedf2_test.zig +++ b/lib/std/special/compiler_rt/comparedf2_test.zig @@ -6,7 +6,7 @@ const std = @import("std"); const builtin = @import("builtin"); const is_test = builtin.is_test; -const comparedf2 = @import("comparedf2.zig"); +const comparedf2 = @import("compareXf2.zig"); const TestVector = struct { a: f64, diff --git a/lib/std/special/compiler_rt/comparesf2.zig b/lib/std/special/compiler_rt/comparesf2.zig deleted file mode 100644 index bd881af2a1..0000000000 --- a/lib/std/special/compiler_rt/comparesf2.zig +++ /dev/null @@ -1,127 +0,0 @@ -// Ported from: -// -// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/comparesf2.c - -const std = @import("std"); -const builtin = @import("builtin"); -const is_test = builtin.is_test; - -const fp_t = f32; -const rep_t = u32; -const srep_t = i32; - -const typeWidth = rep_t.bit_count; -const significandBits = std.math.floatMantissaBits(fp_t); -const exponentBits = std.math.floatExponentBits(fp_t); -const signBit = (@as(rep_t, 1) << (significandBits + exponentBits)); -const absMask = signBit - 1; -const implicitBit = @as(rep_t, 1) << significandBits; -const significandMask = implicitBit - 1; -const exponentMask = absMask ^ significandMask; -const infRep = @bitCast(rep_t, std.math.inf(fp_t)); - -// TODO https://github.com/ziglang/zig/issues/641 -// and then make the return types of some of these functions the enum instead of c_int -const LE_LESS = @as(c_int, -1); -const LE_EQUAL = @as(c_int, 0); -const LE_GREATER = @as(c_int, 1); -const LE_UNORDERED = @as(c_int, 1); - -pub fn __lesf2(a: fp_t, b: fp_t) callconv(.C) c_int { - @setRuntimeSafety(is_test); - const aInt: srep_t = @bitCast(srep_t, a); - const bInt: srep_t = @bitCast(srep_t, b); - const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask; - const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask; - - // If either a or b is NaN, they are unordered. - if (aAbs > infRep or bAbs > infRep) return LE_UNORDERED; - - // If a and b are both zeros, they are equal. - if ((aAbs | bAbs) == 0) return LE_EQUAL; - - // If at least one of a and b is positive, we get the same result comparing - // a and b as signed integers as we would with a fp_ting-point compare. - if ((aInt & bInt) >= 0) { - if (aInt < bInt) { - return LE_LESS; - } else if (aInt == bInt) { - return LE_EQUAL; - } else return LE_GREATER; - } - - // Otherwise, both are negative, so we need to flip the sense of the - // comparison to get the correct result. (This assumes a twos- or ones- - // complement integer representation; if integers are represented in a - // sign-magnitude representation, then this flip is incorrect). - else { - if (aInt > bInt) { - return LE_LESS; - } else if (aInt == bInt) { - return LE_EQUAL; - } else return LE_GREATER; - } -} - -// TODO https://github.com/ziglang/zig/issues/641 -// and then make the return types of some of these functions the enum instead of c_int -const GE_LESS = @as(c_int, -1); -const GE_EQUAL = @as(c_int, 0); -const GE_GREATER = @as(c_int, 1); -const GE_UNORDERED = @as(c_int, -1); // Note: different from LE_UNORDERED - -pub fn __gesf2(a: fp_t, b: fp_t) callconv(.C) c_int { - @setRuntimeSafety(is_test); - const aInt: srep_t = @bitCast(srep_t, a); - const bInt: srep_t = @bitCast(srep_t, b); - const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask; - const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask; - - if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED; - if ((aAbs | bAbs) == 0) return GE_EQUAL; - if ((aInt & bInt) >= 0) { - if (aInt < bInt) { - return GE_LESS; - } else if (aInt == bInt) { - return GE_EQUAL; - } else return GE_GREATER; - } else { - if (aInt > bInt) { - return GE_LESS; - } else if (aInt == bInt) { - return GE_EQUAL; - } else return GE_GREATER; - } -} - -pub fn __unordsf2(a: fp_t, b: fp_t) callconv(.C) c_int { - @setRuntimeSafety(is_test); - const aAbs: rep_t = @bitCast(rep_t, a) & absMask; - const bAbs: rep_t = @bitCast(rep_t, b) & absMask; - return @boolToInt(aAbs > infRep or bAbs > infRep); -} - -pub fn __eqsf2(a: fp_t, b: fp_t) callconv(.C) c_int { - return __lesf2(a, b); -} - -pub fn __ltsf2(a: fp_t, b: fp_t) callconv(.C) c_int { - return __lesf2(a, b); -} - -pub fn __nesf2(a: fp_t, b: fp_t) callconv(.C) c_int { - return __lesf2(a, b); -} - -pub fn __gtsf2(a: fp_t, b: fp_t) callconv(.C) c_int { - return __gesf2(a, b); -} - -pub fn __aeabi_fcmpun(a: fp_t, b: fp_t) callconv(.AAPCS) c_int { - @setRuntimeSafety(false); - return @call(.{ .modifier = .always_inline }, __unordsf2, .{ a, b }); -} - -test "import comparesf2" { - _ = @import("comparesf2_test.zig"); -} diff --git a/lib/std/special/compiler_rt/comparesf2_test.zig b/lib/std/special/compiler_rt/comparesf2_test.zig index d736988bfb..e3966c021b 100644 --- a/lib/std/special/compiler_rt/comparesf2_test.zig +++ b/lib/std/special/compiler_rt/comparesf2_test.zig @@ -6,7 +6,7 @@ const std = @import("std"); const builtin = @import("builtin"); const is_test = builtin.is_test; -const comparesf2 = @import("comparesf2.zig"); +const comparesf2 = @import("compareXf2.zig"); const TestVector = struct { a: f32, diff --git a/lib/std/special/compiler_rt/comparetf2.zig b/lib/std/special/compiler_rt/comparetf2.zig deleted file mode 100644 index f2969f2112..0000000000 --- a/lib/std/special/compiler_rt/comparetf2.zig +++ /dev/null @@ -1,99 +0,0 @@ -// TODO https://github.com/ziglang/zig/issues/641 -// and then make the return types of some of these functions the enum instead of c_int -const LE_LESS = @as(c_int, -1); -const LE_EQUAL = @as(c_int, 0); -const LE_GREATER = @as(c_int, 1); -const LE_UNORDERED = @as(c_int, 1); - -const rep_t = u128; -const srep_t = i128; - -const typeWidth = rep_t.bit_count; -const significandBits = 112; -const exponentBits = (typeWidth - significandBits - 1); -const signBit = (@as(rep_t, 1) << (significandBits + exponentBits)); -const absMask = signBit - 1; -const implicitBit = @as(rep_t, 1) << significandBits; -const significandMask = implicitBit - 1; -const exponentMask = absMask ^ significandMask; -const infRep = exponentMask; - -const builtin = @import("builtin"); -const is_test = builtin.is_test; - -pub fn __letf2(a: f128, b: f128) callconv(.C) c_int { - @setRuntimeSafety(is_test); - - const aInt = @bitCast(rep_t, a); - const bInt = @bitCast(rep_t, b); - - const aAbs: rep_t = aInt & absMask; - const bAbs: rep_t = bInt & absMask; - - // If either a or b is NaN, they are unordered. - if (aAbs > infRep or bAbs > infRep) return LE_UNORDERED; - - // If a and b are both zeros, they are equal. - if ((aAbs | bAbs) == 0) return LE_EQUAL; - - // If at least one of a and b is positive, we get the same result comparing - // a and b as signed integers as we would with a floating-point compare. - return if ((aInt & bInt) >= 0) - if (aInt < bInt) - LE_LESS - else if (aInt == bInt) - LE_EQUAL - else - LE_GREATER - else - // Otherwise, both are negative, so we need to flip the sense of the - // comparison to get the correct result. (This assumes a twos- or ones- - // complement integer representation; if integers are represented in a - // sign-magnitude representation, then this flip is incorrect). - if (aInt > bInt) - LE_LESS - else if (aInt == bInt) - LE_EQUAL - else - LE_GREATER; -} - -// TODO https://github.com/ziglang/zig/issues/641 -// and then make the return types of some of these functions the enum instead of c_int -const GE_LESS = @as(c_int, -1); -const GE_EQUAL = @as(c_int, 0); -const GE_GREATER = @as(c_int, 1); -const GE_UNORDERED = @as(c_int, -1); // Note: different from LE_UNORDERED - -pub fn __getf2(a: f128, b: f128) callconv(.C) c_int { - @setRuntimeSafety(is_test); - - const aInt = @bitCast(srep_t, a); - const bInt = @bitCast(srep_t, b); - const aAbs = @bitCast(rep_t, aInt) & absMask; - const bAbs = @bitCast(rep_t, bInt) & absMask; - - if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED; - if ((aAbs | bAbs) == 0) return GE_EQUAL; - return if ((aInt & bInt) >= 0) - if (aInt < bInt) - GE_LESS - else if (aInt == bInt) - GE_EQUAL - else - GE_GREATER - else if (aInt > bInt) - GE_LESS - else if (aInt == bInt) - GE_EQUAL - else - GE_GREATER; -} - -pub fn __unordtf2(a: f128, b: f128) callconv(.C) c_int { - @setRuntimeSafety(is_test); - - const aAbs = @bitCast(rep_t, a) & absMask; - const bAbs = @bitCast(rep_t, b) & absMask; - return @boolToInt(aAbs > infRep or bAbs > infRep); -} diff --git a/lib/std/special/compiler_rt/fixtfdi_test.zig b/lib/std/special/compiler_rt/fixtfdi_test.zig index 6baa9011c3..4c43c90550 100644 --- a/lib/std/special/compiler_rt/fixtfdi_test.zig +++ b/lib/std/special/compiler_rt/fixtfdi_test.zig @@ -11,6 +11,10 @@ fn test__fixtfdi(a: f128, expected: i64) void { } test "fixtfdi" { + if (@import("std").Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } //warn("\n", .{}); test__fixtfdi(-math.f128_max, math.minInt(i64)); diff --git a/lib/std/special/compiler_rt/fixtfsi_test.zig b/lib/std/special/compiler_rt/fixtfsi_test.zig index c7294fe250..4eabd0c594 100644 --- a/lib/std/special/compiler_rt/fixtfsi_test.zig +++ b/lib/std/special/compiler_rt/fixtfsi_test.zig @@ -11,6 +11,10 @@ fn test__fixtfsi(a: f128, expected: i32) void { } test "fixtfsi" { + if (@import("std").Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } //warn("\n", .{}); test__fixtfsi(-math.f128_max, math.minInt(i32)); diff --git a/lib/std/special/compiler_rt/fixtfti_test.zig b/lib/std/special/compiler_rt/fixtfti_test.zig index 6b8218e2f6..acda2f162b 100644 --- a/lib/std/special/compiler_rt/fixtfti_test.zig +++ b/lib/std/special/compiler_rt/fixtfti_test.zig @@ -11,6 +11,10 @@ fn test__fixtfti(a: f128, expected: i128) void { } test "fixtfti" { + if (@import("std").Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } //warn("\n", .{}); test__fixtfti(-math.f128_max, math.minInt(i128)); diff --git a/lib/std/special/compiler_rt/fixunstfdi_test.zig b/lib/std/special/compiler_rt/fixunstfdi_test.zig index 0d47641c09..154fffe18a 100644 --- a/lib/std/special/compiler_rt/fixunstfdi_test.zig +++ b/lib/std/special/compiler_rt/fixunstfdi_test.zig @@ -7,6 +7,10 @@ fn test__fixunstfdi(a: f128, expected: u64) void { } test "fixunstfdi" { + if (@import("std").Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } test__fixunstfdi(0.0, 0); test__fixunstfdi(0.5, 0); diff --git a/lib/std/special/compiler_rt/fixunstfsi_test.zig b/lib/std/special/compiler_rt/fixunstfsi_test.zig index 286567629a..af312ddc46 100644 --- a/lib/std/special/compiler_rt/fixunstfsi_test.zig +++ b/lib/std/special/compiler_rt/fixunstfsi_test.zig @@ -9,6 +9,10 @@ fn test__fixunstfsi(a: f128, expected: u32) void { const inf128 = @bitCast(f128, @as(u128, 0x7fff0000000000000000000000000000)); test "fixunstfsi" { + if (@import("std").Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } test__fixunstfsi(inf128, 0xffffffff); test__fixunstfsi(0, 0x0); test__fixunstfsi(0x1.23456789abcdefp+5, 0x24); diff --git a/lib/std/special/compiler_rt/fixunstfti_test.zig b/lib/std/special/compiler_rt/fixunstfti_test.zig index 62a9bbfecf..84dbf991e2 100644 --- a/lib/std/special/compiler_rt/fixunstfti_test.zig +++ b/lib/std/special/compiler_rt/fixunstfti_test.zig @@ -9,6 +9,10 @@ fn test__fixunstfti(a: f128, expected: u128) void { const inf128 = @bitCast(f128, @as(u128, 0x7fff0000000000000000000000000000)); test "fixunstfti" { + if (@import("std").Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } test__fixunstfti(inf128, 0xffffffffffffffffffffffffffffffff); test__fixunstfti(0.0, 0); diff --git a/lib/std/special/compiler_rt/floattitf_test.zig b/lib/std/special/compiler_rt/floattitf_test.zig index 53e3e48bdb..0b2b5b958a 100644 --- a/lib/std/special/compiler_rt/floattitf_test.zig +++ b/lib/std/special/compiler_rt/floattitf_test.zig @@ -7,6 +7,10 @@ fn test__floattitf(a: i128, expected: f128) void { } test "floattitf" { + if (@import("std").Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } test__floattitf(0, 0.0); test__floattitf(1, 1.0); diff --git a/lib/std/special/compiler_rt/floatuntitf_test.zig b/lib/std/special/compiler_rt/floatuntitf_test.zig index 09f3eabb3e..8b99bbef5d 100644 --- a/lib/std/special/compiler_rt/floatuntitf_test.zig +++ b/lib/std/special/compiler_rt/floatuntitf_test.zig @@ -7,6 +7,10 @@ fn test__floatuntitf(a: u128, expected: f128) void { } test "floatuntitf" { + if (@import("std").Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } test__floatuntitf(0, 0.0); test__floatuntitf(1, 1.0); diff --git a/lib/std/special/compiler_rt/int.zig b/lib/std/special/compiler_rt/int.zig index 88f4d66966..eb731ee898 100644 --- a/lib/std/special/compiler_rt/int.zig +++ b/lib/std/special/compiler_rt/int.zig @@ -1,6 +1,8 @@ // Builtin functions that operate on integer types const builtin = @import("builtin"); const testing = @import("std").testing; +const maxInt = @import("std").math.maxInt; +const minInt = @import("std").math.minInt; const udivmod = @import("udivmod.zig").udivmod; @@ -578,3 +580,61 @@ fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) void { const r: u32 = __umodsi3(a, b); testing.expect(r == expected_r); } + +pub fn __mulsi3(a: i32, b: i32) callconv(.C) i32 { + @setRuntimeSafety(builtin.is_test); + + var ua = @bitCast(u32, a); + var ub = @bitCast(u32, b); + var r: u32 = 0; + + while (ua > 0) { + if ((ua & 1) != 0) r +%= ub; + ua >>= 1; + ub <<= 1; + } + + return @bitCast(i32, r); +} + +fn test_one_mulsi3(a: i32, b: i32, result: i32) void { + testing.expectEqual(result, __mulsi3(a, b)); +} + +test "mulsi3" { + test_one_mulsi3(0, 0, 0); + test_one_mulsi3(0, 1, 0); + test_one_mulsi3(1, 0, 0); + test_one_mulsi3(0, 10, 0); + test_one_mulsi3(10, 0, 0); + test_one_mulsi3(0, maxInt(i32), 0); + test_one_mulsi3(maxInt(i32), 0, 0); + test_one_mulsi3(0, -1, 0); + test_one_mulsi3(-1, 0, 0); + test_one_mulsi3(0, -10, 0); + test_one_mulsi3(-10, 0, 0); + test_one_mulsi3(0, minInt(i32), 0); + test_one_mulsi3(minInt(i32), 0, 0); + test_one_mulsi3(1, 1, 1); + test_one_mulsi3(1, 10, 10); + test_one_mulsi3(10, 1, 10); + test_one_mulsi3(1, maxInt(i32), maxInt(i32)); + test_one_mulsi3(maxInt(i32), 1, maxInt(i32)); + test_one_mulsi3(1, -1, -1); + test_one_mulsi3(1, -10, -10); + test_one_mulsi3(-10, 1, -10); + test_one_mulsi3(1, minInt(i32), minInt(i32)); + test_one_mulsi3(minInt(i32), 1, minInt(i32)); + test_one_mulsi3(46340, 46340, 2147395600); + test_one_mulsi3(-46340, 46340, -2147395600); + test_one_mulsi3(46340, -46340, -2147395600); + test_one_mulsi3(-46340, -46340, 2147395600); + test_one_mulsi3(4194303, 8192, @truncate(i32, 34359730176)); + test_one_mulsi3(-4194303, 8192, @truncate(i32, -34359730176)); + test_one_mulsi3(4194303, -8192, @truncate(i32, -34359730176)); + test_one_mulsi3(-4194303, -8192, @truncate(i32, 34359730176)); + test_one_mulsi3(8192, 4194303, @truncate(i32, 34359730176)); + test_one_mulsi3(-8192, 4194303, @truncate(i32, -34359730176)); + test_one_mulsi3(8192, -4194303, @truncate(i32, -34359730176)); + test_one_mulsi3(-8192, -4194303, @truncate(i32, 34359730176)); +} diff --git a/lib/std/special/compiler_rt/mulXf3_test.zig b/lib/std/special/compiler_rt/mulXf3_test.zig index 57dc385321..00db984a89 100644 --- a/lib/std/special/compiler_rt/mulXf3_test.zig +++ b/lib/std/special/compiler_rt/mulXf3_test.zig @@ -44,6 +44,10 @@ fn makeNaN128(rand: u64) f128 { return float_result; } test "multf3" { + if (@import("std").Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } // qNaN * any = qNaN test__multf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); diff --git a/lib/std/special/compiler_rt/truncXfYf2_test.zig b/lib/std/special/compiler_rt/truncXfYf2_test.zig index baec2a4450..f14dbe6b43 100644 --- a/lib/std/special/compiler_rt/truncXfYf2_test.zig +++ b/lib/std/special/compiler_rt/truncXfYf2_test.zig @@ -151,6 +151,10 @@ fn test__trunctfsf2(a: f128, expected: u32) void { } test "trunctfsf2" { + if (@import("std").Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } // qnan test__trunctfsf2(@bitCast(f128, @as(u128, 0x7fff800000000000 << 64)), 0x7fc00000); // nan @@ -186,6 +190,10 @@ fn test__trunctfdf2(a: f128, expected: u64) void { } test "trunctfdf2" { + if (@import("std").Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } // qnan test__trunctfdf2(@bitCast(f128, @as(u128, 0x7fff800000000000 << 64)), 0x7ff8000000000000); // nan diff --git a/lib/std/start.zig b/lib/std/start.zig index c3844e4d1e..bf6f61f25f 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -8,16 +8,7 @@ const uefi = std.os.uefi; var starting_stack_ptr: [*]usize = undefined; -const is_wasm = switch (builtin.arch) { - .wasm32, .wasm64 => true, - else => false, -}; - -const is_mips = switch (builtin.arch) { - .mips, .mipsel, .mips64, .mips64el => true, - else => false, -}; -const start_sym_name = if (is_mips) "__start" else "_start"; +const start_sym_name = if (builtin.arch.isMIPS()) "__start" else "_start"; comptime { if (builtin.output_mode == .Lib and builtin.link_mode == .Dynamic) { @@ -35,7 +26,7 @@ comptime { } } else if (builtin.os == .uefi) { if (!@hasDecl(root, "EfiMain")) @export(EfiMain, .{ .name = "EfiMain" }); - } else if (is_wasm and builtin.os == .freestanding) { + } else if (builtin.arch.isWasm() and builtin.os == .freestanding) { if (!@hasDecl(root, start_sym_name)) @export(wasm_freestanding_start, .{ .name = start_sym_name }); } else if (builtin.os != .other and builtin.os != .freestanding) { if (!@hasDecl(root, start_sym_name)) @export(_start, .{ .name = start_sym_name }); diff --git a/lib/std/target.zig b/lib/std/target.zig index 22fea691c4..0b09ebf838 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -49,6 +49,22 @@ pub const Target = union(enum) { other, }; + pub const aarch64 = @import("target/aarch64.zig"); + pub const amdgpu = @import("target/amdgpu.zig"); + pub const arm = @import("target/arm.zig"); + pub const avr = @import("target/avr.zig"); + pub const bpf = @import("target/bpf.zig"); + pub const hexagon = @import("target/hexagon.zig"); + pub const mips = @import("target/mips.zig"); + pub const msp430 = @import("target/msp430.zig"); + pub const nvptx = @import("target/nvptx.zig"); + pub const powerpc = @import("target/powerpc.zig"); + pub const riscv = @import("target/riscv.zig"); + pub const sparc = @import("target/sparc.zig"); + pub const systemz = @import("target/systemz.zig"); + pub const wasm = @import("target/wasm.zig"); + pub const x86 = @import("target/x86.zig"); + pub const Arch = union(enum) { arm: Arm32, armeb: Arm32, @@ -107,12 +123,12 @@ pub const Target = union(enum) { v8_3a, v8_2a, v8_1a, - v8, + v8a, v8r, v8m_baseline, v8m_mainline, v8_1m_mainline, - v7, + v7a, v7em, v7m, v7s, @@ -125,6 +141,16 @@ pub const Target = union(enum) { v5, v5te, v4t, + + pub fn version(version: Arm32) comptime_int { + return switch (version) { + .v8_5a, .v8_4a, .v8_3a, .v8_2a, .v8_1a, .v8a, .v8r, .v8m_baseline, .v8m_mainline, .v8_1m_mainline => 8, + .v7a, .v7em, .v7m, .v7s, .v7k, .v7ve => 7, + .v6, .v6m, .v6k, .v6t2 => 6, + .v5, .v5te => 5, + .v4t => 4, + }; + } }; pub const Arm64 = enum { v8_5a, @@ -132,10 +158,7 @@ pub const Target = union(enum) { v8_3a, v8_2a, v8_1a, - v8, - v8r, - v8m_baseline, - v8m_mainline, + v8a, }; pub const Kalimba = enum { v5, @@ -146,6 +169,129 @@ pub const Target = union(enum) { r6, }; + pub fn subArchName(arch: Arch) ?[]const u8 { + return switch (arch) { + .arm, .armeb, .thumb, .thumbeb => |arm32| @tagName(arm32), + .aarch64, .aarch64_be, .aarch64_32 => |arm64| @tagName(arm64), + .kalimba => |kalimba| @tagName(kalimba), + else => return null, + }; + } + + pub fn subArchFeature(arch: Arch) ?Cpu.Feature.Set.Index { + return switch (arch) { + .arm, .armeb, .thumb, .thumbeb => |arm32| switch (arm32) { + .v8_5a => @enumToInt(arm.Feature.armv8_5_a), + .v8_4a => @enumToInt(arm.Feature.armv8_4_a), + .v8_3a => @enumToInt(arm.Feature.armv8_3_a), + .v8_2a => @enumToInt(arm.Feature.armv8_2_a), + .v8_1a => @enumToInt(arm.Feature.armv8_1_a), + .v8a => @enumToInt(arm.Feature.armv8_a), + .v8r => @enumToInt(arm.Feature.armv8_r), + .v8m_baseline => @enumToInt(arm.Feature.armv8_m_base), + .v8m_mainline => @enumToInt(arm.Feature.armv8_m_main), + .v8_1m_mainline => @enumToInt(arm.Feature.armv8_1_m_main), + .v7a => @enumToInt(arm.Feature.armv7_a), + .v7em => @enumToInt(arm.Feature.armv7e_m), + .v7m => @enumToInt(arm.Feature.armv7_m), + .v7s => @enumToInt(arm.Feature.armv7s), + .v7k => @enumToInt(arm.Feature.armv7k), + .v7ve => @enumToInt(arm.Feature.armv7ve), + .v6 => @enumToInt(arm.Feature.armv6), + .v6m => @enumToInt(arm.Feature.armv6_m), + .v6k => @enumToInt(arm.Feature.armv6k), + .v6t2 => @enumToInt(arm.Feature.armv6t2), + .v5 => @enumToInt(arm.Feature.armv5t), + .v5te => @enumToInt(arm.Feature.armv5te), + .v4t => @enumToInt(arm.Feature.armv4t), + }, + .aarch64, .aarch64_be, .aarch64_32 => |arm64| switch (arm64) { + .v8_5a => @enumToInt(aarch64.Feature.v8_5a), + .v8_4a => @enumToInt(aarch64.Feature.v8_4a), + .v8_3a => @enumToInt(aarch64.Feature.v8_3a), + .v8_2a => @enumToInt(aarch64.Feature.v8_2a), + .v8_1a => @enumToInt(aarch64.Feature.v8_1a), + .v8a => @enumToInt(aarch64.Feature.v8a), + }, + else => return null, + }; + } + + pub fn isARM(arch: Arch) bool { + return switch (arch) { + .arm, .armeb => true, + else => false, + }; + } + + pub fn isThumb(arch: Arch) bool { + return switch (arch) { + .thumb, .thumbeb => true, + else => false, + }; + } + + pub fn isWasm(arch: Arch) bool { + return switch (arch) { + .wasm32, .wasm64 => true, + else => false, + }; + } + + pub fn isMIPS(arch: Arch) bool { + return switch (arch) { + .mips, .mipsel, .mips64, .mips64el => true, + else => false, + }; + } + + pub fn parseCpu(arch: Arch, cpu_name: []const u8) !*const Cpu { + for (arch.allCpus()) |cpu| { + if (mem.eql(u8, cpu_name, cpu.name)) { + return cpu; + } + } + return error.UnknownCpu; + } + + /// Comma-separated list of features, with + or - in front of each feature. This + /// form represents a deviation from baseline CPU, which is provided as a parameter. + /// Extra commas are ignored. + pub fn parseCpuFeatureSet(arch: Arch, cpu: *const Cpu, features_text: []const u8) !Cpu.Feature.Set { + const all_features = arch.allFeaturesList(); + var set = cpu.features; + var it = mem.tokenize(features_text, ","); + while (it.next()) |item_text| { + var feature_name: []const u8 = undefined; + var op: enum { + add, + sub, + } = undefined; + if (mem.startsWith(u8, item_text, "+")) { + op = .add; + feature_name = item_text[1..]; + } else if (mem.startsWith(u8, item_text, "-")) { + op = .sub; + feature_name = item_text[1..]; + } else { + return error.InvalidCpuFeatures; + } + for (all_features) |feature, index_usize| { + const index = @intCast(Cpu.Feature.Set.Index, index_usize); + if (mem.eql(u8, feature_name, feature.name)) { + switch (op) { + .add => set.addFeature(index), + .sub => set.removeFeature(index), + } + break; + } + } else { + return error.UnknownCpuFeature; + } + } + return set; + } + pub fn toElfMachine(arch: Arch) std.elf.EM { return switch (arch) { .avr => ._AVR, @@ -258,6 +404,109 @@ pub const Target = union(enum) { => .Big, }; } + + /// Returns a name that matches the lib/std/target/* directory name. + pub fn genericName(arch: Arch) []const u8 { + return switch (arch) { + .arm, .armeb, .thumb, .thumbeb => "arm", + .aarch64, .aarch64_be, .aarch64_32 => "aarch64", + .avr => "avr", + .bpfel, .bpfeb => "bpf", + .hexagon => "hexagon", + .mips, .mipsel, .mips64, .mips64el => "mips", + .msp430 => "msp430", + .powerpc, .powerpc64, .powerpc64le => "powerpc", + .amdgcn => "amdgpu", + .riscv32, .riscv64 => "riscv", + .sparc, .sparcv9, .sparcel => "sparc", + .s390x => "systemz", + .i386, .x86_64 => "x86", + .nvptx, .nvptx64 => "nvptx", + .wasm32, .wasm64 => "wasm", + else => @tagName(arch), + }; + } + + /// All CPU features Zig is aware of, sorted lexicographically by name. + pub fn allFeaturesList(arch: Arch) []const Cpu.Feature { + return switch (arch) { + .arm, .armeb, .thumb, .thumbeb => &arm.all_features, + .aarch64, .aarch64_be, .aarch64_32 => &aarch64.all_features, + .avr => &avr.all_features, + .bpfel, .bpfeb => &bpf.all_features, + .hexagon => &hexagon.all_features, + .mips, .mipsel, .mips64, .mips64el => &mips.all_features, + .msp430 => &msp430.all_features, + .powerpc, .powerpc64, .powerpc64le => &powerpc.all_features, + .amdgcn => &amdgpu.all_features, + .riscv32, .riscv64 => &riscv.all_features, + .sparc, .sparcv9, .sparcel => &sparc.all_features, + .s390x => &systemz.all_features, + .i386, .x86_64 => &x86.all_features, + .nvptx, .nvptx64 => &nvptx.all_features, + .wasm32, .wasm64 => &wasm.all_features, + + else => &[0]Cpu.Feature{}, + }; + } + + /// The "default" set of CPU features for cross-compiling. A conservative set + /// of features that is expected to be supported on most available hardware. + pub fn getBaselineCpuFeatures(arch: Arch) CpuFeatures { + const S = struct { + const generic_cpu = Cpu{ + .name = "generic", + .llvm_name = null, + .features = Cpu.Feature.Set.empty, + }; + }; + const cpu = switch (arch) { + .arm, .armeb, .thumb, .thumbeb => &arm.cpu.generic, + .aarch64, .aarch64_be, .aarch64_32 => &aarch64.cpu.generic, + .avr => &avr.cpu.avr1, + .bpfel, .bpfeb => &bpf.cpu.generic, + .hexagon => &hexagon.cpu.generic, + .mips, .mipsel => &mips.cpu.mips32, + .mips64, .mips64el => &mips.cpu.mips64, + .msp430 => &msp430.cpu.generic, + .powerpc, .powerpc64, .powerpc64le => &powerpc.cpu.generic, + .amdgcn => &amdgpu.cpu.generic, + .riscv32 => &riscv.cpu.baseline_rv32, + .riscv64 => &riscv.cpu.baseline_rv64, + .sparc, .sparcv9, .sparcel => &sparc.cpu.generic, + .s390x => &systemz.cpu.generic, + .i386 => &x86.cpu.pentium4, + .x86_64 => &x86.cpu.x86_64, + .nvptx, .nvptx64 => &nvptx.cpu.sm_20, + .wasm32, .wasm64 => &wasm.cpu.generic, + + else => &S.generic_cpu, + }; + return CpuFeatures.initFromCpu(arch, cpu); + } + + /// All CPUs Zig is aware of, sorted lexicographically by name. + pub fn allCpus(arch: Arch) []const *const Cpu { + return switch (arch) { + .arm, .armeb, .thumb, .thumbeb => arm.all_cpus, + .aarch64, .aarch64_be, .aarch64_32 => aarch64.all_cpus, + .avr => avr.all_cpus, + .bpfel, .bpfeb => bpf.all_cpus, + .hexagon => hexagon.all_cpus, + .mips, .mipsel, .mips64, .mips64el => mips.all_cpus, + .msp430 => msp430.all_cpus, + .powerpc, .powerpc64, .powerpc64le => powerpc.all_cpus, + .amdgcn => amdgpu.all_cpus, + .riscv32, .riscv64 => riscv.all_cpus, + .sparc, .sparcv9, .sparcel => sparc.all_cpus, + .s390x => systemz.all_cpus, + .i386, .x86_64 => x86.all_cpus, + .nvptx, .nvptx64 => nvptx.all_cpus, + .wasm32, .wasm64 => wasm.all_cpus, + + else => &[0]*const Cpu{}, + }; + } }; pub const Abi = enum { @@ -285,6 +534,109 @@ pub const Target = union(enum) { macabi, }; + pub const Cpu = struct { + name: []const u8, + llvm_name: ?[:0]const u8, + features: Feature.Set, + + pub const Feature = struct { + /// The bit index into `Set`. Has a default value of `undefined` because the canonical + /// structures are populated via comptime logic. + index: Set.Index = undefined, + + /// Has a default value of `undefined` because the canonical + /// structures are populated via comptime logic. + name: []const u8 = undefined, + + /// If this corresponds to an LLVM-recognized feature, this will be populated; + /// otherwise null. + llvm_name: ?[:0]const u8, + + /// Human-friendly UTF-8 text. + description: []const u8, + + /// Sparse `Set` of features this depends on. + dependencies: Set, + + /// A bit set of all the features. + pub const Set = struct { + ints: [usize_count]usize, + + pub const needed_bit_count = 174; + pub const byte_count = (needed_bit_count + 7) / 8; + pub const usize_count = (byte_count + (@sizeOf(usize) - 1)) / @sizeOf(usize); + pub const Index = std.math.Log2Int(@IntType(false, usize_count * @bitSizeOf(usize))); + pub const ShiftInt = std.math.Log2Int(usize); + + pub const empty = Set{ .ints = [1]usize{0} ** usize_count }; + pub fn empty_workaround() Set { + return Set{ .ints = [1]usize{0} ** usize_count }; + } + + pub fn isEnabled(set: Set, arch_feature_index: Index) bool { + const usize_index = arch_feature_index / @bitSizeOf(usize); + const bit_index = @intCast(ShiftInt, arch_feature_index % @bitSizeOf(usize)); + return (set.ints[usize_index] & (@as(usize, 1) << bit_index)) != 0; + } + + /// Adds the specified feature but not its dependencies. + pub fn addFeature(set: *Set, arch_feature_index: Index) void { + const usize_index = arch_feature_index / @bitSizeOf(usize); + const bit_index = @intCast(ShiftInt, arch_feature_index % @bitSizeOf(usize)); + set.ints[usize_index] |= @as(usize, 1) << bit_index; + } + + /// Removes the specified feature but not its dependents. + pub fn removeFeature(set: *Set, arch_feature_index: Index) void { + const usize_index = arch_feature_index / @bitSizeOf(usize); + const bit_index = @intCast(ShiftInt, arch_feature_index % @bitSizeOf(usize)); + set.ints[usize_index] &= ~(@as(usize, 1) << bit_index); + } + + pub fn populateDependencies(set: *Set, all_features_list: []const Cpu.Feature) void { + var old = set.ints; + while (true) { + for (all_features_list) |feature, index_usize| { + const index = @intCast(Index, index_usize); + if (set.isEnabled(index)) { + set.ints = @as(@Vector(usize_count, usize), set.ints) | + @as(@Vector(usize_count, usize), feature.dependencies.ints); + } + } + const nothing_changed = mem.eql(usize, &old, &set.ints); + if (nothing_changed) return; + old = set.ints; + } + } + + pub fn asBytes(set: *const Set) *const [byte_count]u8 { + return @ptrCast(*const [byte_count]u8, &set.ints); + } + + pub fn eql(set: Set, other: Set) bool { + return mem.eql(usize, &set.ints, &other.ints); + } + }; + + pub fn feature_set_fns(comptime F: type) type { + return struct { + /// Populates only the feature bits specified. + pub fn featureSet(features: []const F) Set { + var x = Set.empty_workaround(); // TODO remove empty_workaround + for (features) |feature| { + x.addFeature(@enumToInt(feature)); + } + return x; + } + + pub fn featureSetHas(set: Set, feature: F) bool { + return set.isEnabled(@enumToInt(feature)); + } + }; + } + }; + }; + pub const ObjectFormat = enum { unknown, coff, @@ -308,6 +660,28 @@ pub const Target = union(enum) { arch: Arch, os: Os, abi: Abi, + cpu_features: CpuFeatures, + }; + + pub const CpuFeatures = struct { + /// The CPU to target. It has a set of features + /// which are overridden with the `features` field. + cpu: *const Cpu, + + /// Explicitly provide the entire CPU feature set. + features: Cpu.Feature.Set, + + pub fn initFromCpu(arch: Arch, cpu: *const Cpu) CpuFeatures { + var features = cpu.features; + if (arch.subArchFeature()) |sub_arch_index| { + features.addFeature(sub_arch_index); + } + features.populateDependencies(arch.allFeaturesList()); + return CpuFeatures{ + .cpu = cpu, + .features = features, + }; + } }; pub const current = Target{ @@ -315,11 +689,19 @@ pub const Target = union(enum) { .arch = builtin.arch, .os = builtin.os, .abi = builtin.abi, + .cpu_features = builtin.cpu_features, }, }; pub const stack_align = 16; + pub fn getCpuFeatures(self: Target) CpuFeatures { + return switch (self) { + .Native => builtin.cpu_features, + .Cross => |cross| cross.cpu_features, + }; + } + pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![]u8 { return std.fmt.allocPrint(allocator, "{}{}-{}-{}", .{ @tagName(self.getArch()), @@ -385,14 +767,18 @@ pub const Target = union(enum) { }); } + /// TODO: Support CPU features here? + /// https://github.com/ziglang/zig/issues/4261 pub fn parse(text: []const u8) !Target { var it = mem.separate(text, "-"); const arch_name = it.next() orelse return error.MissingArchitecture; const os_name = it.next() orelse return error.MissingOperatingSystem; const abi_name = it.next(); + const arch = try parseArchSub(arch_name); var cross = Cross{ - .arch = try parseArchSub(arch_name), + .arch = arch, + .cpu_features = arch.getBaselineCpuFeatures(), .os = try parseOs(os_name), .abi = undefined, }; @@ -458,7 +844,7 @@ pub const Target = union(enum) { pub fn parseArchSub(text: []const u8) ParseArchSubError!Arch { const info = @typeInfo(Arch); inline for (info.Union.fields) |field| { - if (mem.eql(u8, text, field.name)) { + if (mem.startsWith(u8, text, field.name)) { if (field.field_type == void) { return @as(Arch, @field(Arch, field.name)); } else { @@ -778,3 +1164,15 @@ pub const Target = union(enum) { return .unavailable; } }; + +test "parseCpuFeatureSet" { + const arch: Target.Arch = .x86_64; + const baseline = arch.getBaselineCpuFeatures(); + const set = try arch.parseCpuFeatureSet(baseline.cpu, "-sse,-avx,-cx8"); + std.testing.expect(!Target.x86.featureSetHas(set, .sse)); + std.testing.expect(!Target.x86.featureSetHas(set, .avx)); + std.testing.expect(!Target.x86.featureSetHas(set, .cx8)); + // These are expected because they are part of the baseline + std.testing.expect(Target.x86.featureSetHas(set, .cmov)); + std.testing.expect(Target.x86.featureSetHas(set, .fxsr)); +} diff --git a/lib/std/target/aarch64.zig b/lib/std/target/aarch64.zig new file mode 100644 index 0000000000..d2878e2423 --- /dev/null +++ b/lib/std/target/aarch64.zig @@ -0,0 +1,1450 @@ +const std = @import("../std.zig"); +const Cpu = std.Target.Cpu; + +pub const Feature = enum { + a35, + a53, + a55, + a57, + a72, + a73, + a75, + a76, + aes, + aggressive_fma, + alternate_sextload_cvt_f32_pattern, + altnzcv, + am, + arith_bcc_fusion, + arith_cbz_fusion, + balance_fp_ops, + bti, + call_saved_x10, + call_saved_x11, + call_saved_x12, + call_saved_x13, + call_saved_x14, + call_saved_x15, + call_saved_x18, + call_saved_x8, + call_saved_x9, + ccdp, + ccidx, + ccpp, + complxnum, + crc, + crypto, + custom_cheap_as_move, + cyclone, + disable_latency_sched_heuristic, + dit, + dotprod, + exynos_cheap_as_move, + exynosm1, + exynosm2, + exynosm3, + exynosm4, + falkor, + fmi, + force_32bit_jump_tables, + fp_armv8, + fp16fml, + fptoint, + fullfp16, + fuse_address, + fuse_aes, + fuse_arith_logic, + fuse_crypto_eor, + fuse_csel, + fuse_literals, + jsconv, + kryo, + lor, + lse, + lsl_fast, + mpam, + mte, + neon, + no_neg_immediates, + nv, + pa, + pan, + pan_rwv, + perfmon, + predictable_select_expensive, + predres, + rand, + ras, + rasv8_4, + rcpc, + rcpc_immo, + rdm, + reserve_x1, + reserve_x10, + reserve_x11, + reserve_x12, + reserve_x13, + reserve_x14, + reserve_x15, + reserve_x18, + reserve_x2, + reserve_x20, + reserve_x21, + reserve_x22, + reserve_x23, + reserve_x24, + reserve_x25, + reserve_x26, + reserve_x27, + reserve_x28, + reserve_x3, + reserve_x4, + reserve_x5, + reserve_x6, + reserve_x7, + reserve_x9, + saphira, + sb, + sel2, + sha2, + sha3, + slow_misaligned_128store, + slow_paired_128, + slow_strqro_store, + sm4, + spe, + specrestrict, + ssbs, + strict_align, + sve, + sve2, + sve2_aes, + sve2_bitperm, + sve2_sha3, + sve2_sm4, + thunderx, + thunderx2t99, + thunderxt81, + thunderxt83, + thunderxt88, + tlb_rmi, + tpidr_el1, + tpidr_el2, + tpidr_el3, + tracev8_4, + tsv110, + uaops, + use_aa, + use_postra_scheduler, + use_reciprocal_square_root, + v8a, + v8_1a, + v8_2a, + v8_3a, + v8_4a, + v8_5a, + vh, + zcm, + zcz, + zcz_fp, + zcz_fp_workaround, + zcz_gp, +}; + +pub usingnamespace Cpu.Feature.feature_set_fns(Feature); + +pub const all_features = blk: { + @setEvalBranchQuota(2000); + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); + var result: [len]Cpu.Feature = undefined; + result[@enumToInt(Feature.a35)] = .{ + .llvm_name = "a35", + .description = "Cortex-A35 ARM processors", + .dependencies = featureSet(&[_]Feature{ + .crc, + .crypto, + .fp_armv8, + .neon, + .perfmon, + }), + }; + result[@enumToInt(Feature.a53)] = .{ + .llvm_name = "a53", + .description = "Cortex-A53 ARM processors", + .dependencies = featureSet(&[_]Feature{ + .balance_fp_ops, + .crc, + .crypto, + .custom_cheap_as_move, + .fp_armv8, + .fuse_aes, + .neon, + .perfmon, + .use_aa, + .use_postra_scheduler, + }), + }; + result[@enumToInt(Feature.a55)] = .{ + .llvm_name = "a55", + .description = "Cortex-A55 ARM processors", + .dependencies = featureSet(&[_]Feature{ + .crypto, + .dotprod, + .fp_armv8, + .fullfp16, + .fuse_aes, + .neon, + .perfmon, + .rcpc, + .v8_2a, + }), + }; + result[@enumToInt(Feature.a57)] = .{ + .llvm_name = "a57", + .description = "Cortex-A57 ARM processors", + .dependencies = featureSet(&[_]Feature{ + .balance_fp_ops, + .crc, + .crypto, + .custom_cheap_as_move, + .fp_armv8, + .fuse_aes, + .fuse_literals, + .neon, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + }), + }; + result[@enumToInt(Feature.a72)] = .{ + .llvm_name = "a72", + .description = "Cortex-A72 ARM processors", + .dependencies = featureSet(&[_]Feature{ + .crc, + .crypto, + .fp_armv8, + .fuse_aes, + .neon, + .perfmon, + }), + }; + result[@enumToInt(Feature.a73)] = .{ + .llvm_name = "a73", + .description = "Cortex-A73 ARM processors", + .dependencies = featureSet(&[_]Feature{ + .crc, + .crypto, + .fp_armv8, + .fuse_aes, + .neon, + .perfmon, + }), + }; + result[@enumToInt(Feature.a75)] = .{ + .llvm_name = "a75", + .description = "Cortex-A75 ARM processors", + .dependencies = featureSet(&[_]Feature{ + .crypto, + .dotprod, + .fp_armv8, + .fullfp16, + .fuse_aes, + .neon, + .perfmon, + .rcpc, + .v8_2a, + }), + }; + result[@enumToInt(Feature.a76)] = .{ + .llvm_name = "a76", + .description = "Cortex-A76 ARM processors", + .dependencies = featureSet(&[_]Feature{ + .crypto, + .dotprod, + .fp_armv8, + .fullfp16, + .neon, + .rcpc, + .ssbs, + .v8_2a, + }), + }; + result[@enumToInt(Feature.aes)] = .{ + .llvm_name = "aes", + .description = "Enable AES support", + .dependencies = featureSet(&[_]Feature{ + .neon, + }), + }; + result[@enumToInt(Feature.aggressive_fma)] = .{ + .llvm_name = "aggressive-fma", + .description = "Enable Aggressive FMA for floating-point.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.alternate_sextload_cvt_f32_pattern)] = .{ + .llvm_name = "alternate-sextload-cvt-f32-pattern", + .description = "Use alternative pattern for sextload convert to f32", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.altnzcv)] = .{ + .llvm_name = "altnzcv", + .description = "Enable alternative NZCV format for floating point comparisons", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.am)] = .{ + .llvm_name = "am", + .description = "Enable v8.4-A Activity Monitors extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.arith_bcc_fusion)] = .{ + .llvm_name = "arith-bcc-fusion", + .description = "CPU fuses arithmetic+bcc operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.arith_cbz_fusion)] = .{ + .llvm_name = "arith-cbz-fusion", + .description = "CPU fuses arithmetic + cbz/cbnz operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.balance_fp_ops)] = .{ + .llvm_name = "balance-fp-ops", + .description = "balance mix of odd and even D-registers for fp multiply(-accumulate) ops", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.bti)] = .{ + .llvm_name = "bti", + .description = "Enable Branch Target Identification", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.call_saved_x10)] = .{ + .llvm_name = "call-saved-x10", + .description = "Make X10 callee saved.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.call_saved_x11)] = .{ + .llvm_name = "call-saved-x11", + .description = "Make X11 callee saved.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.call_saved_x12)] = .{ + .llvm_name = "call-saved-x12", + .description = "Make X12 callee saved.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.call_saved_x13)] = .{ + .llvm_name = "call-saved-x13", + .description = "Make X13 callee saved.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.call_saved_x14)] = .{ + .llvm_name = "call-saved-x14", + .description = "Make X14 callee saved.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.call_saved_x15)] = .{ + .llvm_name = "call-saved-x15", + .description = "Make X15 callee saved.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.call_saved_x18)] = .{ + .llvm_name = "call-saved-x18", + .description = "Make X18 callee saved.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.call_saved_x8)] = .{ + .llvm_name = "call-saved-x8", + .description = "Make X8 callee saved.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.call_saved_x9)] = .{ + .llvm_name = "call-saved-x9", + .description = "Make X9 callee saved.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ccdp)] = .{ + .llvm_name = "ccdp", + .description = "Enable v8.5 Cache Clean to Point of Deep Persistence", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ccidx)] = .{ + .llvm_name = "ccidx", + .description = "Enable v8.3-A Extend of the CCSIDR number of sets", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ccpp)] = .{ + .llvm_name = "ccpp", + .description = "Enable v8.2 data Cache Clean to Point of Persistence", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.complxnum)] = .{ + .llvm_name = "complxnum", + .description = "Enable v8.3-A Floating-point complex number support", + .dependencies = featureSet(&[_]Feature{ + .neon, + }), + }; + result[@enumToInt(Feature.crc)] = .{ + .llvm_name = "crc", + .description = "Enable ARMv8 CRC-32 checksum instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.crypto)] = .{ + .llvm_name = "crypto", + .description = "Enable cryptographic instructions", + .dependencies = featureSet(&[_]Feature{ + .aes, + .neon, + .sha2, + }), + }; + result[@enumToInt(Feature.custom_cheap_as_move)] = .{ + .llvm_name = "custom-cheap-as-move", + .description = "Use custom handling of cheap instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.cyclone)] = .{ + .llvm_name = "cyclone", + .description = "Cyclone", + .dependencies = featureSet(&[_]Feature{ + .alternate_sextload_cvt_f32_pattern, + .arith_bcc_fusion, + .arith_cbz_fusion, + .crypto, + .disable_latency_sched_heuristic, + .fp_armv8, + .fuse_aes, + .fuse_crypto_eor, + .neon, + .perfmon, + .zcm, + .zcz, + .zcz_fp_workaround, + }), + }; + result[@enumToInt(Feature.disable_latency_sched_heuristic)] = .{ + .llvm_name = "disable-latency-sched-heuristic", + .description = "Disable latency scheduling heuristic", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dit)] = .{ + .llvm_name = "dit", + .description = "Enable v8.4-A Data Independent Timing instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dotprod)] = .{ + .llvm_name = "dotprod", + .description = "Enable dot product support", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.exynos_cheap_as_move)] = .{ + .llvm_name = "exynos-cheap-as-move", + .description = "Use Exynos specific handling of cheap instructions", + .dependencies = featureSet(&[_]Feature{ + .custom_cheap_as_move, + }), + }; + result[@enumToInt(Feature.exynosm1)] = .{ + .llvm_name = "exynosm1", + .description = "Samsung Exynos-M1 processors", + .dependencies = featureSet(&[_]Feature{ + .crc, + .crypto, + .exynos_cheap_as_move, + .force_32bit_jump_tables, + .fuse_aes, + .perfmon, + .slow_misaligned_128store, + .slow_paired_128, + .use_postra_scheduler, + .use_reciprocal_square_root, + .zcz_fp, + }), + }; + result[@enumToInt(Feature.exynosm2)] = .{ + .llvm_name = "exynosm2", + .description = "Samsung Exynos-M2 processors", + .dependencies = featureSet(&[_]Feature{ + .crc, + .crypto, + .exynos_cheap_as_move, + .force_32bit_jump_tables, + .fuse_aes, + .perfmon, + .slow_misaligned_128store, + .slow_paired_128, + .use_postra_scheduler, + .zcz_fp, + }), + }; + result[@enumToInt(Feature.exynosm3)] = .{ + .llvm_name = "exynosm3", + .description = "Samsung Exynos-M3 processors", + .dependencies = featureSet(&[_]Feature{ + .crc, + .crypto, + .exynos_cheap_as_move, + .force_32bit_jump_tables, + .fuse_address, + .fuse_aes, + .fuse_csel, + .fuse_literals, + .lsl_fast, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + .zcz_fp, + }), + }; + result[@enumToInt(Feature.exynosm4)] = .{ + .llvm_name = "exynosm4", + .description = "Samsung Exynos-M4 processors", + .dependencies = featureSet(&[_]Feature{ + .arith_bcc_fusion, + .arith_cbz_fusion, + .crypto, + .dotprod, + .exynos_cheap_as_move, + .force_32bit_jump_tables, + .fullfp16, + .fuse_address, + .fuse_aes, + .fuse_arith_logic, + .fuse_csel, + .fuse_literals, + .lsl_fast, + .perfmon, + .use_postra_scheduler, + .v8_2a, + .zcz, + }), + }; + result[@enumToInt(Feature.falkor)] = .{ + .llvm_name = "falkor", + .description = "Qualcomm Falkor processors", + .dependencies = featureSet(&[_]Feature{ + .crc, + .crypto, + .custom_cheap_as_move, + .fp_armv8, + .lsl_fast, + .neon, + .perfmon, + .predictable_select_expensive, + .rdm, + .slow_strqro_store, + .use_postra_scheduler, + .zcz, + }), + }; + result[@enumToInt(Feature.fmi)] = .{ + .llvm_name = "fmi", + .description = "Enable v8.4-A Flag Manipulation Instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.force_32bit_jump_tables)] = .{ + .llvm_name = "force-32bit-jump-tables", + .description = "Force jump table entries to be 32-bits wide except at MinSize", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fp_armv8)] = .{ + .llvm_name = "fp-armv8", + .description = "Enable ARMv8 FP", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fp16fml)] = .{ + .llvm_name = "fp16fml", + .description = "Enable FP16 FML instructions", + .dependencies = featureSet(&[_]Feature{ + .fullfp16, + }), + }; + result[@enumToInt(Feature.fptoint)] = .{ + .llvm_name = "fptoint", + .description = "Enable FRInt[32|64][Z|X] instructions that round a floating-point number to an integer (in FP format) forcing it to fit into a 32- or 64-bit int", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fullfp16)] = .{ + .llvm_name = "fullfp16", + .description = "Full FP16", + .dependencies = featureSet(&[_]Feature{ + .fp_armv8, + }), + }; + result[@enumToInt(Feature.fuse_address)] = .{ + .llvm_name = "fuse-address", + .description = "CPU fuses address generation and memory operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fuse_aes)] = .{ + .llvm_name = "fuse-aes", + .description = "CPU fuses AES crypto operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fuse_arith_logic)] = .{ + .llvm_name = "fuse-arith-logic", + .description = "CPU fuses arithmetic and logic operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fuse_crypto_eor)] = .{ + .llvm_name = "fuse-crypto-eor", + .description = "CPU fuses AES/PMULL and EOR operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fuse_csel)] = .{ + .llvm_name = "fuse-csel", + .description = "CPU fuses conditional select operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fuse_literals)] = .{ + .llvm_name = "fuse-literals", + .description = "CPU fuses literal generation operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.jsconv)] = .{ + .llvm_name = "jsconv", + .description = "Enable v8.3-A JavaScript FP conversion enchancement", + .dependencies = featureSet(&[_]Feature{ + .fp_armv8, + }), + }; + result[@enumToInt(Feature.kryo)] = .{ + .llvm_name = "kryo", + .description = "Qualcomm Kryo processors", + .dependencies = featureSet(&[_]Feature{ + .crc, + .crypto, + .custom_cheap_as_move, + .fp_armv8, + .lsl_fast, + .neon, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + .zcz, + }), + }; + result[@enumToInt(Feature.lor)] = .{ + .llvm_name = "lor", + .description = "Enables ARM v8.1 Limited Ordering Regions extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.lse)] = .{ + .llvm_name = "lse", + .description = "Enable ARMv8.1 Large System Extension (LSE) atomic instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.lsl_fast)] = .{ + .llvm_name = "lsl-fast", + .description = "CPU has a fastpath logical shift of up to 3 places", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mpam)] = .{ + .llvm_name = "mpam", + .description = "Enable v8.4-A Memory system Partitioning and Monitoring extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mte)] = .{ + .llvm_name = "mte", + .description = "Enable Memory Tagging Extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.neon)] = .{ + .llvm_name = "neon", + .description = "Enable Advanced SIMD instructions", + .dependencies = featureSet(&[_]Feature{ + .fp_armv8, + }), + }; + result[@enumToInt(Feature.no_neg_immediates)] = .{ + .llvm_name = "no-neg-immediates", + .description = "Convert immediates and instructions to their negated or complemented equivalent when the immediate does not fit in the encoding.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.nv)] = .{ + .llvm_name = "nv", + .description = "Enable v8.4-A Nested Virtualization Enchancement", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.pa)] = .{ + .llvm_name = "pa", + .description = "Enable v8.3-A Pointer Authentication enchancement", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.pan)] = .{ + .llvm_name = "pan", + .description = "Enables ARM v8.1 Privileged Access-Never extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.pan_rwv)] = .{ + .llvm_name = "pan-rwv", + .description = "Enable v8.2 PAN s1e1R and s1e1W Variants", + .dependencies = featureSet(&[_]Feature{ + .pan, + }), + }; + result[@enumToInt(Feature.perfmon)] = .{ + .llvm_name = "perfmon", + .description = "Enable ARMv8 PMUv3 Performance Monitors extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.predictable_select_expensive)] = .{ + .llvm_name = "predictable-select-expensive", + .description = "Prefer likely predicted branches over selects", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.predres)] = .{ + .llvm_name = "predres", + .description = "Enable v8.5a execution and data prediction invalidation instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.rand)] = .{ + .llvm_name = "rand", + .description = "Enable Random Number generation instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ras)] = .{ + .llvm_name = "ras", + .description = "Enable ARMv8 Reliability, Availability and Serviceability Extensions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.rasv8_4)] = .{ + .llvm_name = "rasv8_4", + .description = "Enable v8.4-A Reliability, Availability and Serviceability extension", + .dependencies = featureSet(&[_]Feature{ + .ras, + }), + }; + result[@enumToInt(Feature.rcpc)] = .{ + .llvm_name = "rcpc", + .description = "Enable support for RCPC extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.rcpc_immo)] = .{ + .llvm_name = "rcpc-immo", + .description = "Enable v8.4-A RCPC instructions with Immediate Offsets", + .dependencies = featureSet(&[_]Feature{ + .rcpc, + }), + }; + result[@enumToInt(Feature.rdm)] = .{ + .llvm_name = "rdm", + .description = "Enable ARMv8.1 Rounding Double Multiply Add/Subtract instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x1)] = .{ + .llvm_name = "reserve-x1", + .description = "Reserve X1, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x10)] = .{ + .llvm_name = "reserve-x10", + .description = "Reserve X10, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x11)] = .{ + .llvm_name = "reserve-x11", + .description = "Reserve X11, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x12)] = .{ + .llvm_name = "reserve-x12", + .description = "Reserve X12, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x13)] = .{ + .llvm_name = "reserve-x13", + .description = "Reserve X13, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x14)] = .{ + .llvm_name = "reserve-x14", + .description = "Reserve X14, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x15)] = .{ + .llvm_name = "reserve-x15", + .description = "Reserve X15, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x18)] = .{ + .llvm_name = "reserve-x18", + .description = "Reserve X18, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x2)] = .{ + .llvm_name = "reserve-x2", + .description = "Reserve X2, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x20)] = .{ + .llvm_name = "reserve-x20", + .description = "Reserve X20, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x21)] = .{ + .llvm_name = "reserve-x21", + .description = "Reserve X21, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x22)] = .{ + .llvm_name = "reserve-x22", + .description = "Reserve X22, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x23)] = .{ + .llvm_name = "reserve-x23", + .description = "Reserve X23, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x24)] = .{ + .llvm_name = "reserve-x24", + .description = "Reserve X24, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x25)] = .{ + .llvm_name = "reserve-x25", + .description = "Reserve X25, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x26)] = .{ + .llvm_name = "reserve-x26", + .description = "Reserve X26, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x27)] = .{ + .llvm_name = "reserve-x27", + .description = "Reserve X27, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x28)] = .{ + .llvm_name = "reserve-x28", + .description = "Reserve X28, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x3)] = .{ + .llvm_name = "reserve-x3", + .description = "Reserve X3, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x4)] = .{ + .llvm_name = "reserve-x4", + .description = "Reserve X4, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x5)] = .{ + .llvm_name = "reserve-x5", + .description = "Reserve X5, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x6)] = .{ + .llvm_name = "reserve-x6", + .description = "Reserve X6, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x7)] = .{ + .llvm_name = "reserve-x7", + .description = "Reserve X7, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_x9)] = .{ + .llvm_name = "reserve-x9", + .description = "Reserve X9, making it unavailable as a GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.saphira)] = .{ + .llvm_name = "saphira", + .description = "Qualcomm Saphira processors", + .dependencies = featureSet(&[_]Feature{ + .crypto, + .custom_cheap_as_move, + .fp_armv8, + .lsl_fast, + .neon, + .perfmon, + .predictable_select_expensive, + .spe, + .use_postra_scheduler, + .v8_4a, + .zcz, + }), + }; + result[@enumToInt(Feature.sb)] = .{ + .llvm_name = "sb", + .description = "Enable v8.5 Speculation Barrier", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sel2)] = .{ + .llvm_name = "sel2", + .description = "Enable v8.4-A Secure Exception Level 2 extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sha2)] = .{ + .llvm_name = "sha2", + .description = "Enable SHA1 and SHA256 support", + .dependencies = featureSet(&[_]Feature{ + .neon, + }), + }; + result[@enumToInt(Feature.sha3)] = .{ + .llvm_name = "sha3", + .description = "Enable SHA512 and SHA3 support", + .dependencies = featureSet(&[_]Feature{ + .neon, + .sha2, + }), + }; + result[@enumToInt(Feature.slow_misaligned_128store)] = .{ + .llvm_name = "slow-misaligned-128store", + .description = "Misaligned 128 bit stores are slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.slow_paired_128)] = .{ + .llvm_name = "slow-paired-128", + .description = "Paired 128 bit loads and stores are slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.slow_strqro_store)] = .{ + .llvm_name = "slow-strqro-store", + .description = "STR of Q register with register offset is slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sm4)] = .{ + .llvm_name = "sm4", + .description = "Enable SM3 and SM4 support", + .dependencies = featureSet(&[_]Feature{ + .neon, + }), + }; + result[@enumToInt(Feature.spe)] = .{ + .llvm_name = "spe", + .description = "Enable Statistical Profiling extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.specrestrict)] = .{ + .llvm_name = "specrestrict", + .description = "Enable architectural speculation restriction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ssbs)] = .{ + .llvm_name = "ssbs", + .description = "Enable Speculative Store Bypass Safe bit", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.strict_align)] = .{ + .llvm_name = "strict-align", + .description = "Disallow all unaligned memory access", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sve)] = .{ + .llvm_name = "sve", + .description = "Enable Scalable Vector Extension (SVE) instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sve2)] = .{ + .llvm_name = "sve2", + .description = "Enable Scalable Vector Extension 2 (SVE2) instructions", + .dependencies = featureSet(&[_]Feature{ + .sve, + }), + }; + result[@enumToInt(Feature.sve2_aes)] = .{ + .llvm_name = "sve2-aes", + .description = "Enable AES SVE2 instructions", + .dependencies = featureSet(&[_]Feature{ + .aes, + .sve2, + }), + }; + result[@enumToInt(Feature.sve2_bitperm)] = .{ + .llvm_name = "sve2-bitperm", + .description = "Enable bit permutation SVE2 instructions", + .dependencies = featureSet(&[_]Feature{ + .sve2, + }), + }; + result[@enumToInt(Feature.sve2_sha3)] = .{ + .llvm_name = "sve2-sha3", + .description = "Enable SHA3 SVE2 instructions", + .dependencies = featureSet(&[_]Feature{ + .sha3, + .sve2, + }), + }; + result[@enumToInt(Feature.sve2_sm4)] = .{ + .llvm_name = "sve2-sm4", + .description = "Enable SM4 SVE2 instructions", + .dependencies = featureSet(&[_]Feature{ + .sm4, + .sve2, + }), + }; + result[@enumToInt(Feature.thunderx)] = .{ + .llvm_name = "thunderx", + .description = "Cavium ThunderX processors", + .dependencies = featureSet(&[_]Feature{ + .crc, + .crypto, + .fp_armv8, + .neon, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + }), + }; + result[@enumToInt(Feature.thunderx2t99)] = .{ + .llvm_name = "thunderx2t99", + .description = "Cavium ThunderX2 processors", + .dependencies = featureSet(&[_]Feature{ + .aggressive_fma, + .arith_bcc_fusion, + .crc, + .crypto, + .fp_armv8, + .lse, + .neon, + .predictable_select_expensive, + .use_postra_scheduler, + .v8_1a, + }), + }; + result[@enumToInt(Feature.thunderxt81)] = .{ + .llvm_name = "thunderxt81", + .description = "Cavium ThunderX processors", + .dependencies = featureSet(&[_]Feature{ + .crc, + .crypto, + .fp_armv8, + .neon, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + }), + }; + result[@enumToInt(Feature.thunderxt83)] = .{ + .llvm_name = "thunderxt83", + .description = "Cavium ThunderX processors", + .dependencies = featureSet(&[_]Feature{ + .crc, + .crypto, + .fp_armv8, + .neon, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + }), + }; + result[@enumToInt(Feature.thunderxt88)] = .{ + .llvm_name = "thunderxt88", + .description = "Cavium ThunderX processors", + .dependencies = featureSet(&[_]Feature{ + .crc, + .crypto, + .fp_armv8, + .neon, + .perfmon, + .predictable_select_expensive, + .use_postra_scheduler, + }), + }; + result[@enumToInt(Feature.tlb_rmi)] = .{ + .llvm_name = "tlb-rmi", + .description = "Enable v8.4-A TLB Range and Maintenance Instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.tpidr_el1)] = .{ + .llvm_name = "tpidr-el1", + .description = "Permit use of TPIDR_EL1 for the TLS base", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.tpidr_el2)] = .{ + .llvm_name = "tpidr-el2", + .description = "Permit use of TPIDR_EL2 for the TLS base", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.tpidr_el3)] = .{ + .llvm_name = "tpidr-el3", + .description = "Permit use of TPIDR_EL3 for the TLS base", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.tracev8_4)] = .{ + .llvm_name = "tracev8.4", + .description = "Enable v8.4-A Trace extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.tsv110)] = .{ + .llvm_name = "tsv110", + .description = "HiSilicon TS-V110 processors", + .dependencies = featureSet(&[_]Feature{ + .crypto, + .custom_cheap_as_move, + .dotprod, + .fp_armv8, + .fp16fml, + .fullfp16, + .fuse_aes, + .neon, + .perfmon, + .spe, + .use_postra_scheduler, + .v8_2a, + }), + }; + result[@enumToInt(Feature.uaops)] = .{ + .llvm_name = "uaops", + .description = "Enable v8.2 UAO PState", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.use_aa)] = .{ + .llvm_name = "use-aa", + .description = "Use alias analysis during codegen", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.use_postra_scheduler)] = .{ + .llvm_name = "use-postra-scheduler", + .description = "Schedule again after register allocation", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.use_reciprocal_square_root)] = .{ + .llvm_name = "use-reciprocal-square-root", + .description = "Use the reciprocal square root approximation", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.v8a)] = .{ + .llvm_name = null, + .description = "Support ARM v8a instructions", + .dependencies = featureSet(&[_]Feature{ + .fp_armv8, + .neon, + }), + }; + result[@enumToInt(Feature.v8_1a)] = .{ + .llvm_name = "v8.1a", + .description = "Support ARM v8.1a instructions", + .dependencies = featureSet(&[_]Feature{ + .crc, + .lor, + .lse, + .pan, + .rdm, + .vh, + .v8a, + }), + }; + result[@enumToInt(Feature.v8_2a)] = .{ + .llvm_name = "v8.2a", + .description = "Support ARM v8.2a instructions", + .dependencies = featureSet(&[_]Feature{ + .ccpp, + .pan_rwv, + .ras, + .uaops, + .v8_1a, + }), + }; + result[@enumToInt(Feature.v8_3a)] = .{ + .llvm_name = "v8.3a", + .description = "Support ARM v8.3a instructions", + .dependencies = featureSet(&[_]Feature{ + .ccidx, + .complxnum, + .jsconv, + .pa, + .rcpc, + .v8_2a, + }), + }; + result[@enumToInt(Feature.v8_4a)] = .{ + .llvm_name = "v8.4a", + .description = "Support ARM v8.4a instructions", + .dependencies = featureSet(&[_]Feature{ + .am, + .dit, + .dotprod, + .fmi, + .mpam, + .nv, + .rasv8_4, + .rcpc_immo, + .sel2, + .tlb_rmi, + .tracev8_4, + .v8_3a, + }), + }; + result[@enumToInt(Feature.v8_5a)] = .{ + .llvm_name = "v8.5a", + .description = "Support ARM v8.5a instructions", + .dependencies = featureSet(&[_]Feature{ + .altnzcv, + .bti, + .ccdp, + .fptoint, + .predres, + .sb, + .specrestrict, + .ssbs, + .v8_4a, + }), + }; + result[@enumToInt(Feature.vh)] = .{ + .llvm_name = "vh", + .description = "Enables ARM v8.1 Virtual Host extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.zcm)] = .{ + .llvm_name = "zcm", + .description = "Has zero-cycle register moves", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.zcz)] = .{ + .llvm_name = "zcz", + .description = "Has zero-cycle zeroing instructions", + .dependencies = featureSet(&[_]Feature{ + .zcz_fp, + .zcz_gp, + }), + }; + result[@enumToInt(Feature.zcz_fp)] = .{ + .llvm_name = "zcz-fp", + .description = "Has zero-cycle zeroing instructions for FP registers", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.zcz_fp_workaround)] = .{ + .llvm_name = "zcz-fp-workaround", + .description = "The zero-cycle floating-point zeroing instruction has a bug", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.zcz_gp)] = .{ + .llvm_name = "zcz-gp", + .description = "Has zero-cycle zeroing instructions for generic registers", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (result) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const apple_latest = Cpu{ + .name = "apple_latest", + .llvm_name = "apple-latest", + .features = featureSet(&[_]Feature{ + .cyclone, + }), + }; + pub const cortex_a35 = Cpu{ + .name = "cortex_a35", + .llvm_name = "cortex-a35", + .features = featureSet(&[_]Feature{ + .a35, + }), + }; + pub const cortex_a53 = Cpu{ + .name = "cortex_a53", + .llvm_name = "cortex-a53", + .features = featureSet(&[_]Feature{ + .a53, + }), + }; + pub const cortex_a55 = Cpu{ + .name = "cortex_a55", + .llvm_name = "cortex-a55", + .features = featureSet(&[_]Feature{ + .a55, + }), + }; + pub const cortex_a57 = Cpu{ + .name = "cortex_a57", + .llvm_name = "cortex-a57", + .features = featureSet(&[_]Feature{ + .a57, + }), + }; + pub const cortex_a72 = Cpu{ + .name = "cortex_a72", + .llvm_name = "cortex-a72", + .features = featureSet(&[_]Feature{ + .a72, + }), + }; + pub const cortex_a73 = Cpu{ + .name = "cortex_a73", + .llvm_name = "cortex-a73", + .features = featureSet(&[_]Feature{ + .a73, + }), + }; + pub const cortex_a75 = Cpu{ + .name = "cortex_a75", + .llvm_name = "cortex-a75", + .features = featureSet(&[_]Feature{ + .a75, + }), + }; + pub const cortex_a76 = Cpu{ + .name = "cortex_a76", + .llvm_name = "cortex-a76", + .features = featureSet(&[_]Feature{ + .a76, + }), + }; + pub const cortex_a76ae = Cpu{ + .name = "cortex_a76ae", + .llvm_name = "cortex-a76ae", + .features = featureSet(&[_]Feature{ + .a76, + }), + }; + pub const cyclone = Cpu{ + .name = "cyclone", + .llvm_name = "cyclone", + .features = featureSet(&[_]Feature{ + .cyclone, + }), + }; + pub const exynos_m1 = Cpu{ + .name = "exynos_m1", + .llvm_name = "exynos-m1", + .features = featureSet(&[_]Feature{ + .exynosm1, + }), + }; + pub const exynos_m2 = Cpu{ + .name = "exynos_m2", + .llvm_name = "exynos-m2", + .features = featureSet(&[_]Feature{ + .exynosm2, + }), + }; + pub const exynos_m3 = Cpu{ + .name = "exynos_m3", + .llvm_name = "exynos-m3", + .features = featureSet(&[_]Feature{ + .exynosm3, + }), + }; + pub const exynos_m4 = Cpu{ + .name = "exynos_m4", + .llvm_name = "exynos-m4", + .features = featureSet(&[_]Feature{ + .exynosm4, + }), + }; + pub const exynos_m5 = Cpu{ + .name = "exynos_m5", + .llvm_name = "exynos-m5", + .features = featureSet(&[_]Feature{ + .exynosm4, + }), + }; + pub const falkor = Cpu{ + .name = "falkor", + .llvm_name = "falkor", + .features = featureSet(&[_]Feature{ + .falkor, + }), + }; + pub const generic = Cpu{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{ + .fp_armv8, + .fuse_aes, + .neon, + .perfmon, + .use_postra_scheduler, + }), + }; + pub const kryo = Cpu{ + .name = "kryo", + .llvm_name = "kryo", + .features = featureSet(&[_]Feature{ + .kryo, + }), + }; + pub const saphira = Cpu{ + .name = "saphira", + .llvm_name = "saphira", + .features = featureSet(&[_]Feature{ + .saphira, + }), + }; + pub const thunderx = Cpu{ + .name = "thunderx", + .llvm_name = "thunderx", + .features = featureSet(&[_]Feature{ + .thunderx, + }), + }; + pub const thunderx2t99 = Cpu{ + .name = "thunderx2t99", + .llvm_name = "thunderx2t99", + .features = featureSet(&[_]Feature{ + .thunderx2t99, + }), + }; + pub const thunderxt81 = Cpu{ + .name = "thunderxt81", + .llvm_name = "thunderxt81", + .features = featureSet(&[_]Feature{ + .thunderxt81, + }), + }; + pub const thunderxt83 = Cpu{ + .name = "thunderxt83", + .llvm_name = "thunderxt83", + .features = featureSet(&[_]Feature{ + .thunderxt83, + }), + }; + pub const thunderxt88 = Cpu{ + .name = "thunderxt88", + .llvm_name = "thunderxt88", + .features = featureSet(&[_]Feature{ + .thunderxt88, + }), + }; + pub const tsv110 = Cpu{ + .name = "tsv110", + .llvm_name = "tsv110", + .features = featureSet(&[_]Feature{ + .tsv110, + }), + }; +}; + +/// All aarch64 CPUs, sorted alphabetically by name. +/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 +/// compiler has inefficient memory and CPU usage, affecting build times. +pub const all_cpus = &[_]*const Cpu{ + &cpu.apple_latest, + &cpu.cortex_a35, + &cpu.cortex_a53, + &cpu.cortex_a55, + &cpu.cortex_a57, + &cpu.cortex_a72, + &cpu.cortex_a73, + &cpu.cortex_a75, + &cpu.cortex_a76, + &cpu.cortex_a76ae, + &cpu.cyclone, + &cpu.exynos_m1, + &cpu.exynos_m2, + &cpu.exynos_m3, + &cpu.exynos_m4, + &cpu.exynos_m5, + &cpu.falkor, + &cpu.generic, + &cpu.kryo, + &cpu.saphira, + &cpu.thunderx, + &cpu.thunderx2t99, + &cpu.thunderxt81, + &cpu.thunderxt83, + &cpu.thunderxt88, + &cpu.tsv110, +}; diff --git a/lib/std/target/amdgpu.zig b/lib/std/target/amdgpu.zig new file mode 100644 index 0000000000..182b9fa453 --- /dev/null +++ b/lib/std/target/amdgpu.zig @@ -0,0 +1,1315 @@ +const std = @import("../std.zig"); +const Cpu = std.Target.Cpu; + +pub const Feature = enum { + @"16_bit_insts", + DumpCode, + add_no_carry_insts, + aperture_regs, + atomic_fadd_insts, + auto_waitcnt_before_barrier, + ci_insts, + code_object_v3, + cumode, + dl_insts, + dot1_insts, + dot2_insts, + dot3_insts, + dot4_insts, + dot5_insts, + dot6_insts, + dpp, + dpp8, + dumpcode, + enable_ds128, + enable_prt_strict_null, + fast_fmaf, + flat_address_space, + flat_for_global, + flat_global_insts, + flat_inst_offsets, + flat_scratch_insts, + flat_segment_offset_bug, + fma_mix_insts, + fmaf, + fp_exceptions, + fp16_denormals, + fp32_denormals, + fp64, + fp64_denormals, + fp64_fp16_denormals, + gcn3_encoding, + gfx10, + gfx10_insts, + gfx7_gfx8_gfx9_insts, + gfx8_insts, + gfx9, + gfx9_insts, + half_rate_64_ops, + inst_fwd_prefetch_bug, + int_clamp_insts, + inv_2pi_inline_imm, + lds_branch_vmem_war_hazard, + lds_misaligned_bug, + ldsbankcount16, + ldsbankcount32, + load_store_opt, + localmemorysize0, + localmemorysize32768, + localmemorysize65536, + mad_mix_insts, + mai_insts, + max_private_element_size_16, + max_private_element_size_4, + max_private_element_size_8, + mimg_r128, + movrel, + no_data_dep_hazard, + no_sdst_cmpx, + no_sram_ecc_support, + no_xnack_support, + nsa_encoding, + nsa_to_vmem_bug, + offset_3f_bug, + pk_fmac_f16_inst, + promote_alloca, + r128_a16, + register_banking, + s_memrealtime, + scalar_atomics, + scalar_flat_scratch_insts, + scalar_stores, + sdwa, + sdwa_mav, + sdwa_omod, + sdwa_out_mods_vopc, + sdwa_scalar, + sdwa_sdst, + sea_islands, + sgpr_init_bug, + si_scheduler, + smem_to_vector_write_hazard, + southern_islands, + sram_ecc, + trap_handler, + trig_reduced_range, + unaligned_buffer_access, + unaligned_scratch_access, + unpacked_d16_vmem, + unsafe_ds_offset_folding, + vcmpx_exec_war_hazard, + vcmpx_permlane_hazard, + vgpr_index_mode, + vmem_to_scalar_write_hazard, + volcanic_islands, + vop3_literal, + vop3p, + vscnt, + wavefrontsize16, + wavefrontsize32, + wavefrontsize64, + xnack, +}; + +pub usingnamespace Cpu.Feature.feature_set_fns(Feature); + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); + var result: [len]Cpu.Feature = undefined; + result[@enumToInt(Feature.@"16_bit_insts")] = .{ + .llvm_name = "16-bit-insts", + .description = "Has i16/f16 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.DumpCode)] = .{ + .llvm_name = "DumpCode", + .description = "Dump MachineInstrs in the CodeEmitter", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.add_no_carry_insts)] = .{ + .llvm_name = "add-no-carry-insts", + .description = "Have VALU add/sub instructions without carry out", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.aperture_regs)] = .{ + .llvm_name = "aperture-regs", + .description = "Has Memory Aperture Base and Size Registers", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.atomic_fadd_insts)] = .{ + .llvm_name = "atomic-fadd-insts", + .description = "Has buffer_atomic_add_f32, buffer_atomic_pk_add_f16, global_atomic_add_f32, global_atomic_pk_add_f16 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.auto_waitcnt_before_barrier)] = .{ + .llvm_name = "auto-waitcnt-before-barrier", + .description = "Hardware automatically inserts waitcnt before barrier", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ci_insts)] = .{ + .llvm_name = "ci-insts", + .description = "Additional instructions for CI+", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.code_object_v3)] = .{ + .llvm_name = "code-object-v3", + .description = "Generate code object version 3", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.cumode)] = .{ + .llvm_name = "cumode", + .description = "Enable CU wavefront execution mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dl_insts)] = .{ + .llvm_name = "dl-insts", + .description = "Has v_fmac_f32 and v_xnor_b32 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dot1_insts)] = .{ + .llvm_name = "dot1-insts", + .description = "Has v_dot4_i32_i8 and v_dot8_i32_i4 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dot2_insts)] = .{ + .llvm_name = "dot2-insts", + .description = "Has v_dot2_f32_f16, v_dot2_i32_i16, v_dot2_u32_u16, v_dot4_u32_u8, v_dot8_u32_u4 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dot3_insts)] = .{ + .llvm_name = "dot3-insts", + .description = "Has v_dot8c_i32_i4 instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dot4_insts)] = .{ + .llvm_name = "dot4-insts", + .description = "Has v_dot2c_i32_i16 instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dot5_insts)] = .{ + .llvm_name = "dot5-insts", + .description = "Has v_dot2c_f32_f16 instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dot6_insts)] = .{ + .llvm_name = "dot6-insts", + .description = "Has v_dot4c_i32_i8 instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dpp)] = .{ + .llvm_name = "dpp", + .description = "Support DPP (Data Parallel Primitives) extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dpp8)] = .{ + .llvm_name = "dpp8", + .description = "Support DPP8 (Data Parallel Primitives) extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dumpcode)] = .{ + .llvm_name = "dumpcode", + .description = "Dump MachineInstrs in the CodeEmitter", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.enable_ds128)] = .{ + .llvm_name = "enable-ds128", + .description = "Use ds_read|write_b128", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.enable_prt_strict_null)] = .{ + .llvm_name = "enable-prt-strict-null", + .description = "Enable zeroing of result registers for sparse texture fetches", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fast_fmaf)] = .{ + .llvm_name = "fast-fmaf", + .description = "Assuming f32 fma is at least as fast as mul + add", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.flat_address_space)] = .{ + .llvm_name = "flat-address-space", + .description = "Support flat address space", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.flat_for_global)] = .{ + .llvm_name = "flat-for-global", + .description = "Force to generate flat instruction for global", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.flat_global_insts)] = .{ + .llvm_name = "flat-global-insts", + .description = "Have global_* flat memory instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.flat_inst_offsets)] = .{ + .llvm_name = "flat-inst-offsets", + .description = "Flat instructions have immediate offset addressing mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.flat_scratch_insts)] = .{ + .llvm_name = "flat-scratch-insts", + .description = "Have scratch_* flat memory instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.flat_segment_offset_bug)] = .{ + .llvm_name = "flat-segment-offset-bug", + .description = "GFX10 bug, inst_offset ignored in flat segment", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fma_mix_insts)] = .{ + .llvm_name = "fma-mix-insts", + .description = "Has v_fma_mix_f32, v_fma_mixlo_f16, v_fma_mixhi_f16 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fmaf)] = .{ + .llvm_name = "fmaf", + .description = "Enable single precision FMA (not as fast as mul+add, but fused)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fp_exceptions)] = .{ + .llvm_name = "fp-exceptions", + .description = "Enable floating point exceptions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fp16_denormals)] = .{ + .llvm_name = "fp16-denormals", + .description = "Enable half precision denormal handling", + .dependencies = featureSet(&[_]Feature{ + .fp64_fp16_denormals, + }), + }; + result[@enumToInt(Feature.fp32_denormals)] = .{ + .llvm_name = "fp32-denormals", + .description = "Enable single precision denormal handling", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fp64)] = .{ + .llvm_name = "fp64", + .description = "Enable double precision operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fp64_denormals)] = .{ + .llvm_name = "fp64-denormals", + .description = "Enable double and half precision denormal handling", + .dependencies = featureSet(&[_]Feature{ + .fp64, + .fp64_fp16_denormals, + }), + }; + result[@enumToInt(Feature.fp64_fp16_denormals)] = .{ + .llvm_name = "fp64-fp16-denormals", + .description = "Enable double and half precision denormal handling", + .dependencies = featureSet(&[_]Feature{ + .fp64, + }), + }; + result[@enumToInt(Feature.gcn3_encoding)] = .{ + .llvm_name = "gcn3-encoding", + .description = "Encoding format for VI", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.gfx10)] = .{ + .llvm_name = "gfx10", + .description = "GFX10 GPU generation", + .dependencies = featureSet(&[_]Feature{ + .@"16_bit_insts", + .add_no_carry_insts, + .aperture_regs, + .ci_insts, + .dpp, + .dpp8, + .fast_fmaf, + .flat_address_space, + .flat_global_insts, + .flat_inst_offsets, + .flat_scratch_insts, + .fma_mix_insts, + .fp64, + .gfx10_insts, + .gfx8_insts, + .gfx9_insts, + .int_clamp_insts, + .inv_2pi_inline_imm, + .localmemorysize65536, + .mimg_r128, + .movrel, + .no_data_dep_hazard, + .no_sdst_cmpx, + .no_sram_ecc_support, + .pk_fmac_f16_inst, + .register_banking, + .s_memrealtime, + .sdwa, + .sdwa_omod, + .sdwa_scalar, + .sdwa_sdst, + .vop3_literal, + .vop3p, + .vscnt, + }), + }; + result[@enumToInt(Feature.gfx10_insts)] = .{ + .llvm_name = "gfx10-insts", + .description = "Additional instructions for GFX10+", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.gfx7_gfx8_gfx9_insts)] = .{ + .llvm_name = "gfx7-gfx8-gfx9-insts", + .description = "Instructions shared in GFX7, GFX8, GFX9", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.gfx8_insts)] = .{ + .llvm_name = "gfx8-insts", + .description = "Additional instructions for GFX8+", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.gfx9)] = .{ + .llvm_name = "gfx9", + .description = "GFX9 GPU generation", + .dependencies = featureSet(&[_]Feature{ + .@"16_bit_insts", + .add_no_carry_insts, + .aperture_regs, + .ci_insts, + .dpp, + .fast_fmaf, + .flat_address_space, + .flat_global_insts, + .flat_inst_offsets, + .flat_scratch_insts, + .fp64, + .gcn3_encoding, + .gfx7_gfx8_gfx9_insts, + .gfx8_insts, + .gfx9_insts, + .int_clamp_insts, + .inv_2pi_inline_imm, + .localmemorysize65536, + .r128_a16, + .s_memrealtime, + .scalar_atomics, + .scalar_flat_scratch_insts, + .scalar_stores, + .sdwa, + .sdwa_omod, + .sdwa_scalar, + .sdwa_sdst, + .vgpr_index_mode, + .vop3p, + .wavefrontsize64, + }), + }; + result[@enumToInt(Feature.gfx9_insts)] = .{ + .llvm_name = "gfx9-insts", + .description = "Additional instructions for GFX9+", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.half_rate_64_ops)] = .{ + .llvm_name = "half-rate-64-ops", + .description = "Most fp64 instructions are half rate instead of quarter", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.inst_fwd_prefetch_bug)] = .{ + .llvm_name = "inst-fwd-prefetch-bug", + .description = "S_INST_PREFETCH instruction causes shader to hang", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.int_clamp_insts)] = .{ + .llvm_name = "int-clamp-insts", + .description = "Support clamp for integer destination", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.inv_2pi_inline_imm)] = .{ + .llvm_name = "inv-2pi-inline-imm", + .description = "Has 1 / (2 * pi) as inline immediate", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.lds_branch_vmem_war_hazard)] = .{ + .llvm_name = "lds-branch-vmem-war-hazard", + .description = "Switching between LDS and VMEM-tex not waiting VM_VSRC=0", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.lds_misaligned_bug)] = .{ + .llvm_name = "lds-misaligned-bug", + .description = "Some GFX10 bug with misaligned multi-dword LDS access in WGP mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ldsbankcount16)] = .{ + .llvm_name = "ldsbankcount16", + .description = "The number of LDS banks per compute unit.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ldsbankcount32)] = .{ + .llvm_name = "ldsbankcount32", + .description = "The number of LDS banks per compute unit.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.load_store_opt)] = .{ + .llvm_name = "load-store-opt", + .description = "Enable SI load/store optimizer pass", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.localmemorysize0)] = .{ + .llvm_name = "localmemorysize0", + .description = "The size of local memory in bytes", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.localmemorysize32768)] = .{ + .llvm_name = "localmemorysize32768", + .description = "The size of local memory in bytes", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.localmemorysize65536)] = .{ + .llvm_name = "localmemorysize65536", + .description = "The size of local memory in bytes", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mad_mix_insts)] = .{ + .llvm_name = "mad-mix-insts", + .description = "Has v_mad_mix_f32, v_mad_mixlo_f16, v_mad_mixhi_f16 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mai_insts)] = .{ + .llvm_name = "mai-insts", + .description = "Has mAI instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.max_private_element_size_16)] = .{ + .llvm_name = "max-private-element-size-16", + .description = "Maximum private access size may be 16", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.max_private_element_size_4)] = .{ + .llvm_name = "max-private-element-size-4", + .description = "Maximum private access size may be 4", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.max_private_element_size_8)] = .{ + .llvm_name = "max-private-element-size-8", + .description = "Maximum private access size may be 8", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mimg_r128)] = .{ + .llvm_name = "mimg-r128", + .description = "Support 128-bit texture resources", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.movrel)] = .{ + .llvm_name = "movrel", + .description = "Has v_movrel*_b32 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.no_data_dep_hazard)] = .{ + .llvm_name = "no-data-dep-hazard", + .description = "Does not need SW waitstates", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.no_sdst_cmpx)] = .{ + .llvm_name = "no-sdst-cmpx", + .description = "V_CMPX does not write VCC/SGPR in addition to EXEC", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.no_sram_ecc_support)] = .{ + .llvm_name = "no-sram-ecc-support", + .description = "Hardware does not support SRAM ECC", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.no_xnack_support)] = .{ + .llvm_name = "no-xnack-support", + .description = "Hardware does not support XNACK", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.nsa_encoding)] = .{ + .llvm_name = "nsa-encoding", + .description = "Support NSA encoding for image instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.nsa_to_vmem_bug)] = .{ + .llvm_name = "nsa-to-vmem-bug", + .description = "MIMG-NSA followed by VMEM fail if EXEC_LO or EXEC_HI equals zero", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.offset_3f_bug)] = .{ + .llvm_name = "offset-3f-bug", + .description = "Branch offset of 3f hardware bug", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.pk_fmac_f16_inst)] = .{ + .llvm_name = "pk-fmac-f16-inst", + .description = "Has v_pk_fmac_f16 instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.promote_alloca)] = .{ + .llvm_name = "promote-alloca", + .description = "Enable promote alloca pass", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.r128_a16)] = .{ + .llvm_name = "r128-a16", + .description = "Support 16 bit coordindates/gradients/lod/clamp/mip types on gfx9", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.register_banking)] = .{ + .llvm_name = "register-banking", + .description = "Has register banking", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.s_memrealtime)] = .{ + .llvm_name = "s-memrealtime", + .description = "Has s_memrealtime instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.scalar_atomics)] = .{ + .llvm_name = "scalar-atomics", + .description = "Has atomic scalar memory instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.scalar_flat_scratch_insts)] = .{ + .llvm_name = "scalar-flat-scratch-insts", + .description = "Have s_scratch_* flat memory instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.scalar_stores)] = .{ + .llvm_name = "scalar-stores", + .description = "Has store scalar memory instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sdwa)] = .{ + .llvm_name = "sdwa", + .description = "Support SDWA (Sub-DWORD Addressing) extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sdwa_mav)] = .{ + .llvm_name = "sdwa-mav", + .description = "Support v_mac_f32/f16 with SDWA (Sub-DWORD Addressing) extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sdwa_omod)] = .{ + .llvm_name = "sdwa-omod", + .description = "Support OMod with SDWA (Sub-DWORD Addressing) extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sdwa_out_mods_vopc)] = .{ + .llvm_name = "sdwa-out-mods-vopc", + .description = "Support clamp for VOPC with SDWA (Sub-DWORD Addressing) extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sdwa_scalar)] = .{ + .llvm_name = "sdwa-scalar", + .description = "Support scalar register with SDWA (Sub-DWORD Addressing) extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sdwa_sdst)] = .{ + .llvm_name = "sdwa-sdst", + .description = "Support scalar dst for VOPC with SDWA (Sub-DWORD Addressing) extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sea_islands)] = .{ + .llvm_name = "sea-islands", + .description = "SEA_ISLANDS GPU generation", + .dependencies = featureSet(&[_]Feature{ + .ci_insts, + .flat_address_space, + .fp64, + .gfx7_gfx8_gfx9_insts, + .localmemorysize65536, + .mimg_r128, + .movrel, + .no_sram_ecc_support, + .trig_reduced_range, + .wavefrontsize64, + }), + }; + result[@enumToInt(Feature.sgpr_init_bug)] = .{ + .llvm_name = "sgpr-init-bug", + .description = "VI SGPR initialization bug requiring a fixed SGPR allocation size", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.si_scheduler)] = .{ + .llvm_name = "si-scheduler", + .description = "Enable SI Machine Scheduler", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.smem_to_vector_write_hazard)] = .{ + .llvm_name = "smem-to-vector-write-hazard", + .description = "s_load_dword followed by v_cmp page faults", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.southern_islands)] = .{ + .llvm_name = "southern-islands", + .description = "SOUTHERN_ISLANDS GPU generation", + .dependencies = featureSet(&[_]Feature{ + .fp64, + .ldsbankcount32, + .localmemorysize32768, + .mimg_r128, + .movrel, + .no_sram_ecc_support, + .no_xnack_support, + .trig_reduced_range, + .wavefrontsize64, + }), + }; + result[@enumToInt(Feature.sram_ecc)] = .{ + .llvm_name = "sram-ecc", + .description = "Enable SRAM ECC", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.trap_handler)] = .{ + .llvm_name = "trap-handler", + .description = "Trap handler support", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.trig_reduced_range)] = .{ + .llvm_name = "trig-reduced-range", + .description = "Requires use of fract on arguments to trig instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.unaligned_buffer_access)] = .{ + .llvm_name = "unaligned-buffer-access", + .description = "Support unaligned global loads and stores", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.unaligned_scratch_access)] = .{ + .llvm_name = "unaligned-scratch-access", + .description = "Support unaligned scratch loads and stores", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.unpacked_d16_vmem)] = .{ + .llvm_name = "unpacked-d16-vmem", + .description = "Has unpacked d16 vmem instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.unsafe_ds_offset_folding)] = .{ + .llvm_name = "unsafe-ds-offset-folding", + .description = "Force using DS instruction immediate offsets on SI", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vcmpx_exec_war_hazard)] = .{ + .llvm_name = "vcmpx-exec-war-hazard", + .description = "V_CMPX WAR hazard on EXEC (V_CMPX issue ONLY)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vcmpx_permlane_hazard)] = .{ + .llvm_name = "vcmpx-permlane-hazard", + .description = "TODO: describe me", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vgpr_index_mode)] = .{ + .llvm_name = "vgpr-index-mode", + .description = "Has VGPR mode register indexing", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vmem_to_scalar_write_hazard)] = .{ + .llvm_name = "vmem-to-scalar-write-hazard", + .description = "VMEM instruction followed by scalar writing to EXEC mask, M0 or SGPR leads to incorrect execution.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.volcanic_islands)] = .{ + .llvm_name = "volcanic-islands", + .description = "VOLCANIC_ISLANDS GPU generation", + .dependencies = featureSet(&[_]Feature{ + .@"16_bit_insts", + .ci_insts, + .dpp, + .flat_address_space, + .fp64, + .gcn3_encoding, + .gfx7_gfx8_gfx9_insts, + .gfx8_insts, + .int_clamp_insts, + .inv_2pi_inline_imm, + .localmemorysize65536, + .mimg_r128, + .movrel, + .no_sram_ecc_support, + .s_memrealtime, + .scalar_stores, + .sdwa, + .sdwa_mav, + .sdwa_out_mods_vopc, + .trig_reduced_range, + .vgpr_index_mode, + .wavefrontsize64, + }), + }; + result[@enumToInt(Feature.vop3_literal)] = .{ + .llvm_name = "vop3-literal", + .description = "Can use one literal in VOP3", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vop3p)] = .{ + .llvm_name = "vop3p", + .description = "Has VOP3P packed instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vscnt)] = .{ + .llvm_name = "vscnt", + .description = "Has separate store vscnt counter", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.wavefrontsize16)] = .{ + .llvm_name = "wavefrontsize16", + .description = "The number of threads per wavefront", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.wavefrontsize32)] = .{ + .llvm_name = "wavefrontsize32", + .description = "The number of threads per wavefront", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.wavefrontsize64)] = .{ + .llvm_name = "wavefrontsize64", + .description = "The number of threads per wavefront", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.xnack)] = .{ + .llvm_name = "xnack", + .description = "Enable XNACK support", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (result) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const bonaire = Cpu{ + .name = "bonaire", + .llvm_name = "bonaire", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount32, + .no_xnack_support, + .sea_islands, + }), + }; + pub const carrizo = Cpu{ + .name = "carrizo", + .llvm_name = "carrizo", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .fast_fmaf, + .half_rate_64_ops, + .ldsbankcount32, + .unpacked_d16_vmem, + .volcanic_islands, + .xnack, + }), + }; + pub const fiji = Cpu{ + .name = "fiji", + .llvm_name = "fiji", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount32, + .no_xnack_support, + .unpacked_d16_vmem, + .volcanic_islands, + }), + }; + pub const generic = Cpu{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{ + .wavefrontsize64, + }), + }; + pub const generic_hsa = Cpu{ + .name = "generic_hsa", + .llvm_name = "generic-hsa", + .features = featureSet(&[_]Feature{ + .flat_address_space, + .wavefrontsize64, + }), + }; + pub const gfx1010 = Cpu{ + .name = "gfx1010", + .llvm_name = "gfx1010", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .dl_insts, + .flat_segment_offset_bug, + .gfx10, + .inst_fwd_prefetch_bug, + .lds_branch_vmem_war_hazard, + .lds_misaligned_bug, + .ldsbankcount32, + .no_xnack_support, + .nsa_encoding, + .nsa_to_vmem_bug, + .offset_3f_bug, + .scalar_atomics, + .scalar_flat_scratch_insts, + .scalar_stores, + .smem_to_vector_write_hazard, + .vcmpx_exec_war_hazard, + .vcmpx_permlane_hazard, + .vmem_to_scalar_write_hazard, + .wavefrontsize32, + }), + }; + pub const gfx1011 = Cpu{ + .name = "gfx1011", + .llvm_name = "gfx1011", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .dl_insts, + .dot1_insts, + .dot2_insts, + .dot5_insts, + .dot6_insts, + .flat_segment_offset_bug, + .gfx10, + .inst_fwd_prefetch_bug, + .lds_branch_vmem_war_hazard, + .ldsbankcount32, + .no_xnack_support, + .nsa_encoding, + .nsa_to_vmem_bug, + .offset_3f_bug, + .scalar_atomics, + .scalar_flat_scratch_insts, + .scalar_stores, + .smem_to_vector_write_hazard, + .vcmpx_exec_war_hazard, + .vcmpx_permlane_hazard, + .vmem_to_scalar_write_hazard, + .wavefrontsize32, + }), + }; + pub const gfx1012 = Cpu{ + .name = "gfx1012", + .llvm_name = "gfx1012", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .dl_insts, + .dot1_insts, + .dot2_insts, + .dot5_insts, + .dot6_insts, + .flat_segment_offset_bug, + .gfx10, + .inst_fwd_prefetch_bug, + .lds_branch_vmem_war_hazard, + .lds_misaligned_bug, + .ldsbankcount32, + .no_xnack_support, + .nsa_encoding, + .nsa_to_vmem_bug, + .offset_3f_bug, + .scalar_atomics, + .scalar_flat_scratch_insts, + .scalar_stores, + .smem_to_vector_write_hazard, + .vcmpx_exec_war_hazard, + .vcmpx_permlane_hazard, + .vmem_to_scalar_write_hazard, + .wavefrontsize32, + }), + }; + pub const gfx600 = Cpu{ + .name = "gfx600", + .llvm_name = "gfx600", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .fast_fmaf, + .half_rate_64_ops, + .ldsbankcount32, + .no_xnack_support, + .southern_islands, + }), + }; + pub const gfx601 = Cpu{ + .name = "gfx601", + .llvm_name = "gfx601", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount32, + .no_xnack_support, + .southern_islands, + }), + }; + pub const gfx700 = Cpu{ + .name = "gfx700", + .llvm_name = "gfx700", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount32, + .no_xnack_support, + .sea_islands, + }), + }; + pub const gfx701 = Cpu{ + .name = "gfx701", + .llvm_name = "gfx701", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .fast_fmaf, + .half_rate_64_ops, + .ldsbankcount32, + .no_xnack_support, + .sea_islands, + }), + }; + pub const gfx702 = Cpu{ + .name = "gfx702", + .llvm_name = "gfx702", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .fast_fmaf, + .ldsbankcount16, + .no_xnack_support, + .sea_islands, + }), + }; + pub const gfx703 = Cpu{ + .name = "gfx703", + .llvm_name = "gfx703", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount16, + .no_xnack_support, + .sea_islands, + }), + }; + pub const gfx704 = Cpu{ + .name = "gfx704", + .llvm_name = "gfx704", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount32, + .no_xnack_support, + .sea_islands, + }), + }; + pub const gfx801 = Cpu{ + .name = "gfx801", + .llvm_name = "gfx801", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .fast_fmaf, + .half_rate_64_ops, + .ldsbankcount32, + .unpacked_d16_vmem, + .volcanic_islands, + .xnack, + }), + }; + pub const gfx802 = Cpu{ + .name = "gfx802", + .llvm_name = "gfx802", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount32, + .no_xnack_support, + .sgpr_init_bug, + .unpacked_d16_vmem, + .volcanic_islands, + }), + }; + pub const gfx803 = Cpu{ + .name = "gfx803", + .llvm_name = "gfx803", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount32, + .no_xnack_support, + .unpacked_d16_vmem, + .volcanic_islands, + }), + }; + pub const gfx810 = Cpu{ + .name = "gfx810", + .llvm_name = "gfx810", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount16, + .volcanic_islands, + .xnack, + }), + }; + pub const gfx900 = Cpu{ + .name = "gfx900", + .llvm_name = "gfx900", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .gfx9, + .ldsbankcount32, + .mad_mix_insts, + .no_sram_ecc_support, + .no_xnack_support, + }), + }; + pub const gfx902 = Cpu{ + .name = "gfx902", + .llvm_name = "gfx902", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .gfx9, + .ldsbankcount32, + .mad_mix_insts, + .no_sram_ecc_support, + .xnack, + }), + }; + pub const gfx904 = Cpu{ + .name = "gfx904", + .llvm_name = "gfx904", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .fma_mix_insts, + .gfx9, + .ldsbankcount32, + .no_sram_ecc_support, + .no_xnack_support, + }), + }; + pub const gfx906 = Cpu{ + .name = "gfx906", + .llvm_name = "gfx906", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .dl_insts, + .dot1_insts, + .dot2_insts, + .fma_mix_insts, + .gfx9, + .half_rate_64_ops, + .ldsbankcount32, + .no_xnack_support, + }), + }; + pub const gfx908 = Cpu{ + .name = "gfx908", + .llvm_name = "gfx908", + .features = featureSet(&[_]Feature{ + .atomic_fadd_insts, + .code_object_v3, + .dl_insts, + .dot1_insts, + .dot2_insts, + .dot3_insts, + .dot4_insts, + .dot5_insts, + .dot6_insts, + .fma_mix_insts, + .gfx9, + .half_rate_64_ops, + .ldsbankcount32, + .mai_insts, + .pk_fmac_f16_inst, + .sram_ecc, + }), + }; + pub const gfx909 = Cpu{ + .name = "gfx909", + .llvm_name = "gfx909", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .gfx9, + .ldsbankcount32, + .mad_mix_insts, + .xnack, + }), + }; + pub const hainan = Cpu{ + .name = "hainan", + .llvm_name = "hainan", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount32, + .no_xnack_support, + .southern_islands, + }), + }; + pub const hawaii = Cpu{ + .name = "hawaii", + .llvm_name = "hawaii", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .fast_fmaf, + .half_rate_64_ops, + .ldsbankcount32, + .no_xnack_support, + .sea_islands, + }), + }; + pub const iceland = Cpu{ + .name = "iceland", + .llvm_name = "iceland", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount32, + .no_xnack_support, + .sgpr_init_bug, + .unpacked_d16_vmem, + .volcanic_islands, + }), + }; + pub const kabini = Cpu{ + .name = "kabini", + .llvm_name = "kabini", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount16, + .no_xnack_support, + .sea_islands, + }), + }; + pub const kaveri = Cpu{ + .name = "kaveri", + .llvm_name = "kaveri", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount32, + .no_xnack_support, + .sea_islands, + }), + }; + pub const mullins = Cpu{ + .name = "mullins", + .llvm_name = "mullins", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount16, + .no_xnack_support, + .sea_islands, + }), + }; + pub const oland = Cpu{ + .name = "oland", + .llvm_name = "oland", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount32, + .no_xnack_support, + .southern_islands, + }), + }; + pub const pitcairn = Cpu{ + .name = "pitcairn", + .llvm_name = "pitcairn", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount32, + .no_xnack_support, + .southern_islands, + }), + }; + pub const polaris10 = Cpu{ + .name = "polaris10", + .llvm_name = "polaris10", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount32, + .no_xnack_support, + .unpacked_d16_vmem, + .volcanic_islands, + }), + }; + pub const polaris11 = Cpu{ + .name = "polaris11", + .llvm_name = "polaris11", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount32, + .no_xnack_support, + .unpacked_d16_vmem, + .volcanic_islands, + }), + }; + pub const stoney = Cpu{ + .name = "stoney", + .llvm_name = "stoney", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount16, + .volcanic_islands, + .xnack, + }), + }; + pub const tahiti = Cpu{ + .name = "tahiti", + .llvm_name = "tahiti", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .fast_fmaf, + .half_rate_64_ops, + .ldsbankcount32, + .no_xnack_support, + .southern_islands, + }), + }; + pub const tonga = Cpu{ + .name = "tonga", + .llvm_name = "tonga", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount32, + .no_xnack_support, + .sgpr_init_bug, + .unpacked_d16_vmem, + .volcanic_islands, + }), + }; + pub const verde = Cpu{ + .name = "verde", + .llvm_name = "verde", + .features = featureSet(&[_]Feature{ + .code_object_v3, + .ldsbankcount32, + .no_xnack_support, + .southern_islands, + }), + }; +}; + +/// All amdgpu CPUs, sorted alphabetically by name. +/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 +/// compiler has inefficient memory and CPU usage, affecting build times. +pub const all_cpus = &[_]*const Cpu{ + &cpu.bonaire, + &cpu.carrizo, + &cpu.fiji, + &cpu.generic, + &cpu.generic_hsa, + &cpu.gfx1010, + &cpu.gfx1011, + &cpu.gfx1012, + &cpu.gfx600, + &cpu.gfx601, + &cpu.gfx700, + &cpu.gfx701, + &cpu.gfx702, + &cpu.gfx703, + &cpu.gfx704, + &cpu.gfx801, + &cpu.gfx802, + &cpu.gfx803, + &cpu.gfx810, + &cpu.gfx900, + &cpu.gfx902, + &cpu.gfx904, + &cpu.gfx906, + &cpu.gfx908, + &cpu.gfx909, + &cpu.hainan, + &cpu.hawaii, + &cpu.iceland, + &cpu.kabini, + &cpu.kaveri, + &cpu.mullins, + &cpu.oland, + &cpu.pitcairn, + &cpu.polaris10, + &cpu.polaris11, + &cpu.stoney, + &cpu.tahiti, + &cpu.tonga, + &cpu.verde, +}; diff --git a/lib/std/target/arm.zig b/lib/std/target/arm.zig new file mode 100644 index 0000000000..62a4e1e835 --- /dev/null +++ b/lib/std/target/arm.zig @@ -0,0 +1,2333 @@ +const std = @import("../std.zig"); +const Cpu = std.Target.Cpu; + +pub const Feature = enum { + @"32bit", + @"8msecext", + a12, + a15, + a17, + a32, + a35, + a5, + a53, + a55, + a57, + a7, + a72, + a73, + a75, + a76, + a8, + a9, + aclass, + acquire_release, + aes, + armv2, + armv2a, + armv3, + armv3m, + armv4, + armv4t, + armv5t, + armv5te, + armv5tej, + armv6, + armv6_m, + armv6j, + armv6k, + armv6kz, + armv6s_m, + armv6t2, + armv7_a, + armv7_m, + armv7_r, + armv7e_m, + armv7k, + armv7s, + armv7ve, + armv8_a, + armv8_m_base, + armv8_m_main, + armv8_r, + armv8_1_a, + armv8_1_m_main, + armv8_2_a, + armv8_3_a, + armv8_4_a, + armv8_5_a, + avoid_movs_shop, + avoid_partial_cpsr, + cheap_predicable_cpsr, + crc, + crypto, + d32, + db, + dfb, + disable_postra_scheduler, + dont_widen_vmovs, + dotprod, + dsp, + execute_only, + expand_fp_mlx, + exynos, + fp_armv8, + fp_armv8d16, + fp_armv8d16sp, + fp_armv8sp, + fp16, + fp16fml, + fp64, + fpao, + fpregs, + fpregs16, + fpregs64, + fullfp16, + fuse_aes, + fuse_literals, + hwdiv, + hwdiv_arm, + iwmmxt, + iwmmxt2, + krait, + kryo, + lob, + long_calls, + loop_align, + m3, + mclass, + mp, + muxed_units, + mve, + mve_fp, + nacl_trap, + neon, + neon_fpmovs, + neonfp, + no_branch_predictor, + no_movt, + no_neg_immediates, + noarm, + nonpipelined_vfp, + perfmon, + prefer_ishst, + prefer_vmovsr, + prof_unpr, + r4, + r5, + r52, + r7, + ras, + rclass, + read_tp_hard, + reserve_r9, + ret_addr_stack, + sb, + sha2, + slow_fp_brcc, + slow_load_D_subreg, + slow_odd_reg, + slow_vdup32, + slow_vgetlni32, + slowfpvmlx, + soft_float, + splat_vfp_neon, + strict_align, + swift, + thumb_mode, + thumb2, + trustzone, + use_aa, + use_misched, + v4t, + v5t, + v5te, + v6, + v6k, + v6m, + v6t2, + v7, + v7clrex, + v8, + v8_1a, + v8_1m_main, + v8_2a, + v8_3a, + v8_4a, + v8_5a, + v8m, + v8m_main, + vfp2, + vfp2d16, + vfp2d16sp, + vfp2sp, + vfp3, + vfp3d16, + vfp3d16sp, + vfp3sp, + vfp4, + vfp4d16, + vfp4d16sp, + vfp4sp, + virtualization, + vldn_align, + vmlx_forwarding, + vmlx_hazards, + wide_stride_vfp, + xscale, + zcz, +}; + +pub usingnamespace Cpu.Feature.feature_set_fns(Feature); + +pub const all_features = blk: { + @setEvalBranchQuota(10000); + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); + var result: [len]Cpu.Feature = undefined; + result[@enumToInt(Feature.@"32bit")] = .{ + .llvm_name = "32bit", + .description = "Prefer 32-bit Thumb instrs", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.@"8msecext")] = .{ + .llvm_name = "8msecext", + .description = "Enable support for ARMv8-M Security Extensions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.a12)] = .{ + .llvm_name = "a12", + .description = "Cortex-A12 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.a15)] = .{ + .llvm_name = "a15", + .description = "Cortex-A15 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.a17)] = .{ + .llvm_name = "a17", + .description = "Cortex-A17 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.a32)] = .{ + .llvm_name = "a32", + .description = "Cortex-A32 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.a35)] = .{ + .llvm_name = "a35", + .description = "Cortex-A35 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.a5)] = .{ + .llvm_name = "a5", + .description = "Cortex-A5 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.a53)] = .{ + .llvm_name = "a53", + .description = "Cortex-A53 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.a55)] = .{ + .llvm_name = "a55", + .description = "Cortex-A55 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.a57)] = .{ + .llvm_name = "a57", + .description = "Cortex-A57 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.a7)] = .{ + .llvm_name = "a7", + .description = "Cortex-A7 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.a72)] = .{ + .llvm_name = "a72", + .description = "Cortex-A72 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.a73)] = .{ + .llvm_name = "a73", + .description = "Cortex-A73 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.a75)] = .{ + .llvm_name = "a75", + .description = "Cortex-A75 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.a76)] = .{ + .llvm_name = "a76", + .description = "Cortex-A76 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.a8)] = .{ + .llvm_name = "a8", + .description = "Cortex-A8 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.a9)] = .{ + .llvm_name = "a9", + .description = "Cortex-A9 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.aclass)] = .{ + .llvm_name = "aclass", + .description = "Is application profile ('A' series)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.acquire_release)] = .{ + .llvm_name = "acquire-release", + .description = "Has v8 acquire/release (lda/ldaex etc) instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.aes)] = .{ + .llvm_name = "aes", + .description = "Enable AES support", + .dependencies = featureSet(&[_]Feature{ + .neon, + }), + }; + result[@enumToInt(Feature.armv2)] = .{ + .llvm_name = "armv2", + .description = "ARMv2 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.armv2a)] = .{ + .llvm_name = "armv2a", + .description = "ARMv2a architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.armv3)] = .{ + .llvm_name = "armv3", + .description = "ARMv3 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.armv3m)] = .{ + .llvm_name = "armv3m", + .description = "ARMv3m architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.armv4)] = .{ + .llvm_name = "armv4", + .description = "ARMv4 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.armv4t)] = .{ + .llvm_name = "armv4t", + .description = "ARMv4t architecture", + .dependencies = featureSet(&[_]Feature{ + .v4t, + }), + }; + result[@enumToInt(Feature.armv5t)] = .{ + .llvm_name = "armv5t", + .description = "ARMv5t architecture", + .dependencies = featureSet(&[_]Feature{ + .v5t, + }), + }; + result[@enumToInt(Feature.armv5te)] = .{ + .llvm_name = "armv5te", + .description = "ARMv5te architecture", + .dependencies = featureSet(&[_]Feature{ + .v5te, + }), + }; + result[@enumToInt(Feature.armv5tej)] = .{ + .llvm_name = "armv5tej", + .description = "ARMv5tej architecture", + .dependencies = featureSet(&[_]Feature{ + .v5te, + }), + }; + result[@enumToInt(Feature.armv6)] = .{ + .llvm_name = "armv6", + .description = "ARMv6 architecture", + .dependencies = featureSet(&[_]Feature{ + .dsp, + .v6, + }), + }; + result[@enumToInt(Feature.armv6_m)] = .{ + .llvm_name = "armv6-m", + .description = "ARMv6m architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .mclass, + .noarm, + .strict_align, + .thumb_mode, + .v6m, + }), + }; + result[@enumToInt(Feature.armv6j)] = .{ + .llvm_name = "armv6j", + .description = "ARMv7a architecture", + .dependencies = featureSet(&[_]Feature{ + .armv6, + }), + }; + result[@enumToInt(Feature.armv6k)] = .{ + .llvm_name = "armv6k", + .description = "ARMv6k architecture", + .dependencies = featureSet(&[_]Feature{ + .v6k, + }), + }; + result[@enumToInt(Feature.armv6kz)] = .{ + .llvm_name = "armv6kz", + .description = "ARMv6kz architecture", + .dependencies = featureSet(&[_]Feature{ + .trustzone, + .v6k, + }), + }; + result[@enumToInt(Feature.armv6s_m)] = .{ + .llvm_name = "armv6s-m", + .description = "ARMv6sm architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .mclass, + .noarm, + .strict_align, + .thumb_mode, + .v6m, + }), + }; + result[@enumToInt(Feature.armv6t2)] = .{ + .llvm_name = "armv6t2", + .description = "ARMv6t2 architecture", + .dependencies = featureSet(&[_]Feature{ + .dsp, + .v6t2, + }), + }; + result[@enumToInt(Feature.armv7_a)] = .{ + .llvm_name = "armv7-a", + .description = "ARMv7a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .db, + .dsp, + .neon, + .v7, + }), + }; + result[@enumToInt(Feature.armv7_m)] = .{ + .llvm_name = "armv7-m", + .description = "ARMv7m architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .hwdiv, + .mclass, + .noarm, + .thumb_mode, + .thumb2, + .v7, + }), + }; + result[@enumToInt(Feature.armv7_r)] = .{ + .llvm_name = "armv7-r", + .description = "ARMv7r architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .dsp, + .hwdiv, + .rclass, + .v7, + }), + }; + result[@enumToInt(Feature.armv7e_m)] = .{ + .llvm_name = "armv7e-m", + .description = "ARMv7em architecture", + .dependencies = featureSet(&[_]Feature{ + .db, + .dsp, + .hwdiv, + .mclass, + .noarm, + .thumb_mode, + .thumb2, + .v7, + }), + }; + result[@enumToInt(Feature.armv7k)] = .{ + .llvm_name = "armv7k", + .description = "ARMv7a architecture", + .dependencies = featureSet(&[_]Feature{ + .armv7_a, + }), + }; + result[@enumToInt(Feature.armv7s)] = .{ + .llvm_name = "armv7s", + .description = "ARMv7a architecture", + .dependencies = featureSet(&[_]Feature{ + .armv7_a, + }), + }; + result[@enumToInt(Feature.armv7ve)] = .{ + .llvm_name = "armv7ve", + .description = "ARMv7ve architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .db, + .dsp, + .mp, + .neon, + .trustzone, + .v7, + .virtualization, + }), + }; + result[@enumToInt(Feature.armv8_a)] = .{ + .llvm_name = "armv8-a", + .description = "ARMv8a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .mp, + .neon, + .trustzone, + .v8, + .virtualization, + }), + }; + result[@enumToInt(Feature.armv8_m_base)] = .{ + .llvm_name = "armv8-m.base", + .description = "ARMv8mBaseline architecture", + .dependencies = featureSet(&[_]Feature{ + .@"8msecext", + .acquire_release, + .db, + .hwdiv, + .mclass, + .noarm, + .strict_align, + .thumb_mode, + .v7clrex, + .v8m, + }), + }; + result[@enumToInt(Feature.armv8_m_main)] = .{ + .llvm_name = "armv8-m.main", + .description = "ARMv8mMainline architecture", + .dependencies = featureSet(&[_]Feature{ + .@"8msecext", + .acquire_release, + .db, + .hwdiv, + .mclass, + .noarm, + .thumb_mode, + .v8m_main, + }), + }; + result[@enumToInt(Feature.armv8_r)] = .{ + .llvm_name = "armv8-r", + .description = "ARMv8r architecture", + .dependencies = featureSet(&[_]Feature{ + .crc, + .db, + .dfb, + .dsp, + .fp_armv8, + .mp, + .neon, + .rclass, + .v8, + .virtualization, + }), + }; + result[@enumToInt(Feature.armv8_1_a)] = .{ + .llvm_name = "armv8.1-a", + .description = "ARMv81a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .mp, + .neon, + .trustzone, + .v8_1a, + .virtualization, + }), + }; + result[@enumToInt(Feature.armv8_1_m_main)] = .{ + .llvm_name = "armv8.1-m.main", + .description = "ARMv81mMainline architecture", + .dependencies = featureSet(&[_]Feature{ + .@"8msecext", + .acquire_release, + .db, + .hwdiv, + .lob, + .mclass, + .noarm, + .ras, + .thumb_mode, + .v8_1m_main, + }), + }; + result[@enumToInt(Feature.armv8_2_a)] = .{ + .llvm_name = "armv8.2-a", + .description = "ARMv82a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .mp, + .neon, + .ras, + .trustzone, + .v8_2a, + .virtualization, + }), + }; + result[@enumToInt(Feature.armv8_3_a)] = .{ + .llvm_name = "armv8.3-a", + .description = "ARMv83a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dsp, + .fp_armv8, + .mp, + .neon, + .ras, + .trustzone, + .v8_3a, + .virtualization, + }), + }; + result[@enumToInt(Feature.armv8_4_a)] = .{ + .llvm_name = "armv8.4-a", + .description = "ARMv84a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dotprod, + .dsp, + .fp_armv8, + .mp, + .neon, + .ras, + .trustzone, + .v8_4a, + .virtualization, + }), + }; + result[@enumToInt(Feature.armv8_5_a)] = .{ + .llvm_name = "armv8.5-a", + .description = "ARMv85a architecture", + .dependencies = featureSet(&[_]Feature{ + .aclass, + .crc, + .crypto, + .db, + .dotprod, + .dsp, + .fp_armv8, + .mp, + .neon, + .ras, + .trustzone, + .v8_5a, + .virtualization, + }), + }; + result[@enumToInt(Feature.avoid_movs_shop)] = .{ + .llvm_name = "avoid-movs-shop", + .description = "Avoid movs instructions with shifter operand", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.avoid_partial_cpsr)] = .{ + .llvm_name = "avoid-partial-cpsr", + .description = "Avoid CPSR partial update for OOO execution", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.cheap_predicable_cpsr)] = .{ + .llvm_name = "cheap-predicable-cpsr", + .description = "Disable +1 predication cost for instructions updating CPSR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.crc)] = .{ + .llvm_name = "crc", + .description = "Enable support for CRC instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.crypto)] = .{ + .llvm_name = "crypto", + .description = "Enable support for Cryptography extensions", + .dependencies = featureSet(&[_]Feature{ + .aes, + .neon, + .sha2, + }), + }; + result[@enumToInt(Feature.d32)] = .{ + .llvm_name = "d32", + .description = "Extend FP to 32 double registers", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.db)] = .{ + .llvm_name = "db", + .description = "Has data barrier (dmb/dsb) instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dfb)] = .{ + .llvm_name = "dfb", + .description = "Has full data barrier (dfb) instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.disable_postra_scheduler)] = .{ + .llvm_name = "disable-postra-scheduler", + .description = "Don't schedule again after register allocation", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dont_widen_vmovs)] = .{ + .llvm_name = "dont-widen-vmovs", + .description = "Don't widen VMOVS to VMOVD", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dotprod)] = .{ + .llvm_name = "dotprod", + .description = "Enable support for dot product instructions", + .dependencies = featureSet(&[_]Feature{ + .neon, + }), + }; + result[@enumToInt(Feature.dsp)] = .{ + .llvm_name = "dsp", + .description = "Supports DSP instructions in ARM and/or Thumb2", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.execute_only)] = .{ + .llvm_name = "execute-only", + .description = "Enable the generation of execute only code.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.expand_fp_mlx)] = .{ + .llvm_name = "expand-fp-mlx", + .description = "Expand VFP/NEON MLA/MLS instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.exynos)] = .{ + .llvm_name = "exynos", + .description = "Samsung Exynos processors", + .dependencies = featureSet(&[_]Feature{ + .crc, + .crypto, + .expand_fp_mlx, + .fuse_aes, + .fuse_literals, + .hwdiv, + .hwdiv_arm, + .prof_unpr, + .ret_addr_stack, + .slow_fp_brcc, + .slow_vdup32, + .slow_vgetlni32, + .slowfpvmlx, + .splat_vfp_neon, + .use_aa, + .wide_stride_vfp, + .zcz, + }), + }; + result[@enumToInt(Feature.fp_armv8)] = .{ + .llvm_name = "fp-armv8", + .description = "Enable ARMv8 FP", + .dependencies = featureSet(&[_]Feature{ + .fp_armv8d16, + .fp_armv8sp, + .vfp4, + }), + }; + result[@enumToInt(Feature.fp_armv8d16)] = .{ + .llvm_name = "fp-armv8d16", + .description = "Enable ARMv8 FP with only 16 d-registers", + .dependencies = featureSet(&[_]Feature{ + .fp_armv8d16sp, + .fp64, + .vfp4d16, + }), + }; + result[@enumToInt(Feature.fp_armv8d16sp)] = .{ + .llvm_name = "fp-armv8d16sp", + .description = "Enable ARMv8 FP with only 16 d-registers and no double precision", + .dependencies = featureSet(&[_]Feature{ + .vfp4d16sp, + }), + }; + result[@enumToInt(Feature.fp_armv8sp)] = .{ + .llvm_name = "fp-armv8sp", + .description = "Enable ARMv8 FP with no double precision", + .dependencies = featureSet(&[_]Feature{ + .d32, + .fp_armv8d16sp, + .vfp4sp, + }), + }; + result[@enumToInt(Feature.fp16)] = .{ + .llvm_name = "fp16", + .description = "Enable half-precision floating point", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fp16fml)] = .{ + .llvm_name = "fp16fml", + .description = "Enable full half-precision floating point fml instructions", + .dependencies = featureSet(&[_]Feature{ + .fullfp16, + }), + }; + result[@enumToInt(Feature.fp64)] = .{ + .llvm_name = "fp64", + .description = "Floating point unit supports double precision", + .dependencies = featureSet(&[_]Feature{ + .fpregs64, + }), + }; + result[@enumToInt(Feature.fpao)] = .{ + .llvm_name = "fpao", + .description = "Enable fast computation of positive address offsets", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fpregs)] = .{ + .llvm_name = "fpregs", + .description = "Enable FP registers", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fpregs16)] = .{ + .llvm_name = "fpregs16", + .description = "Enable 16-bit FP registers", + .dependencies = featureSet(&[_]Feature{ + .fpregs, + }), + }; + result[@enumToInt(Feature.fpregs64)] = .{ + .llvm_name = "fpregs64", + .description = "Enable 64-bit FP registers", + .dependencies = featureSet(&[_]Feature{ + .fpregs, + }), + }; + result[@enumToInt(Feature.fullfp16)] = .{ + .llvm_name = "fullfp16", + .description = "Enable full half-precision floating point", + .dependencies = featureSet(&[_]Feature{ + .fp_armv8d16sp, + .fpregs16, + }), + }; + result[@enumToInt(Feature.fuse_aes)] = .{ + .llvm_name = "fuse-aes", + .description = "CPU fuses AES crypto operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fuse_literals)] = .{ + .llvm_name = "fuse-literals", + .description = "CPU fuses literal generation operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.hwdiv)] = .{ + .llvm_name = "hwdiv", + .description = "Enable divide instructions in Thumb", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.hwdiv_arm)] = .{ + .llvm_name = "hwdiv-arm", + .description = "Enable divide instructions in ARM mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.iwmmxt)] = .{ + .llvm_name = "iwmmxt", + .description = "ARMv5te architecture", + .dependencies = featureSet(&[_]Feature{ + .armv5te, + }), + }; + result[@enumToInt(Feature.iwmmxt2)] = .{ + .llvm_name = "iwmmxt2", + .description = "ARMv5te architecture", + .dependencies = featureSet(&[_]Feature{ + .armv5te, + }), + }; + result[@enumToInt(Feature.krait)] = .{ + .llvm_name = "krait", + .description = "Qualcomm Krait processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.kryo)] = .{ + .llvm_name = "kryo", + .description = "Qualcomm Kryo processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.lob)] = .{ + .llvm_name = "lob", + .description = "Enable Low Overhead Branch extensions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.long_calls)] = .{ + .llvm_name = "long-calls", + .description = "Generate calls via indirect call instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.loop_align)] = .{ + .llvm_name = "loop-align", + .description = "Prefer 32-bit alignment for loops", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.m3)] = .{ + .llvm_name = "m3", + .description = "Cortex-M3 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mclass)] = .{ + .llvm_name = "mclass", + .description = "Is microcontroller profile ('M' series)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mp)] = .{ + .llvm_name = "mp", + .description = "Supports Multiprocessing extension", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.muxed_units)] = .{ + .llvm_name = "muxed-units", + .description = "Has muxed AGU and NEON/FPU", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mve)] = .{ + .llvm_name = "mve", + .description = "Support M-Class Vector Extension with integer ops", + .dependencies = featureSet(&[_]Feature{ + .dsp, + .fpregs16, + .fpregs64, + .v8_1m_main, + }), + }; + result[@enumToInt(Feature.mve_fp)] = .{ + .llvm_name = "mve.fp", + .description = "Support M-Class Vector Extension with integer and floating ops", + .dependencies = featureSet(&[_]Feature{ + .fp_armv8d16sp, + .fullfp16, + .mve, + }), + }; + result[@enumToInt(Feature.nacl_trap)] = .{ + .llvm_name = "nacl-trap", + .description = "NaCl trap", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.neon)] = .{ + .llvm_name = "neon", + .description = "Enable NEON instructions", + .dependencies = featureSet(&[_]Feature{ + .vfp3, + }), + }; + result[@enumToInt(Feature.neon_fpmovs)] = .{ + .llvm_name = "neon-fpmovs", + .description = "Convert VMOVSR, VMOVRS, VMOVS to NEON", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.neonfp)] = .{ + .llvm_name = "neonfp", + .description = "Use NEON for single precision FP", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.no_branch_predictor)] = .{ + .llvm_name = "no-branch-predictor", + .description = "Has no branch predictor", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.no_movt)] = .{ + .llvm_name = "no-movt", + .description = "Don't use movt/movw pairs for 32-bit imms", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.no_neg_immediates)] = .{ + .llvm_name = "no-neg-immediates", + .description = "Convert immediates and instructions to their negated or complemented equivalent when the immediate does not fit in the encoding.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.noarm)] = .{ + .llvm_name = "noarm", + .description = "Does not support ARM mode execution", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.nonpipelined_vfp)] = .{ + .llvm_name = "nonpipelined-vfp", + .description = "VFP instructions are not pipelined", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.perfmon)] = .{ + .llvm_name = "perfmon", + .description = "Enable support for Performance Monitor extensions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.prefer_ishst)] = .{ + .llvm_name = "prefer-ishst", + .description = "Prefer ISHST barriers", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.prefer_vmovsr)] = .{ + .llvm_name = "prefer-vmovsr", + .description = "Prefer VMOVSR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.prof_unpr)] = .{ + .llvm_name = "prof-unpr", + .description = "Is profitable to unpredicate", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.r4)] = .{ + .llvm_name = "r4", + .description = "Cortex-R4 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.r5)] = .{ + .llvm_name = "r5", + .description = "Cortex-R5 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.r52)] = .{ + .llvm_name = "r52", + .description = "Cortex-R52 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.r7)] = .{ + .llvm_name = "r7", + .description = "Cortex-R7 ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ras)] = .{ + .llvm_name = "ras", + .description = "Enable Reliability, Availability and Serviceability extensions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.rclass)] = .{ + .llvm_name = "rclass", + .description = "Is realtime profile ('R' series)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.read_tp_hard)] = .{ + .llvm_name = "read-tp-hard", + .description = "Reading thread pointer from register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserve_r9)] = .{ + .llvm_name = "reserve-r9", + .description = "Reserve R9, making it unavailable as GPR", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ret_addr_stack)] = .{ + .llvm_name = "ret-addr-stack", + .description = "Has return address stack", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sb)] = .{ + .llvm_name = "sb", + .description = "Enable v8.5a Speculation Barrier", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sha2)] = .{ + .llvm_name = "sha2", + .description = "Enable SHA1 and SHA256 support", + .dependencies = featureSet(&[_]Feature{ + .neon, + }), + }; + result[@enumToInt(Feature.slow_fp_brcc)] = .{ + .llvm_name = "slow-fp-brcc", + .description = "FP compare + branch is slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.slow_load_D_subreg)] = .{ + .llvm_name = "slow-load-D-subreg", + .description = "Loading into D subregs is slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.slow_odd_reg)] = .{ + .llvm_name = "slow-odd-reg", + .description = "VLDM/VSTM starting with an odd register is slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.slow_vdup32)] = .{ + .llvm_name = "slow-vdup32", + .description = "Has slow VDUP32 - prefer VMOV", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.slow_vgetlni32)] = .{ + .llvm_name = "slow-vgetlni32", + .description = "Has slow VGETLNi32 - prefer VMOV", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.slowfpvmlx)] = .{ + .llvm_name = "slowfpvmlx", + .description = "Disable VFP / NEON MAC instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.soft_float)] = .{ + .llvm_name = "soft-float", + .description = "Use software floating point features.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.splat_vfp_neon)] = .{ + .llvm_name = "splat-vfp-neon", + .description = "Splat register from VFP to NEON", + .dependencies = featureSet(&[_]Feature{ + .dont_widen_vmovs, + }), + }; + result[@enumToInt(Feature.strict_align)] = .{ + .llvm_name = "strict-align", + .description = "Disallow all unaligned memory access", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.swift)] = .{ + .llvm_name = "swift", + .description = "Swift ARM processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.thumb_mode)] = .{ + .llvm_name = "thumb-mode", + .description = "Thumb mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.thumb2)] = .{ + .llvm_name = "thumb2", + .description = "Enable Thumb2 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.trustzone)] = .{ + .llvm_name = "trustzone", + .description = "Enable support for TrustZone security extensions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.use_aa)] = .{ + .llvm_name = "use-aa", + .description = "Use alias analysis during codegen", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.use_misched)] = .{ + .llvm_name = "use-misched", + .description = "Use the MachineScheduler", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.v4t)] = .{ + .llvm_name = "v4t", + .description = "Support ARM v4T instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.v5t)] = .{ + .llvm_name = "v5t", + .description = "Support ARM v5T instructions", + .dependencies = featureSet(&[_]Feature{ + .v4t, + }), + }; + result[@enumToInt(Feature.v5te)] = .{ + .llvm_name = "v5te", + .description = "Support ARM v5TE, v5TEj, and v5TExp instructions", + .dependencies = featureSet(&[_]Feature{ + .v5t, + }), + }; + result[@enumToInt(Feature.v6)] = .{ + .llvm_name = "v6", + .description = "Support ARM v6 instructions", + .dependencies = featureSet(&[_]Feature{ + .v5te, + }), + }; + result[@enumToInt(Feature.v6k)] = .{ + .llvm_name = "v6k", + .description = "Support ARM v6k instructions", + .dependencies = featureSet(&[_]Feature{ + .v6, + }), + }; + result[@enumToInt(Feature.v6m)] = .{ + .llvm_name = "v6m", + .description = "Support ARM v6M instructions", + .dependencies = featureSet(&[_]Feature{ + .v6, + }), + }; + result[@enumToInt(Feature.v6t2)] = .{ + .llvm_name = "v6t2", + .description = "Support ARM v6t2 instructions", + .dependencies = featureSet(&[_]Feature{ + .thumb2, + .v6k, + .v8m, + }), + }; + result[@enumToInt(Feature.v7)] = .{ + .llvm_name = "v7", + .description = "Support ARM v7 instructions", + .dependencies = featureSet(&[_]Feature{ + .perfmon, + .v6t2, + .v7clrex, + }), + }; + result[@enumToInt(Feature.v7clrex)] = .{ + .llvm_name = "v7clrex", + .description = "Has v7 clrex instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.v8)] = .{ + .llvm_name = "v8", + .description = "Support ARM v8 instructions", + .dependencies = featureSet(&[_]Feature{ + .acquire_release, + .v7, + }), + }; + result[@enumToInt(Feature.v8_1a)] = .{ + .llvm_name = "v8.1a", + .description = "Support ARM v8.1a instructions", + .dependencies = featureSet(&[_]Feature{ + .v8, + }), + }; + result[@enumToInt(Feature.v8_1m_main)] = .{ + .llvm_name = "v8.1m.main", + .description = "Support ARM v8-1M Mainline instructions", + .dependencies = featureSet(&[_]Feature{ + .v8m_main, + }), + }; + result[@enumToInt(Feature.v8_2a)] = .{ + .llvm_name = "v8.2a", + .description = "Support ARM v8.2a instructions", + .dependencies = featureSet(&[_]Feature{ + .v8_1a, + }), + }; + result[@enumToInt(Feature.v8_3a)] = .{ + .llvm_name = "v8.3a", + .description = "Support ARM v8.3a instructions", + .dependencies = featureSet(&[_]Feature{ + .v8_2a, + }), + }; + result[@enumToInt(Feature.v8_4a)] = .{ + .llvm_name = "v8.4a", + .description = "Support ARM v8.4a instructions", + .dependencies = featureSet(&[_]Feature{ + .dotprod, + .v8_3a, + }), + }; + result[@enumToInt(Feature.v8_5a)] = .{ + .llvm_name = "v8.5a", + .description = "Support ARM v8.5a instructions", + .dependencies = featureSet(&[_]Feature{ + .sb, + .v8_4a, + }), + }; + result[@enumToInt(Feature.v8m)] = .{ + .llvm_name = "v8m", + .description = "Support ARM v8M Baseline instructions", + .dependencies = featureSet(&[_]Feature{ + .v6m, + }), + }; + result[@enumToInt(Feature.v8m_main)] = .{ + .llvm_name = "v8m.main", + .description = "Support ARM v8M Mainline instructions", + .dependencies = featureSet(&[_]Feature{ + .v7, + }), + }; + result[@enumToInt(Feature.vfp2)] = .{ + .llvm_name = "vfp2", + .description = "Enable VFP2 instructions", + .dependencies = featureSet(&[_]Feature{ + .vfp2d16, + .vfp2sp, + }), + }; + result[@enumToInt(Feature.vfp2d16)] = .{ + .llvm_name = "vfp2d16", + .description = "Enable VFP2 instructions", + .dependencies = featureSet(&[_]Feature{ + .fp64, + .vfp2d16sp, + }), + }; + result[@enumToInt(Feature.vfp2d16sp)] = .{ + .llvm_name = "vfp2d16sp", + .description = "Enable VFP2 instructions with no double precision", + .dependencies = featureSet(&[_]Feature{ + .fpregs, + }), + }; + result[@enumToInt(Feature.vfp2sp)] = .{ + .llvm_name = "vfp2sp", + .description = "Enable VFP2 instructions with no double precision", + .dependencies = featureSet(&[_]Feature{ + .vfp2d16sp, + }), + }; + result[@enumToInt(Feature.vfp3)] = .{ + .llvm_name = "vfp3", + .description = "Enable VFP3 instructions", + .dependencies = featureSet(&[_]Feature{ + .vfp3d16, + .vfp3sp, + }), + }; + result[@enumToInt(Feature.vfp3d16)] = .{ + .llvm_name = "vfp3d16", + .description = "Enable VFP3 instructions with only 16 d-registers", + .dependencies = featureSet(&[_]Feature{ + .fp64, + .vfp2, + .vfp3d16sp, + }), + }; + result[@enumToInt(Feature.vfp3d16sp)] = .{ + .llvm_name = "vfp3d16sp", + .description = "Enable VFP3 instructions with only 16 d-registers and no double precision", + .dependencies = featureSet(&[_]Feature{ + .vfp2sp, + }), + }; + result[@enumToInt(Feature.vfp3sp)] = .{ + .llvm_name = "vfp3sp", + .description = "Enable VFP3 instructions with no double precision", + .dependencies = featureSet(&[_]Feature{ + .d32, + .vfp3d16sp, + }), + }; + result[@enumToInt(Feature.vfp4)] = .{ + .llvm_name = "vfp4", + .description = "Enable VFP4 instructions", + .dependencies = featureSet(&[_]Feature{ + .fp16, + .vfp3, + .vfp4d16, + .vfp4sp, + }), + }; + result[@enumToInt(Feature.vfp4d16)] = .{ + .llvm_name = "vfp4d16", + .description = "Enable VFP4 instructions with only 16 d-registers", + .dependencies = featureSet(&[_]Feature{ + .fp16, + .fp64, + .vfp3d16, + .vfp4d16sp, + }), + }; + result[@enumToInt(Feature.vfp4d16sp)] = .{ + .llvm_name = "vfp4d16sp", + .description = "Enable VFP4 instructions with only 16 d-registers and no double precision", + .dependencies = featureSet(&[_]Feature{ + .fp16, + .vfp3d16sp, + }), + }; + result[@enumToInt(Feature.vfp4sp)] = .{ + .llvm_name = "vfp4sp", + .description = "Enable VFP4 instructions with no double precision", + .dependencies = featureSet(&[_]Feature{ + .d32, + .fp16, + .vfp3sp, + .vfp4d16sp, + }), + }; + result[@enumToInt(Feature.virtualization)] = .{ + .llvm_name = "virtualization", + .description = "Supports Virtualization extension", + .dependencies = featureSet(&[_]Feature{ + .hwdiv, + .hwdiv_arm, + }), + }; + result[@enumToInt(Feature.vldn_align)] = .{ + .llvm_name = "vldn-align", + .description = "Check for VLDn unaligned access", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vmlx_forwarding)] = .{ + .llvm_name = "vmlx-forwarding", + .description = "Has multiplier accumulator forwarding", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vmlx_hazards)] = .{ + .llvm_name = "vmlx-hazards", + .description = "Has VMLx hazards", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.wide_stride_vfp)] = .{ + .llvm_name = "wide-stride-vfp", + .description = "Use a wide stride when allocating VFP registers", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.xscale)] = .{ + .llvm_name = "xscale", + .description = "ARMv5te architecture", + .dependencies = featureSet(&[_]Feature{ + .armv5te, + }), + }; + result[@enumToInt(Feature.zcz)] = .{ + .llvm_name = "zcz", + .description = "Has zero-cycle zeroing instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (result) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const arm1020e = Cpu{ + .name = "arm1020e", + .llvm_name = "arm1020e", + .features = featureSet(&[_]Feature{ + .armv5te, + }), + }; + pub const arm1020t = Cpu{ + .name = "arm1020t", + .llvm_name = "arm1020t", + .features = featureSet(&[_]Feature{ + .armv5t, + }), + }; + pub const arm1022e = Cpu{ + .name = "arm1022e", + .llvm_name = "arm1022e", + .features = featureSet(&[_]Feature{ + .armv5te, + }), + }; + pub const arm10e = Cpu{ + .name = "arm10e", + .llvm_name = "arm10e", + .features = featureSet(&[_]Feature{ + .armv5te, + }), + }; + pub const arm10tdmi = Cpu{ + .name = "arm10tdmi", + .llvm_name = "arm10tdmi", + .features = featureSet(&[_]Feature{ + .armv5t, + }), + }; + pub const arm1136j_s = Cpu{ + .name = "arm1136j_s", + .llvm_name = "arm1136j-s", + .features = featureSet(&[_]Feature{ + .armv6, + }), + }; + pub const arm1136jf_s = Cpu{ + .name = "arm1136jf_s", + .llvm_name = "arm1136jf-s", + .features = featureSet(&[_]Feature{ + .armv6, + .slowfpvmlx, + .vfp2, + }), + }; + pub const arm1156t2_s = Cpu{ + .name = "arm1156t2_s", + .llvm_name = "arm1156t2-s", + .features = featureSet(&[_]Feature{ + .armv6t2, + }), + }; + pub const arm1156t2f_s = Cpu{ + .name = "arm1156t2f_s", + .llvm_name = "arm1156t2f-s", + .features = featureSet(&[_]Feature{ + .armv6t2, + .slowfpvmlx, + .vfp2, + }), + }; + pub const arm1176j_s = Cpu{ + .name = "arm1176j_s", + .llvm_name = "arm1176j-s", + .features = featureSet(&[_]Feature{ + .armv6kz, + }), + }; + pub const arm1176jz_s = Cpu{ + .name = "arm1176jz_s", + .llvm_name = "arm1176jz-s", + .features = featureSet(&[_]Feature{ + .armv6kz, + }), + }; + pub const arm1176jzf_s = Cpu{ + .name = "arm1176jzf_s", + .llvm_name = "arm1176jzf-s", + .features = featureSet(&[_]Feature{ + .armv6kz, + .slowfpvmlx, + .vfp2, + }), + }; + pub const arm710t = Cpu{ + .name = "arm710t", + .llvm_name = "arm710t", + .features = featureSet(&[_]Feature{ + .armv4t, + }), + }; + pub const arm720t = Cpu{ + .name = "arm720t", + .llvm_name = "arm720t", + .features = featureSet(&[_]Feature{ + .armv4t, + }), + }; + pub const arm7tdmi = Cpu{ + .name = "arm7tdmi", + .llvm_name = "arm7tdmi", + .features = featureSet(&[_]Feature{ + .armv4t, + }), + }; + pub const arm7tdmi_s = Cpu{ + .name = "arm7tdmi_s", + .llvm_name = "arm7tdmi-s", + .features = featureSet(&[_]Feature{ + .armv4t, + }), + }; + pub const arm8 = Cpu{ + .name = "arm8", + .llvm_name = "arm8", + .features = featureSet(&[_]Feature{ + .armv4, + }), + }; + pub const arm810 = Cpu{ + .name = "arm810", + .llvm_name = "arm810", + .features = featureSet(&[_]Feature{ + .armv4, + }), + }; + pub const arm9 = Cpu{ + .name = "arm9", + .llvm_name = "arm9", + .features = featureSet(&[_]Feature{ + .armv4t, + }), + }; + pub const arm920 = Cpu{ + .name = "arm920", + .llvm_name = "arm920", + .features = featureSet(&[_]Feature{ + .armv4t, + }), + }; + pub const arm920t = Cpu{ + .name = "arm920t", + .llvm_name = "arm920t", + .features = featureSet(&[_]Feature{ + .armv4t, + }), + }; + pub const arm922t = Cpu{ + .name = "arm922t", + .llvm_name = "arm922t", + .features = featureSet(&[_]Feature{ + .armv4t, + }), + }; + pub const arm926ej_s = Cpu{ + .name = "arm926ej_s", + .llvm_name = "arm926ej-s", + .features = featureSet(&[_]Feature{ + .armv5te, + }), + }; + pub const arm940t = Cpu{ + .name = "arm940t", + .llvm_name = "arm940t", + .features = featureSet(&[_]Feature{ + .armv4t, + }), + }; + pub const arm946e_s = Cpu{ + .name = "arm946e_s", + .llvm_name = "arm946e-s", + .features = featureSet(&[_]Feature{ + .armv5te, + }), + }; + pub const arm966e_s = Cpu{ + .name = "arm966e_s", + .llvm_name = "arm966e-s", + .features = featureSet(&[_]Feature{ + .armv5te, + }), + }; + pub const arm968e_s = Cpu{ + .name = "arm968e_s", + .llvm_name = "arm968e-s", + .features = featureSet(&[_]Feature{ + .armv5te, + }), + }; + pub const arm9e = Cpu{ + .name = "arm9e", + .llvm_name = "arm9e", + .features = featureSet(&[_]Feature{ + .armv5te, + }), + }; + pub const arm9tdmi = Cpu{ + .name = "arm9tdmi", + .llvm_name = "arm9tdmi", + .features = featureSet(&[_]Feature{ + .armv4t, + }), + }; + pub const cortex_a12 = Cpu{ + .name = "cortex_a12", + .llvm_name = "cortex-a12", + .features = featureSet(&[_]Feature{ + .a12, + .armv7_a, + .avoid_partial_cpsr, + .mp, + .ret_addr_stack, + .trustzone, + .vfp4, + .virtualization, + .vmlx_forwarding, + }), + }; + pub const cortex_a15 = Cpu{ + .name = "cortex_a15", + .llvm_name = "cortex-a15", + .features = featureSet(&[_]Feature{ + .a15, + .armv7_a, + .avoid_partial_cpsr, + .dont_widen_vmovs, + .mp, + .muxed_units, + .ret_addr_stack, + .splat_vfp_neon, + .trustzone, + .vfp4, + .virtualization, + .vldn_align, + }), + }; + pub const cortex_a17 = Cpu{ + .name = "cortex_a17", + .llvm_name = "cortex-a17", + .features = featureSet(&[_]Feature{ + .a17, + .armv7_a, + .avoid_partial_cpsr, + .mp, + .ret_addr_stack, + .trustzone, + .vfp4, + .virtualization, + .vmlx_forwarding, + }), + }; + pub const cortex_a32 = Cpu{ + .name = "cortex_a32", + .llvm_name = "cortex-a32", + .features = featureSet(&[_]Feature{ + .armv8_a, + .crc, + .crypto, + .hwdiv, + .hwdiv_arm, + }), + }; + pub const cortex_a35 = Cpu{ + .name = "cortex_a35", + .llvm_name = "cortex-a35", + .features = featureSet(&[_]Feature{ + .a35, + .armv8_a, + .crc, + .crypto, + .hwdiv, + .hwdiv_arm, + }), + }; + pub const cortex_a5 = Cpu{ + .name = "cortex_a5", + .llvm_name = "cortex-a5", + .features = featureSet(&[_]Feature{ + .a5, + .armv7_a, + .mp, + .ret_addr_stack, + .slow_fp_brcc, + .slowfpvmlx, + .trustzone, + .vfp4, + .vmlx_forwarding, + }), + }; + pub const cortex_a53 = Cpu{ + .name = "cortex_a53", + .llvm_name = "cortex-a53", + .features = featureSet(&[_]Feature{ + .a53, + .armv8_a, + .crc, + .crypto, + .fpao, + .hwdiv, + .hwdiv_arm, + }), + }; + pub const cortex_a55 = Cpu{ + .name = "cortex_a55", + .llvm_name = "cortex-a55", + .features = featureSet(&[_]Feature{ + .a55, + .armv8_2_a, + .dotprod, + .hwdiv, + .hwdiv_arm, + }), + }; + pub const cortex_a57 = Cpu{ + .name = "cortex_a57", + .llvm_name = "cortex-a57", + .features = featureSet(&[_]Feature{ + .a57, + .armv8_a, + .avoid_partial_cpsr, + .cheap_predicable_cpsr, + .crc, + .crypto, + .fpao, + .hwdiv, + .hwdiv_arm, + }), + }; + pub const cortex_a7 = Cpu{ + .name = "cortex_a7", + .llvm_name = "cortex-a7", + .features = featureSet(&[_]Feature{ + .a7, + .armv7_a, + .mp, + .ret_addr_stack, + .slow_fp_brcc, + .slowfpvmlx, + .trustzone, + .vfp4, + .virtualization, + .vmlx_forwarding, + .vmlx_hazards, + }), + }; + pub const cortex_a72 = Cpu{ + .name = "cortex_a72", + .llvm_name = "cortex-a72", + .features = featureSet(&[_]Feature{ + .a72, + .armv8_a, + .crc, + .crypto, + .hwdiv, + .hwdiv_arm, + }), + }; + pub const cortex_a73 = Cpu{ + .name = "cortex_a73", + .llvm_name = "cortex-a73", + .features = featureSet(&[_]Feature{ + .a73, + .armv8_a, + .crc, + .crypto, + .hwdiv, + .hwdiv_arm, + }), + }; + pub const cortex_a75 = Cpu{ + .name = "cortex_a75", + .llvm_name = "cortex-a75", + .features = featureSet(&[_]Feature{ + .a75, + .armv8_2_a, + .dotprod, + .hwdiv, + .hwdiv_arm, + }), + }; + pub const cortex_a76 = Cpu{ + .name = "cortex_a76", + .llvm_name = "cortex-a76", + .features = featureSet(&[_]Feature{ + .a76, + .armv8_2_a, + .crc, + .crypto, + .dotprod, + .fullfp16, + .hwdiv, + .hwdiv_arm, + }), + }; + pub const cortex_a76ae = Cpu{ + .name = "cortex_a76ae", + .llvm_name = "cortex-a76ae", + .features = featureSet(&[_]Feature{ + .a76, + .armv8_2_a, + .crc, + .crypto, + .dotprod, + .fullfp16, + .hwdiv, + .hwdiv_arm, + }), + }; + pub const cortex_a8 = Cpu{ + .name = "cortex_a8", + .llvm_name = "cortex-a8", + .features = featureSet(&[_]Feature{ + .a8, + .armv7_a, + .nonpipelined_vfp, + .ret_addr_stack, + .slow_fp_brcc, + .slowfpvmlx, + .trustzone, + .vmlx_forwarding, + .vmlx_hazards, + }), + }; + pub const cortex_a9 = Cpu{ + .name = "cortex_a9", + .llvm_name = "cortex-a9", + .features = featureSet(&[_]Feature{ + .a9, + .armv7_a, + .avoid_partial_cpsr, + .expand_fp_mlx, + .fp16, + .mp, + .muxed_units, + .neon_fpmovs, + .prefer_vmovsr, + .ret_addr_stack, + .trustzone, + .vldn_align, + .vmlx_forwarding, + .vmlx_hazards, + }), + }; + pub const cortex_m0 = Cpu{ + .name = "cortex_m0", + .llvm_name = "cortex-m0", + .features = featureSet(&[_]Feature{ + .armv6_m, + }), + }; + pub const cortex_m0plus = Cpu{ + .name = "cortex_m0plus", + .llvm_name = "cortex-m0plus", + .features = featureSet(&[_]Feature{ + .armv6_m, + }), + }; + pub const cortex_m1 = Cpu{ + .name = "cortex_m1", + .llvm_name = "cortex-m1", + .features = featureSet(&[_]Feature{ + .armv6_m, + }), + }; + pub const cortex_m23 = Cpu{ + .name = "cortex_m23", + .llvm_name = "cortex-m23", + .features = featureSet(&[_]Feature{ + .armv8_m_base, + .no_movt, + }), + }; + pub const cortex_m3 = Cpu{ + .name = "cortex_m3", + .llvm_name = "cortex-m3", + .features = featureSet(&[_]Feature{ + .armv7_m, + .loop_align, + .m3, + .no_branch_predictor, + .use_aa, + .use_misched, + }), + }; + pub const cortex_m33 = Cpu{ + .name = "cortex_m33", + .llvm_name = "cortex-m33", + .features = featureSet(&[_]Feature{ + .armv8_m_main, + .dsp, + .fp_armv8d16sp, + .loop_align, + .no_branch_predictor, + .slowfpvmlx, + .use_aa, + .use_misched, + }), + }; + pub const cortex_m35p = Cpu{ + .name = "cortex_m35p", + .llvm_name = "cortex-m35p", + .features = featureSet(&[_]Feature{ + .armv8_m_main, + .dsp, + .fp_armv8d16sp, + .loop_align, + .no_branch_predictor, + .slowfpvmlx, + .use_aa, + .use_misched, + }), + }; + pub const cortex_m4 = Cpu{ + .name = "cortex_m4", + .llvm_name = "cortex-m4", + .features = featureSet(&[_]Feature{ + .armv7e_m, + .loop_align, + .no_branch_predictor, + .slowfpvmlx, + .use_aa, + .use_misched, + .vfp4d16sp, + }), + }; + pub const cortex_m7 = Cpu{ + .name = "cortex_m7", + .llvm_name = "cortex-m7", + .features = featureSet(&[_]Feature{ + .armv7e_m, + .fp_armv8d16, + }), + }; + pub const cortex_r4 = Cpu{ + .name = "cortex_r4", + .llvm_name = "cortex-r4", + .features = featureSet(&[_]Feature{ + .armv7_r, + .avoid_partial_cpsr, + .r4, + .ret_addr_stack, + }), + }; + pub const cortex_r4f = Cpu{ + .name = "cortex_r4f", + .llvm_name = "cortex-r4f", + .features = featureSet(&[_]Feature{ + .armv7_r, + .avoid_partial_cpsr, + .r4, + .ret_addr_stack, + .slow_fp_brcc, + .slowfpvmlx, + .vfp3d16, + }), + }; + pub const cortex_r5 = Cpu{ + .name = "cortex_r5", + .llvm_name = "cortex-r5", + .features = featureSet(&[_]Feature{ + .armv7_r, + .avoid_partial_cpsr, + .hwdiv_arm, + .r5, + .ret_addr_stack, + .slow_fp_brcc, + .slowfpvmlx, + .vfp3d16, + }), + }; + pub const cortex_r52 = Cpu{ + .name = "cortex_r52", + .llvm_name = "cortex-r52", + .features = featureSet(&[_]Feature{ + .armv8_r, + .fpao, + .r52, + .use_aa, + .use_misched, + }), + }; + pub const cortex_r7 = Cpu{ + .name = "cortex_r7", + .llvm_name = "cortex-r7", + .features = featureSet(&[_]Feature{ + .armv7_r, + .avoid_partial_cpsr, + .fp16, + .hwdiv_arm, + .mp, + .r7, + .ret_addr_stack, + .slow_fp_brcc, + .slowfpvmlx, + .vfp3d16, + }), + }; + pub const cortex_r8 = Cpu{ + .name = "cortex_r8", + .llvm_name = "cortex-r8", + .features = featureSet(&[_]Feature{ + .armv7_r, + .avoid_partial_cpsr, + .fp16, + .hwdiv_arm, + .mp, + .ret_addr_stack, + .slow_fp_brcc, + .slowfpvmlx, + .vfp3d16, + }), + }; + pub const cyclone = Cpu{ + .name = "cyclone", + .llvm_name = "cyclone", + .features = featureSet(&[_]Feature{ + .armv8_a, + .avoid_movs_shop, + .avoid_partial_cpsr, + .crypto, + .disable_postra_scheduler, + .hwdiv, + .hwdiv_arm, + .mp, + .neonfp, + .ret_addr_stack, + .slowfpvmlx, + .swift, + .use_misched, + .vfp4, + .zcz, + }), + }; + pub const ep9312 = Cpu{ + .name = "ep9312", + .llvm_name = "ep9312", + .features = featureSet(&[_]Feature{ + .armv4t, + }), + }; + pub const exynos_m1 = Cpu{ + .name = "exynos_m1", + .llvm_name = "exynos-m1", + .features = featureSet(&[_]Feature{ + .armv8_a, + .exynos, + }), + }; + pub const exynos_m2 = Cpu{ + .name = "exynos_m2", + .llvm_name = "exynos-m2", + .features = featureSet(&[_]Feature{ + .armv8_a, + .exynos, + }), + }; + pub const exynos_m3 = Cpu{ + .name = "exynos_m3", + .llvm_name = "exynos-m3", + .features = featureSet(&[_]Feature{ + .armv8_a, + .exynos, + }), + }; + pub const exynos_m4 = Cpu{ + .name = "exynos_m4", + .llvm_name = "exynos-m4", + .features = featureSet(&[_]Feature{ + .armv8_2_a, + .dotprod, + .exynos, + .fullfp16, + }), + }; + pub const exynos_m5 = Cpu{ + .name = "exynos_m5", + .llvm_name = "exynos-m5", + .features = featureSet(&[_]Feature{ + .armv8_2_a, + .dotprod, + .exynos, + .fullfp16, + }), + }; + pub const generic = Cpu{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{}), + }; + pub const iwmmxt = Cpu{ + .name = "iwmmxt", + .llvm_name = "iwmmxt", + .features = featureSet(&[_]Feature{ + .armv5te, + }), + }; + pub const krait = Cpu{ + .name = "krait", + .llvm_name = "krait", + .features = featureSet(&[_]Feature{ + .armv7_a, + .avoid_partial_cpsr, + .fp16, + .hwdiv, + .hwdiv_arm, + .krait, + .muxed_units, + .ret_addr_stack, + .vfp4, + .vldn_align, + .vmlx_forwarding, + }), + }; + pub const kryo = Cpu{ + .name = "kryo", + .llvm_name = "kryo", + .features = featureSet(&[_]Feature{ + .armv8_a, + .crc, + .crypto, + .hwdiv, + .hwdiv_arm, + .kryo, + }), + }; + pub const mpcore = Cpu{ + .name = "mpcore", + .llvm_name = "mpcore", + .features = featureSet(&[_]Feature{ + .armv6k, + .slowfpvmlx, + .vfp2, + }), + }; + pub const mpcorenovfp = Cpu{ + .name = "mpcorenovfp", + .llvm_name = "mpcorenovfp", + .features = featureSet(&[_]Feature{ + .armv6k, + }), + }; + pub const sc000 = Cpu{ + .name = "sc000", + .llvm_name = "sc000", + .features = featureSet(&[_]Feature{ + .armv6_m, + }), + }; + pub const sc300 = Cpu{ + .name = "sc300", + .llvm_name = "sc300", + .features = featureSet(&[_]Feature{ + .armv7_m, + .m3, + .no_branch_predictor, + .use_aa, + .use_misched, + }), + }; + pub const strongarm = Cpu{ + .name = "strongarm", + .llvm_name = "strongarm", + .features = featureSet(&[_]Feature{ + .armv4, + }), + }; + pub const strongarm110 = Cpu{ + .name = "strongarm110", + .llvm_name = "strongarm110", + .features = featureSet(&[_]Feature{ + .armv4, + }), + }; + pub const strongarm1100 = Cpu{ + .name = "strongarm1100", + .llvm_name = "strongarm1100", + .features = featureSet(&[_]Feature{ + .armv4, + }), + }; + pub const strongarm1110 = Cpu{ + .name = "strongarm1110", + .llvm_name = "strongarm1110", + .features = featureSet(&[_]Feature{ + .armv4, + }), + }; + pub const swift = Cpu{ + .name = "swift", + .llvm_name = "swift", + .features = featureSet(&[_]Feature{ + .armv7_a, + .avoid_movs_shop, + .avoid_partial_cpsr, + .disable_postra_scheduler, + .hwdiv, + .hwdiv_arm, + .mp, + .neonfp, + .prefer_ishst, + .prof_unpr, + .ret_addr_stack, + .slow_load_D_subreg, + .slow_odd_reg, + .slow_vdup32, + .slow_vgetlni32, + .slowfpvmlx, + .swift, + .use_misched, + .vfp4, + .vmlx_hazards, + .wide_stride_vfp, + }), + }; + pub const xscale = Cpu{ + .name = "xscale", + .llvm_name = "xscale", + .features = featureSet(&[_]Feature{ + .armv5te, + }), + }; +}; + +/// All arm CPUs, sorted alphabetically by name. +/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 +/// compiler has inefficient memory and CPU usage, affecting build times. +pub const all_cpus = &[_]*const Cpu{ + &cpu.arm1020e, + &cpu.arm1020t, + &cpu.arm1022e, + &cpu.arm10e, + &cpu.arm10tdmi, + &cpu.arm1136j_s, + &cpu.arm1136jf_s, + &cpu.arm1156t2_s, + &cpu.arm1156t2f_s, + &cpu.arm1176j_s, + &cpu.arm1176jz_s, + &cpu.arm1176jzf_s, + &cpu.arm710t, + &cpu.arm720t, + &cpu.arm7tdmi, + &cpu.arm7tdmi_s, + &cpu.arm8, + &cpu.arm810, + &cpu.arm9, + &cpu.arm920, + &cpu.arm920t, + &cpu.arm922t, + &cpu.arm926ej_s, + &cpu.arm940t, + &cpu.arm946e_s, + &cpu.arm966e_s, + &cpu.arm968e_s, + &cpu.arm9e, + &cpu.arm9tdmi, + &cpu.cortex_a12, + &cpu.cortex_a15, + &cpu.cortex_a17, + &cpu.cortex_a32, + &cpu.cortex_a35, + &cpu.cortex_a5, + &cpu.cortex_a53, + &cpu.cortex_a55, + &cpu.cortex_a57, + &cpu.cortex_a7, + &cpu.cortex_a72, + &cpu.cortex_a73, + &cpu.cortex_a75, + &cpu.cortex_a76, + &cpu.cortex_a76ae, + &cpu.cortex_a8, + &cpu.cortex_a9, + &cpu.cortex_m0, + &cpu.cortex_m0plus, + &cpu.cortex_m1, + &cpu.cortex_m23, + &cpu.cortex_m3, + &cpu.cortex_m33, + &cpu.cortex_m35p, + &cpu.cortex_m4, + &cpu.cortex_m7, + &cpu.cortex_r4, + &cpu.cortex_r4f, + &cpu.cortex_r5, + &cpu.cortex_r52, + &cpu.cortex_r7, + &cpu.cortex_r8, + &cpu.cyclone, + &cpu.ep9312, + &cpu.exynos_m1, + &cpu.exynos_m2, + &cpu.exynos_m3, + &cpu.exynos_m4, + &cpu.exynos_m5, + &cpu.generic, + &cpu.iwmmxt, + &cpu.krait, + &cpu.kryo, + &cpu.mpcore, + &cpu.mpcorenovfp, + &cpu.sc000, + &cpu.sc300, + &cpu.strongarm, + &cpu.strongarm110, + &cpu.strongarm1100, + &cpu.strongarm1110, + &cpu.swift, + &cpu.xscale, +}; diff --git a/lib/std/target/avr.zig b/lib/std/target/avr.zig new file mode 100644 index 0000000000..3902a3860f --- /dev/null +++ b/lib/std/target/avr.zig @@ -0,0 +1,2380 @@ +const std = @import("../std.zig"); +const Cpu = std.Target.Cpu; + +pub const Feature = enum { + addsubiw, + avr0, + avr1, + avr2, + avr25, + avr3, + avr31, + avr35, + avr4, + avr5, + avr51, + avr6, + avrtiny, + @"break", + des, + eijmpcall, + elpm, + elpmx, + ijmpcall, + jmpcall, + lpm, + lpmx, + movw, + mul, + rmw, + smallstack, + special, + spm, + spmx, + sram, + tinyencoding, + xmega, + xmegau, +}; + +pub usingnamespace Cpu.Feature.feature_set_fns(Feature); + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); + var result: [len]Cpu.Feature = undefined; + result[@enumToInt(Feature.addsubiw)] = .{ + .llvm_name = "addsubiw", + .description = "Enable 16-bit register-immediate addition and subtraction instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.avr0)] = .{ + .llvm_name = "avr0", + .description = "The device is a part of the avr0 family", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.avr1)] = .{ + .llvm_name = "avr1", + .description = "The device is a part of the avr1 family", + .dependencies = featureSet(&[_]Feature{ + .avr0, + .lpm, + }), + }; + result[@enumToInt(Feature.avr2)] = .{ + .llvm_name = "avr2", + .description = "The device is a part of the avr2 family", + .dependencies = featureSet(&[_]Feature{ + .addsubiw, + .avr1, + .ijmpcall, + .sram, + }), + }; + result[@enumToInt(Feature.avr25)] = .{ + .llvm_name = "avr25", + .description = "The device is a part of the avr25 family", + .dependencies = featureSet(&[_]Feature{ + .avr2, + .@"break", + .lpmx, + .movw, + .spm, + }), + }; + result[@enumToInt(Feature.avr3)] = .{ + .llvm_name = "avr3", + .description = "The device is a part of the avr3 family", + .dependencies = featureSet(&[_]Feature{ + .avr2, + .jmpcall, + }), + }; + result[@enumToInt(Feature.avr31)] = .{ + .llvm_name = "avr31", + .description = "The device is a part of the avr31 family", + .dependencies = featureSet(&[_]Feature{ + .avr3, + .elpm, + }), + }; + result[@enumToInt(Feature.avr35)] = .{ + .llvm_name = "avr35", + .description = "The device is a part of the avr35 family", + .dependencies = featureSet(&[_]Feature{ + .avr3, + .@"break", + .lpmx, + .movw, + .spm, + }), + }; + result[@enumToInt(Feature.avr4)] = .{ + .llvm_name = "avr4", + .description = "The device is a part of the avr4 family", + .dependencies = featureSet(&[_]Feature{ + .avr2, + .@"break", + .lpmx, + .movw, + .mul, + .spm, + }), + }; + result[@enumToInt(Feature.avr5)] = .{ + .llvm_name = "avr5", + .description = "The device is a part of the avr5 family", + .dependencies = featureSet(&[_]Feature{ + .avr3, + .@"break", + .lpmx, + .movw, + .mul, + .spm, + }), + }; + result[@enumToInt(Feature.avr51)] = .{ + .llvm_name = "avr51", + .description = "The device is a part of the avr51 family", + .dependencies = featureSet(&[_]Feature{ + .avr5, + .elpm, + .elpmx, + }), + }; + result[@enumToInt(Feature.avr6)] = .{ + .llvm_name = "avr6", + .description = "The device is a part of the avr6 family", + .dependencies = featureSet(&[_]Feature{ + .avr51, + }), + }; + result[@enumToInt(Feature.avrtiny)] = .{ + .llvm_name = "avrtiny", + .description = "The device is a part of the avrtiny family", + .dependencies = featureSet(&[_]Feature{ + .avr0, + .@"break", + .sram, + .tinyencoding, + }), + }; + result[@enumToInt(Feature.@"break")] = .{ + .llvm_name = "break", + .description = "The device supports the `BREAK` debugging instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.des)] = .{ + .llvm_name = "des", + .description = "The device supports the `DES k` encryption instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.eijmpcall)] = .{ + .llvm_name = "eijmpcall", + .description = "The device supports the `EIJMP`/`EICALL` instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.elpm)] = .{ + .llvm_name = "elpm", + .description = "The device supports the ELPM instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.elpmx)] = .{ + .llvm_name = "elpmx", + .description = "The device supports the `ELPM Rd, Z[+]` instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ijmpcall)] = .{ + .llvm_name = "ijmpcall", + .description = "The device supports `IJMP`/`ICALL`instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.jmpcall)] = .{ + .llvm_name = "jmpcall", + .description = "The device supports the `JMP` and `CALL` instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.lpm)] = .{ + .llvm_name = "lpm", + .description = "The device supports the `LPM` instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.lpmx)] = .{ + .llvm_name = "lpmx", + .description = "The device supports the `LPM Rd, Z[+]` instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.movw)] = .{ + .llvm_name = "movw", + .description = "The device supports the 16-bit MOVW instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mul)] = .{ + .llvm_name = "mul", + .description = "The device supports the multiplication instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.rmw)] = .{ + .llvm_name = "rmw", + .description = "The device supports the read-write-modify instructions: XCH, LAS, LAC, LAT", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.smallstack)] = .{ + .llvm_name = "smallstack", + .description = "The device has an 8-bit stack pointer", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.special)] = .{ + .llvm_name = "special", + .description = "Enable use of the entire instruction set - used for debugging", + .dependencies = featureSet(&[_]Feature{ + .addsubiw, + .@"break", + .des, + .eijmpcall, + .elpm, + .elpmx, + .ijmpcall, + .jmpcall, + .lpm, + .lpmx, + .movw, + .mul, + .rmw, + .spm, + .spmx, + .sram, + }), + }; + result[@enumToInt(Feature.spm)] = .{ + .llvm_name = "spm", + .description = "The device supports the `SPM` instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.spmx)] = .{ + .llvm_name = "spmx", + .description = "The device supports the `SPM Z+` instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sram)] = .{ + .llvm_name = "sram", + .description = "The device has random access memory", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.tinyencoding)] = .{ + .llvm_name = "tinyencoding", + .description = "The device has Tiny core specific instruction encodings", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.xmega)] = .{ + .llvm_name = "xmega", + .description = "The device is a part of the xmega family", + .dependencies = featureSet(&[_]Feature{ + .avr51, + .des, + .eijmpcall, + .spmx, + }), + }; + result[@enumToInt(Feature.xmegau)] = .{ + .llvm_name = "xmegau", + .description = "The device is a part of the xmegau family", + .dependencies = featureSet(&[_]Feature{ + .rmw, + .xmega, + }), + }; + const ti = @typeInfo(Feature); + for (result) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const at43usb320 = Cpu{ + .name = "at43usb320", + .llvm_name = "at43usb320", + .features = featureSet(&[_]Feature{ + .avr31, + }), + }; + pub const at43usb355 = Cpu{ + .name = "at43usb355", + .llvm_name = "at43usb355", + .features = featureSet(&[_]Feature{ + .avr3, + }), + }; + pub const at76c711 = Cpu{ + .name = "at76c711", + .llvm_name = "at76c711", + .features = featureSet(&[_]Feature{ + .avr3, + }), + }; + pub const at86rf401 = Cpu{ + .name = "at86rf401", + .llvm_name = "at86rf401", + .features = featureSet(&[_]Feature{ + .avr2, + .lpmx, + .movw, + }), + }; + pub const at90c8534 = Cpu{ + .name = "at90c8534", + .llvm_name = "at90c8534", + .features = featureSet(&[_]Feature{ + .avr2, + }), + }; + pub const at90can128 = Cpu{ + .name = "at90can128", + .llvm_name = "at90can128", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const at90can32 = Cpu{ + .name = "at90can32", + .llvm_name = "at90can32", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const at90can64 = Cpu{ + .name = "at90can64", + .llvm_name = "at90can64", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const at90pwm1 = Cpu{ + .name = "at90pwm1", + .llvm_name = "at90pwm1", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const at90pwm161 = Cpu{ + .name = "at90pwm161", + .llvm_name = "at90pwm161", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const at90pwm2 = Cpu{ + .name = "at90pwm2", + .llvm_name = "at90pwm2", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const at90pwm216 = Cpu{ + .name = "at90pwm216", + .llvm_name = "at90pwm216", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const at90pwm2b = Cpu{ + .name = "at90pwm2b", + .llvm_name = "at90pwm2b", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const at90pwm3 = Cpu{ + .name = "at90pwm3", + .llvm_name = "at90pwm3", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const at90pwm316 = Cpu{ + .name = "at90pwm316", + .llvm_name = "at90pwm316", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const at90pwm3b = Cpu{ + .name = "at90pwm3b", + .llvm_name = "at90pwm3b", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const at90pwm81 = Cpu{ + .name = "at90pwm81", + .llvm_name = "at90pwm81", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const at90s1200 = Cpu{ + .name = "at90s1200", + .llvm_name = "at90s1200", + .features = featureSet(&[_]Feature{ + .avr0, + }), + }; + pub const at90s2313 = Cpu{ + .name = "at90s2313", + .llvm_name = "at90s2313", + .features = featureSet(&[_]Feature{ + .avr2, + }), + }; + pub const at90s2323 = Cpu{ + .name = "at90s2323", + .llvm_name = "at90s2323", + .features = featureSet(&[_]Feature{ + .avr2, + }), + }; + pub const at90s2333 = Cpu{ + .name = "at90s2333", + .llvm_name = "at90s2333", + .features = featureSet(&[_]Feature{ + .avr2, + }), + }; + pub const at90s2343 = Cpu{ + .name = "at90s2343", + .llvm_name = "at90s2343", + .features = featureSet(&[_]Feature{ + .avr2, + }), + }; + pub const at90s4414 = Cpu{ + .name = "at90s4414", + .llvm_name = "at90s4414", + .features = featureSet(&[_]Feature{ + .avr2, + }), + }; + pub const at90s4433 = Cpu{ + .name = "at90s4433", + .llvm_name = "at90s4433", + .features = featureSet(&[_]Feature{ + .avr2, + }), + }; + pub const at90s4434 = Cpu{ + .name = "at90s4434", + .llvm_name = "at90s4434", + .features = featureSet(&[_]Feature{ + .avr2, + }), + }; + pub const at90s8515 = Cpu{ + .name = "at90s8515", + .llvm_name = "at90s8515", + .features = featureSet(&[_]Feature{ + .avr2, + }), + }; + pub const at90s8535 = Cpu{ + .name = "at90s8535", + .llvm_name = "at90s8535", + .features = featureSet(&[_]Feature{ + .avr2, + }), + }; + pub const at90scr100 = Cpu{ + .name = "at90scr100", + .llvm_name = "at90scr100", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const at90usb1286 = Cpu{ + .name = "at90usb1286", + .llvm_name = "at90usb1286", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const at90usb1287 = Cpu{ + .name = "at90usb1287", + .llvm_name = "at90usb1287", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const at90usb162 = Cpu{ + .name = "at90usb162", + .llvm_name = "at90usb162", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const at90usb646 = Cpu{ + .name = "at90usb646", + .llvm_name = "at90usb646", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const at90usb647 = Cpu{ + .name = "at90usb647", + .llvm_name = "at90usb647", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const at90usb82 = Cpu{ + .name = "at90usb82", + .llvm_name = "at90usb82", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const at94k = Cpu{ + .name = "at94k", + .llvm_name = "at94k", + .features = featureSet(&[_]Feature{ + .avr3, + .lpmx, + .movw, + .mul, + }), + }; + pub const ata5272 = Cpu{ + .name = "ata5272", + .llvm_name = "ata5272", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const ata5505 = Cpu{ + .name = "ata5505", + .llvm_name = "ata5505", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const ata5790 = Cpu{ + .name = "ata5790", + .llvm_name = "ata5790", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const ata5795 = Cpu{ + .name = "ata5795", + .llvm_name = "ata5795", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const ata6285 = Cpu{ + .name = "ata6285", + .llvm_name = "ata6285", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const ata6286 = Cpu{ + .name = "ata6286", + .llvm_name = "ata6286", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const ata6289 = Cpu{ + .name = "ata6289", + .llvm_name = "ata6289", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega103 = Cpu{ + .name = "atmega103", + .llvm_name = "atmega103", + .features = featureSet(&[_]Feature{ + .avr31, + }), + }; + pub const atmega128 = Cpu{ + .name = "atmega128", + .llvm_name = "atmega128", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const atmega1280 = Cpu{ + .name = "atmega1280", + .llvm_name = "atmega1280", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const atmega1281 = Cpu{ + .name = "atmega1281", + .llvm_name = "atmega1281", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const atmega1284 = Cpu{ + .name = "atmega1284", + .llvm_name = "atmega1284", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const atmega1284p = Cpu{ + .name = "atmega1284p", + .llvm_name = "atmega1284p", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const atmega1284rfr2 = Cpu{ + .name = "atmega1284rfr2", + .llvm_name = "atmega1284rfr2", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const atmega128a = Cpu{ + .name = "atmega128a", + .llvm_name = "atmega128a", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const atmega128rfa1 = Cpu{ + .name = "atmega128rfa1", + .llvm_name = "atmega128rfa1", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const atmega128rfr2 = Cpu{ + .name = "atmega128rfr2", + .llvm_name = "atmega128rfr2", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const atmega16 = Cpu{ + .name = "atmega16", + .llvm_name = "atmega16", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega161 = Cpu{ + .name = "atmega161", + .llvm_name = "atmega161", + .features = featureSet(&[_]Feature{ + .avr3, + .lpmx, + .movw, + .mul, + .spm, + }), + }; + pub const atmega162 = Cpu{ + .name = "atmega162", + .llvm_name = "atmega162", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega163 = Cpu{ + .name = "atmega163", + .llvm_name = "atmega163", + .features = featureSet(&[_]Feature{ + .avr3, + .lpmx, + .movw, + .mul, + .spm, + }), + }; + pub const atmega164a = Cpu{ + .name = "atmega164a", + .llvm_name = "atmega164a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega164p = Cpu{ + .name = "atmega164p", + .llvm_name = "atmega164p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega164pa = Cpu{ + .name = "atmega164pa", + .llvm_name = "atmega164pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega165 = Cpu{ + .name = "atmega165", + .llvm_name = "atmega165", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega165a = Cpu{ + .name = "atmega165a", + .llvm_name = "atmega165a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega165p = Cpu{ + .name = "atmega165p", + .llvm_name = "atmega165p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega165pa = Cpu{ + .name = "atmega165pa", + .llvm_name = "atmega165pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega168 = Cpu{ + .name = "atmega168", + .llvm_name = "atmega168", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega168a = Cpu{ + .name = "atmega168a", + .llvm_name = "atmega168a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega168p = Cpu{ + .name = "atmega168p", + .llvm_name = "atmega168p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega168pa = Cpu{ + .name = "atmega168pa", + .llvm_name = "atmega168pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega169 = Cpu{ + .name = "atmega169", + .llvm_name = "atmega169", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega169a = Cpu{ + .name = "atmega169a", + .llvm_name = "atmega169a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega169p = Cpu{ + .name = "atmega169p", + .llvm_name = "atmega169p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega169pa = Cpu{ + .name = "atmega169pa", + .llvm_name = "atmega169pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega16a = Cpu{ + .name = "atmega16a", + .llvm_name = "atmega16a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega16hva = Cpu{ + .name = "atmega16hva", + .llvm_name = "atmega16hva", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega16hva2 = Cpu{ + .name = "atmega16hva2", + .llvm_name = "atmega16hva2", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega16hvb = Cpu{ + .name = "atmega16hvb", + .llvm_name = "atmega16hvb", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega16hvbrevb = Cpu{ + .name = "atmega16hvbrevb", + .llvm_name = "atmega16hvbrevb", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega16m1 = Cpu{ + .name = "atmega16m1", + .llvm_name = "atmega16m1", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega16u2 = Cpu{ + .name = "atmega16u2", + .llvm_name = "atmega16u2", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const atmega16u4 = Cpu{ + .name = "atmega16u4", + .llvm_name = "atmega16u4", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega2560 = Cpu{ + .name = "atmega2560", + .llvm_name = "atmega2560", + .features = featureSet(&[_]Feature{ + .avr6, + }), + }; + pub const atmega2561 = Cpu{ + .name = "atmega2561", + .llvm_name = "atmega2561", + .features = featureSet(&[_]Feature{ + .avr6, + }), + }; + pub const atmega2564rfr2 = Cpu{ + .name = "atmega2564rfr2", + .llvm_name = "atmega2564rfr2", + .features = featureSet(&[_]Feature{ + .avr6, + }), + }; + pub const atmega256rfr2 = Cpu{ + .name = "atmega256rfr2", + .llvm_name = "atmega256rfr2", + .features = featureSet(&[_]Feature{ + .avr6, + }), + }; + pub const atmega32 = Cpu{ + .name = "atmega32", + .llvm_name = "atmega32", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega323 = Cpu{ + .name = "atmega323", + .llvm_name = "atmega323", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega324a = Cpu{ + .name = "atmega324a", + .llvm_name = "atmega324a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega324p = Cpu{ + .name = "atmega324p", + .llvm_name = "atmega324p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega324pa = Cpu{ + .name = "atmega324pa", + .llvm_name = "atmega324pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega325 = Cpu{ + .name = "atmega325", + .llvm_name = "atmega325", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega3250 = Cpu{ + .name = "atmega3250", + .llvm_name = "atmega3250", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega3250a = Cpu{ + .name = "atmega3250a", + .llvm_name = "atmega3250a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega3250p = Cpu{ + .name = "atmega3250p", + .llvm_name = "atmega3250p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega3250pa = Cpu{ + .name = "atmega3250pa", + .llvm_name = "atmega3250pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega325a = Cpu{ + .name = "atmega325a", + .llvm_name = "atmega325a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega325p = Cpu{ + .name = "atmega325p", + .llvm_name = "atmega325p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega325pa = Cpu{ + .name = "atmega325pa", + .llvm_name = "atmega325pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega328 = Cpu{ + .name = "atmega328", + .llvm_name = "atmega328", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega328p = Cpu{ + .name = "atmega328p", + .llvm_name = "atmega328p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega329 = Cpu{ + .name = "atmega329", + .llvm_name = "atmega329", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega3290 = Cpu{ + .name = "atmega3290", + .llvm_name = "atmega3290", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega3290a = Cpu{ + .name = "atmega3290a", + .llvm_name = "atmega3290a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega3290p = Cpu{ + .name = "atmega3290p", + .llvm_name = "atmega3290p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega3290pa = Cpu{ + .name = "atmega3290pa", + .llvm_name = "atmega3290pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega329a = Cpu{ + .name = "atmega329a", + .llvm_name = "atmega329a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega329p = Cpu{ + .name = "atmega329p", + .llvm_name = "atmega329p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega329pa = Cpu{ + .name = "atmega329pa", + .llvm_name = "atmega329pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega32a = Cpu{ + .name = "atmega32a", + .llvm_name = "atmega32a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega32c1 = Cpu{ + .name = "atmega32c1", + .llvm_name = "atmega32c1", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega32hvb = Cpu{ + .name = "atmega32hvb", + .llvm_name = "atmega32hvb", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega32hvbrevb = Cpu{ + .name = "atmega32hvbrevb", + .llvm_name = "atmega32hvbrevb", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega32m1 = Cpu{ + .name = "atmega32m1", + .llvm_name = "atmega32m1", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega32u2 = Cpu{ + .name = "atmega32u2", + .llvm_name = "atmega32u2", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const atmega32u4 = Cpu{ + .name = "atmega32u4", + .llvm_name = "atmega32u4", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega32u6 = Cpu{ + .name = "atmega32u6", + .llvm_name = "atmega32u6", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega406 = Cpu{ + .name = "atmega406", + .llvm_name = "atmega406", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega48 = Cpu{ + .name = "atmega48", + .llvm_name = "atmega48", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega48a = Cpu{ + .name = "atmega48a", + .llvm_name = "atmega48a", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega48p = Cpu{ + .name = "atmega48p", + .llvm_name = "atmega48p", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega48pa = Cpu{ + .name = "atmega48pa", + .llvm_name = "atmega48pa", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega64 = Cpu{ + .name = "atmega64", + .llvm_name = "atmega64", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega640 = Cpu{ + .name = "atmega640", + .llvm_name = "atmega640", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega644 = Cpu{ + .name = "atmega644", + .llvm_name = "atmega644", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega644a = Cpu{ + .name = "atmega644a", + .llvm_name = "atmega644a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega644p = Cpu{ + .name = "atmega644p", + .llvm_name = "atmega644p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega644pa = Cpu{ + .name = "atmega644pa", + .llvm_name = "atmega644pa", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega644rfr2 = Cpu{ + .name = "atmega644rfr2", + .llvm_name = "atmega644rfr2", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega645 = Cpu{ + .name = "atmega645", + .llvm_name = "atmega645", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega6450 = Cpu{ + .name = "atmega6450", + .llvm_name = "atmega6450", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega6450a = Cpu{ + .name = "atmega6450a", + .llvm_name = "atmega6450a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega6450p = Cpu{ + .name = "atmega6450p", + .llvm_name = "atmega6450p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega645a = Cpu{ + .name = "atmega645a", + .llvm_name = "atmega645a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega645p = Cpu{ + .name = "atmega645p", + .llvm_name = "atmega645p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega649 = Cpu{ + .name = "atmega649", + .llvm_name = "atmega649", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega6490 = Cpu{ + .name = "atmega6490", + .llvm_name = "atmega6490", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega6490a = Cpu{ + .name = "atmega6490a", + .llvm_name = "atmega6490a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega6490p = Cpu{ + .name = "atmega6490p", + .llvm_name = "atmega6490p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega649a = Cpu{ + .name = "atmega649a", + .llvm_name = "atmega649a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega649p = Cpu{ + .name = "atmega649p", + .llvm_name = "atmega649p", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega64a = Cpu{ + .name = "atmega64a", + .llvm_name = "atmega64a", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega64c1 = Cpu{ + .name = "atmega64c1", + .llvm_name = "atmega64c1", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega64hve = Cpu{ + .name = "atmega64hve", + .llvm_name = "atmega64hve", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega64m1 = Cpu{ + .name = "atmega64m1", + .llvm_name = "atmega64m1", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega64rfr2 = Cpu{ + .name = "atmega64rfr2", + .llvm_name = "atmega64rfr2", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const atmega8 = Cpu{ + .name = "atmega8", + .llvm_name = "atmega8", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega8515 = Cpu{ + .name = "atmega8515", + .llvm_name = "atmega8515", + .features = featureSet(&[_]Feature{ + .avr2, + .lpmx, + .movw, + .mul, + .spm, + }), + }; + pub const atmega8535 = Cpu{ + .name = "atmega8535", + .llvm_name = "atmega8535", + .features = featureSet(&[_]Feature{ + .avr2, + .lpmx, + .movw, + .mul, + .spm, + }), + }; + pub const atmega88 = Cpu{ + .name = "atmega88", + .llvm_name = "atmega88", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega88a = Cpu{ + .name = "atmega88a", + .llvm_name = "atmega88a", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega88p = Cpu{ + .name = "atmega88p", + .llvm_name = "atmega88p", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega88pa = Cpu{ + .name = "atmega88pa", + .llvm_name = "atmega88pa", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega8a = Cpu{ + .name = "atmega8a", + .llvm_name = "atmega8a", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega8hva = Cpu{ + .name = "atmega8hva", + .llvm_name = "atmega8hva", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const atmega8u2 = Cpu{ + .name = "atmega8u2", + .llvm_name = "atmega8u2", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const attiny10 = Cpu{ + .name = "attiny10", + .llvm_name = "attiny10", + .features = featureSet(&[_]Feature{ + .avrtiny, + }), + }; + pub const attiny102 = Cpu{ + .name = "attiny102", + .llvm_name = "attiny102", + .features = featureSet(&[_]Feature{ + .avrtiny, + }), + }; + pub const attiny104 = Cpu{ + .name = "attiny104", + .llvm_name = "attiny104", + .features = featureSet(&[_]Feature{ + .avrtiny, + }), + }; + pub const attiny11 = Cpu{ + .name = "attiny11", + .llvm_name = "attiny11", + .features = featureSet(&[_]Feature{ + .avr1, + }), + }; + pub const attiny12 = Cpu{ + .name = "attiny12", + .llvm_name = "attiny12", + .features = featureSet(&[_]Feature{ + .avr1, + }), + }; + pub const attiny13 = Cpu{ + .name = "attiny13", + .llvm_name = "attiny13", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny13a = Cpu{ + .name = "attiny13a", + .llvm_name = "attiny13a", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny15 = Cpu{ + .name = "attiny15", + .llvm_name = "attiny15", + .features = featureSet(&[_]Feature{ + .avr1, + }), + }; + pub const attiny1634 = Cpu{ + .name = "attiny1634", + .llvm_name = "attiny1634", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const attiny167 = Cpu{ + .name = "attiny167", + .llvm_name = "attiny167", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const attiny20 = Cpu{ + .name = "attiny20", + .llvm_name = "attiny20", + .features = featureSet(&[_]Feature{ + .avrtiny, + }), + }; + pub const attiny22 = Cpu{ + .name = "attiny22", + .llvm_name = "attiny22", + .features = featureSet(&[_]Feature{ + .avr2, + }), + }; + pub const attiny2313 = Cpu{ + .name = "attiny2313", + .llvm_name = "attiny2313", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny2313a = Cpu{ + .name = "attiny2313a", + .llvm_name = "attiny2313a", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny24 = Cpu{ + .name = "attiny24", + .llvm_name = "attiny24", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny24a = Cpu{ + .name = "attiny24a", + .llvm_name = "attiny24a", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny25 = Cpu{ + .name = "attiny25", + .llvm_name = "attiny25", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny26 = Cpu{ + .name = "attiny26", + .llvm_name = "attiny26", + .features = featureSet(&[_]Feature{ + .avr2, + .lpmx, + }), + }; + pub const attiny261 = Cpu{ + .name = "attiny261", + .llvm_name = "attiny261", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny261a = Cpu{ + .name = "attiny261a", + .llvm_name = "attiny261a", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny28 = Cpu{ + .name = "attiny28", + .llvm_name = "attiny28", + .features = featureSet(&[_]Feature{ + .avr1, + }), + }; + pub const attiny4 = Cpu{ + .name = "attiny4", + .llvm_name = "attiny4", + .features = featureSet(&[_]Feature{ + .avrtiny, + }), + }; + pub const attiny40 = Cpu{ + .name = "attiny40", + .llvm_name = "attiny40", + .features = featureSet(&[_]Feature{ + .avrtiny, + }), + }; + pub const attiny4313 = Cpu{ + .name = "attiny4313", + .llvm_name = "attiny4313", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny43u = Cpu{ + .name = "attiny43u", + .llvm_name = "attiny43u", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny44 = Cpu{ + .name = "attiny44", + .llvm_name = "attiny44", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny44a = Cpu{ + .name = "attiny44a", + .llvm_name = "attiny44a", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny45 = Cpu{ + .name = "attiny45", + .llvm_name = "attiny45", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny461 = Cpu{ + .name = "attiny461", + .llvm_name = "attiny461", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny461a = Cpu{ + .name = "attiny461a", + .llvm_name = "attiny461a", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny48 = Cpu{ + .name = "attiny48", + .llvm_name = "attiny48", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny5 = Cpu{ + .name = "attiny5", + .llvm_name = "attiny5", + .features = featureSet(&[_]Feature{ + .avrtiny, + }), + }; + pub const attiny828 = Cpu{ + .name = "attiny828", + .llvm_name = "attiny828", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny84 = Cpu{ + .name = "attiny84", + .llvm_name = "attiny84", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny84a = Cpu{ + .name = "attiny84a", + .llvm_name = "attiny84a", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny85 = Cpu{ + .name = "attiny85", + .llvm_name = "attiny85", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny861 = Cpu{ + .name = "attiny861", + .llvm_name = "attiny861", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny861a = Cpu{ + .name = "attiny861a", + .llvm_name = "attiny861a", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny87 = Cpu{ + .name = "attiny87", + .llvm_name = "attiny87", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny88 = Cpu{ + .name = "attiny88", + .llvm_name = "attiny88", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const attiny9 = Cpu{ + .name = "attiny9", + .llvm_name = "attiny9", + .features = featureSet(&[_]Feature{ + .avrtiny, + }), + }; + pub const atxmega128a1 = Cpu{ + .name = "atxmega128a1", + .llvm_name = "atxmega128a1", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega128a1u = Cpu{ + .name = "atxmega128a1u", + .llvm_name = "atxmega128a1u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega128a3 = Cpu{ + .name = "atxmega128a3", + .llvm_name = "atxmega128a3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega128a3u = Cpu{ + .name = "atxmega128a3u", + .llvm_name = "atxmega128a3u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega128a4u = Cpu{ + .name = "atxmega128a4u", + .llvm_name = "atxmega128a4u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega128b1 = Cpu{ + .name = "atxmega128b1", + .llvm_name = "atxmega128b1", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega128b3 = Cpu{ + .name = "atxmega128b3", + .llvm_name = "atxmega128b3", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega128c3 = Cpu{ + .name = "atxmega128c3", + .llvm_name = "atxmega128c3", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega128d3 = Cpu{ + .name = "atxmega128d3", + .llvm_name = "atxmega128d3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega128d4 = Cpu{ + .name = "atxmega128d4", + .llvm_name = "atxmega128d4", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega16a4 = Cpu{ + .name = "atxmega16a4", + .llvm_name = "atxmega16a4", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega16a4u = Cpu{ + .name = "atxmega16a4u", + .llvm_name = "atxmega16a4u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega16c4 = Cpu{ + .name = "atxmega16c4", + .llvm_name = "atxmega16c4", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega16d4 = Cpu{ + .name = "atxmega16d4", + .llvm_name = "atxmega16d4", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega16e5 = Cpu{ + .name = "atxmega16e5", + .llvm_name = "atxmega16e5", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega192a3 = Cpu{ + .name = "atxmega192a3", + .llvm_name = "atxmega192a3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega192a3u = Cpu{ + .name = "atxmega192a3u", + .llvm_name = "atxmega192a3u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega192c3 = Cpu{ + .name = "atxmega192c3", + .llvm_name = "atxmega192c3", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega192d3 = Cpu{ + .name = "atxmega192d3", + .llvm_name = "atxmega192d3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega256a3 = Cpu{ + .name = "atxmega256a3", + .llvm_name = "atxmega256a3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega256a3b = Cpu{ + .name = "atxmega256a3b", + .llvm_name = "atxmega256a3b", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega256a3bu = Cpu{ + .name = "atxmega256a3bu", + .llvm_name = "atxmega256a3bu", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega256a3u = Cpu{ + .name = "atxmega256a3u", + .llvm_name = "atxmega256a3u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega256c3 = Cpu{ + .name = "atxmega256c3", + .llvm_name = "atxmega256c3", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega256d3 = Cpu{ + .name = "atxmega256d3", + .llvm_name = "atxmega256d3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega32a4 = Cpu{ + .name = "atxmega32a4", + .llvm_name = "atxmega32a4", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega32a4u = Cpu{ + .name = "atxmega32a4u", + .llvm_name = "atxmega32a4u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega32c4 = Cpu{ + .name = "atxmega32c4", + .llvm_name = "atxmega32c4", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega32d4 = Cpu{ + .name = "atxmega32d4", + .llvm_name = "atxmega32d4", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega32e5 = Cpu{ + .name = "atxmega32e5", + .llvm_name = "atxmega32e5", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega32x1 = Cpu{ + .name = "atxmega32x1", + .llvm_name = "atxmega32x1", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega384c3 = Cpu{ + .name = "atxmega384c3", + .llvm_name = "atxmega384c3", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega384d3 = Cpu{ + .name = "atxmega384d3", + .llvm_name = "atxmega384d3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega64a1 = Cpu{ + .name = "atxmega64a1", + .llvm_name = "atxmega64a1", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega64a1u = Cpu{ + .name = "atxmega64a1u", + .llvm_name = "atxmega64a1u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega64a3 = Cpu{ + .name = "atxmega64a3", + .llvm_name = "atxmega64a3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega64a3u = Cpu{ + .name = "atxmega64a3u", + .llvm_name = "atxmega64a3u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega64a4u = Cpu{ + .name = "atxmega64a4u", + .llvm_name = "atxmega64a4u", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega64b1 = Cpu{ + .name = "atxmega64b1", + .llvm_name = "atxmega64b1", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega64b3 = Cpu{ + .name = "atxmega64b3", + .llvm_name = "atxmega64b3", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega64c3 = Cpu{ + .name = "atxmega64c3", + .llvm_name = "atxmega64c3", + .features = featureSet(&[_]Feature{ + .xmegau, + }), + }; + pub const atxmega64d3 = Cpu{ + .name = "atxmega64d3", + .llvm_name = "atxmega64d3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega64d4 = Cpu{ + .name = "atxmega64d4", + .llvm_name = "atxmega64d4", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const atxmega8e5 = Cpu{ + .name = "atxmega8e5", + .llvm_name = "atxmega8e5", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const avr1 = Cpu{ + .name = "avr1", + .llvm_name = "avr1", + .features = featureSet(&[_]Feature{ + .avr1, + }), + }; + pub const avr2 = Cpu{ + .name = "avr2", + .llvm_name = "avr2", + .features = featureSet(&[_]Feature{ + .avr2, + }), + }; + pub const avr25 = Cpu{ + .name = "avr25", + .llvm_name = "avr25", + .features = featureSet(&[_]Feature{ + .avr25, + }), + }; + pub const avr3 = Cpu{ + .name = "avr3", + .llvm_name = "avr3", + .features = featureSet(&[_]Feature{ + .avr3, + }), + }; + pub const avr31 = Cpu{ + .name = "avr31", + .llvm_name = "avr31", + .features = featureSet(&[_]Feature{ + .avr31, + }), + }; + pub const avr35 = Cpu{ + .name = "avr35", + .llvm_name = "avr35", + .features = featureSet(&[_]Feature{ + .avr35, + }), + }; + pub const avr4 = Cpu{ + .name = "avr4", + .llvm_name = "avr4", + .features = featureSet(&[_]Feature{ + .avr4, + }), + }; + pub const avr5 = Cpu{ + .name = "avr5", + .llvm_name = "avr5", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; + pub const avr51 = Cpu{ + .name = "avr51", + .llvm_name = "avr51", + .features = featureSet(&[_]Feature{ + .avr51, + }), + }; + pub const avr6 = Cpu{ + .name = "avr6", + .llvm_name = "avr6", + .features = featureSet(&[_]Feature{ + .avr6, + }), + }; + pub const avrtiny = Cpu{ + .name = "avrtiny", + .llvm_name = "avrtiny", + .features = featureSet(&[_]Feature{ + .avrtiny, + }), + }; + pub const avrxmega1 = Cpu{ + .name = "avrxmega1", + .llvm_name = "avrxmega1", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const avrxmega2 = Cpu{ + .name = "avrxmega2", + .llvm_name = "avrxmega2", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const avrxmega3 = Cpu{ + .name = "avrxmega3", + .llvm_name = "avrxmega3", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const avrxmega4 = Cpu{ + .name = "avrxmega4", + .llvm_name = "avrxmega4", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const avrxmega5 = Cpu{ + .name = "avrxmega5", + .llvm_name = "avrxmega5", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const avrxmega6 = Cpu{ + .name = "avrxmega6", + .llvm_name = "avrxmega6", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const avrxmega7 = Cpu{ + .name = "avrxmega7", + .llvm_name = "avrxmega7", + .features = featureSet(&[_]Feature{ + .xmega, + }), + }; + pub const m3000 = Cpu{ + .name = "m3000", + .llvm_name = "m3000", + .features = featureSet(&[_]Feature{ + .avr5, + }), + }; +}; + +/// All avr CPUs, sorted alphabetically by name. +/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 +/// compiler has inefficient memory and CPU usage, affecting build times. +pub const all_cpus = &[_]*const Cpu{ + &cpu.at43usb320, + &cpu.at43usb355, + &cpu.at76c711, + &cpu.at86rf401, + &cpu.at90c8534, + &cpu.at90can128, + &cpu.at90can32, + &cpu.at90can64, + &cpu.at90pwm1, + &cpu.at90pwm161, + &cpu.at90pwm2, + &cpu.at90pwm216, + &cpu.at90pwm2b, + &cpu.at90pwm3, + &cpu.at90pwm316, + &cpu.at90pwm3b, + &cpu.at90pwm81, + &cpu.at90s1200, + &cpu.at90s2313, + &cpu.at90s2323, + &cpu.at90s2333, + &cpu.at90s2343, + &cpu.at90s4414, + &cpu.at90s4433, + &cpu.at90s4434, + &cpu.at90s8515, + &cpu.at90s8535, + &cpu.at90scr100, + &cpu.at90usb1286, + &cpu.at90usb1287, + &cpu.at90usb162, + &cpu.at90usb646, + &cpu.at90usb647, + &cpu.at90usb82, + &cpu.at94k, + &cpu.ata5272, + &cpu.ata5505, + &cpu.ata5790, + &cpu.ata5795, + &cpu.ata6285, + &cpu.ata6286, + &cpu.ata6289, + &cpu.atmega103, + &cpu.atmega128, + &cpu.atmega1280, + &cpu.atmega1281, + &cpu.atmega1284, + &cpu.atmega1284p, + &cpu.atmega1284rfr2, + &cpu.atmega128a, + &cpu.atmega128rfa1, + &cpu.atmega128rfr2, + &cpu.atmega16, + &cpu.atmega161, + &cpu.atmega162, + &cpu.atmega163, + &cpu.atmega164a, + &cpu.atmega164p, + &cpu.atmega164pa, + &cpu.atmega165, + &cpu.atmega165a, + &cpu.atmega165p, + &cpu.atmega165pa, + &cpu.atmega168, + &cpu.atmega168a, + &cpu.atmega168p, + &cpu.atmega168pa, + &cpu.atmega169, + &cpu.atmega169a, + &cpu.atmega169p, + &cpu.atmega169pa, + &cpu.atmega16a, + &cpu.atmega16hva, + &cpu.atmega16hva2, + &cpu.atmega16hvb, + &cpu.atmega16hvbrevb, + &cpu.atmega16m1, + &cpu.atmega16u2, + &cpu.atmega16u4, + &cpu.atmega2560, + &cpu.atmega2561, + &cpu.atmega2564rfr2, + &cpu.atmega256rfr2, + &cpu.atmega32, + &cpu.atmega323, + &cpu.atmega324a, + &cpu.atmega324p, + &cpu.atmega324pa, + &cpu.atmega325, + &cpu.atmega3250, + &cpu.atmega3250a, + &cpu.atmega3250p, + &cpu.atmega3250pa, + &cpu.atmega325a, + &cpu.atmega325p, + &cpu.atmega325pa, + &cpu.atmega328, + &cpu.atmega328p, + &cpu.atmega329, + &cpu.atmega3290, + &cpu.atmega3290a, + &cpu.atmega3290p, + &cpu.atmega3290pa, + &cpu.atmega329a, + &cpu.atmega329p, + &cpu.atmega329pa, + &cpu.atmega32a, + &cpu.atmega32c1, + &cpu.atmega32hvb, + &cpu.atmega32hvbrevb, + &cpu.atmega32m1, + &cpu.atmega32u2, + &cpu.atmega32u4, + &cpu.atmega32u6, + &cpu.atmega406, + &cpu.atmega48, + &cpu.atmega48a, + &cpu.atmega48p, + &cpu.atmega48pa, + &cpu.atmega64, + &cpu.atmega640, + &cpu.atmega644, + &cpu.atmega644a, + &cpu.atmega644p, + &cpu.atmega644pa, + &cpu.atmega644rfr2, + &cpu.atmega645, + &cpu.atmega6450, + &cpu.atmega6450a, + &cpu.atmega6450p, + &cpu.atmega645a, + &cpu.atmega645p, + &cpu.atmega649, + &cpu.atmega6490, + &cpu.atmega6490a, + &cpu.atmega6490p, + &cpu.atmega649a, + &cpu.atmega649p, + &cpu.atmega64a, + &cpu.atmega64c1, + &cpu.atmega64hve, + &cpu.atmega64m1, + &cpu.atmega64rfr2, + &cpu.atmega8, + &cpu.atmega8515, + &cpu.atmega8535, + &cpu.atmega88, + &cpu.atmega88a, + &cpu.atmega88p, + &cpu.atmega88pa, + &cpu.atmega8a, + &cpu.atmega8hva, + &cpu.atmega8u2, + &cpu.attiny10, + &cpu.attiny102, + &cpu.attiny104, + &cpu.attiny11, + &cpu.attiny12, + &cpu.attiny13, + &cpu.attiny13a, + &cpu.attiny15, + &cpu.attiny1634, + &cpu.attiny167, + &cpu.attiny20, + &cpu.attiny22, + &cpu.attiny2313, + &cpu.attiny2313a, + &cpu.attiny24, + &cpu.attiny24a, + &cpu.attiny25, + &cpu.attiny26, + &cpu.attiny261, + &cpu.attiny261a, + &cpu.attiny28, + &cpu.attiny4, + &cpu.attiny40, + &cpu.attiny4313, + &cpu.attiny43u, + &cpu.attiny44, + &cpu.attiny44a, + &cpu.attiny45, + &cpu.attiny461, + &cpu.attiny461a, + &cpu.attiny48, + &cpu.attiny5, + &cpu.attiny828, + &cpu.attiny84, + &cpu.attiny84a, + &cpu.attiny85, + &cpu.attiny861, + &cpu.attiny861a, + &cpu.attiny87, + &cpu.attiny88, + &cpu.attiny9, + &cpu.atxmega128a1, + &cpu.atxmega128a1u, + &cpu.atxmega128a3, + &cpu.atxmega128a3u, + &cpu.atxmega128a4u, + &cpu.atxmega128b1, + &cpu.atxmega128b3, + &cpu.atxmega128c3, + &cpu.atxmega128d3, + &cpu.atxmega128d4, + &cpu.atxmega16a4, + &cpu.atxmega16a4u, + &cpu.atxmega16c4, + &cpu.atxmega16d4, + &cpu.atxmega16e5, + &cpu.atxmega192a3, + &cpu.atxmega192a3u, + &cpu.atxmega192c3, + &cpu.atxmega192d3, + &cpu.atxmega256a3, + &cpu.atxmega256a3b, + &cpu.atxmega256a3bu, + &cpu.atxmega256a3u, + &cpu.atxmega256c3, + &cpu.atxmega256d3, + &cpu.atxmega32a4, + &cpu.atxmega32a4u, + &cpu.atxmega32c4, + &cpu.atxmega32d4, + &cpu.atxmega32e5, + &cpu.atxmega32x1, + &cpu.atxmega384c3, + &cpu.atxmega384d3, + &cpu.atxmega64a1, + &cpu.atxmega64a1u, + &cpu.atxmega64a3, + &cpu.atxmega64a3u, + &cpu.atxmega64a4u, + &cpu.atxmega64b1, + &cpu.atxmega64b3, + &cpu.atxmega64c3, + &cpu.atxmega64d3, + &cpu.atxmega64d4, + &cpu.atxmega8e5, + &cpu.avr1, + &cpu.avr2, + &cpu.avr25, + &cpu.avr3, + &cpu.avr31, + &cpu.avr35, + &cpu.avr4, + &cpu.avr5, + &cpu.avr51, + &cpu.avr6, + &cpu.avrtiny, + &cpu.avrxmega1, + &cpu.avrxmega2, + &cpu.avrxmega3, + &cpu.avrxmega4, + &cpu.avrxmega5, + &cpu.avrxmega6, + &cpu.avrxmega7, + &cpu.m3000, +}; diff --git a/lib/std/target/bpf.zig b/lib/std/target/bpf.zig new file mode 100644 index 0000000000..b6179075cc --- /dev/null +++ b/lib/std/target/bpf.zig @@ -0,0 +1,76 @@ +const std = @import("../std.zig"); +const Cpu = std.Target.Cpu; + +pub const Feature = enum { + alu32, + dummy, + dwarfris, +}; + +pub usingnamespace Cpu.Feature.feature_set_fns(Feature); + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); + var result: [len]Cpu.Feature = undefined; + result[@enumToInt(Feature.alu32)] = .{ + .llvm_name = "alu32", + .description = "Enable ALU32 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dummy)] = .{ + .llvm_name = "dummy", + .description = "unused feature", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dwarfris)] = .{ + .llvm_name = "dwarfris", + .description = "Disable MCAsmInfo DwarfUsesRelocationsAcrossSections", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (result) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const generic = Cpu{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{}), + }; + pub const probe = Cpu{ + .name = "probe", + .llvm_name = "probe", + .features = featureSet(&[_]Feature{}), + }; + pub const v1 = Cpu{ + .name = "v1", + .llvm_name = "v1", + .features = featureSet(&[_]Feature{}), + }; + pub const v2 = Cpu{ + .name = "v2", + .llvm_name = "v2", + .features = featureSet(&[_]Feature{}), + }; + pub const v3 = Cpu{ + .name = "v3", + .llvm_name = "v3", + .features = featureSet(&[_]Feature{}), + }; +}; + +/// All bpf CPUs, sorted alphabetically by name. +/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 +/// compiler has inefficient memory and CPU usage, affecting build times. +pub const all_cpus = &[_]*const Cpu{ + &cpu.generic, + &cpu.probe, + &cpu.v1, + &cpu.v2, + &cpu.v3, +}; diff --git a/lib/std/target/hexagon.zig b/lib/std/target/hexagon.zig new file mode 100644 index 0000000000..f873237493 --- /dev/null +++ b/lib/std/target/hexagon.zig @@ -0,0 +1,312 @@ +const std = @import("../std.zig"); +const Cpu = std.Target.Cpu; + +pub const Feature = enum { + duplex, + hvx, + hvx_length128b, + hvx_length64b, + hvxv60, + hvxv62, + hvxv65, + hvxv66, + long_calls, + mem_noshuf, + memops, + noreturn_stack_elim, + nvj, + nvs, + packets, + reserved_r19, + small_data, + v5, + v55, + v60, + v62, + v65, + v66, + zreg, +}; + +pub usingnamespace Cpu.Feature.feature_set_fns(Feature); + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); + var result: [len]Cpu.Feature = undefined; + result[@enumToInt(Feature.duplex)] = .{ + .llvm_name = "duplex", + .description = "Enable generation of duplex instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.hvx)] = .{ + .llvm_name = "hvx", + .description = "Hexagon HVX instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.hvx_length128b)] = .{ + .llvm_name = "hvx-length128b", + .description = "Hexagon HVX 128B instructions", + .dependencies = featureSet(&[_]Feature{ + .hvx, + }), + }; + result[@enumToInt(Feature.hvx_length64b)] = .{ + .llvm_name = "hvx-length64b", + .description = "Hexagon HVX 64B instructions", + .dependencies = featureSet(&[_]Feature{ + .hvx, + }), + }; + result[@enumToInt(Feature.hvxv60)] = .{ + .llvm_name = "hvxv60", + .description = "Hexagon HVX instructions", + .dependencies = featureSet(&[_]Feature{ + .hvx, + }), + }; + result[@enumToInt(Feature.hvxv62)] = .{ + .llvm_name = "hvxv62", + .description = "Hexagon HVX instructions", + .dependencies = featureSet(&[_]Feature{ + .hvx, + .hvxv60, + }), + }; + result[@enumToInt(Feature.hvxv65)] = .{ + .llvm_name = "hvxv65", + .description = "Hexagon HVX instructions", + .dependencies = featureSet(&[_]Feature{ + .hvx, + .hvxv60, + .hvxv62, + }), + }; + result[@enumToInt(Feature.hvxv66)] = .{ + .llvm_name = "hvxv66", + .description = "Hexagon HVX instructions", + .dependencies = featureSet(&[_]Feature{ + .hvx, + .hvxv60, + .hvxv62, + .hvxv65, + .zreg, + }), + }; + result[@enumToInt(Feature.long_calls)] = .{ + .llvm_name = "long-calls", + .description = "Use constant-extended calls", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mem_noshuf)] = .{ + .llvm_name = "mem_noshuf", + .description = "Supports mem_noshuf feature", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.memops)] = .{ + .llvm_name = "memops", + .description = "Use memop instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.noreturn_stack_elim)] = .{ + .llvm_name = "noreturn-stack-elim", + .description = "Eliminate stack allocation in a noreturn function when possible", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.nvj)] = .{ + .llvm_name = "nvj", + .description = "Support for new-value jumps", + .dependencies = featureSet(&[_]Feature{ + .packets, + }), + }; + result[@enumToInt(Feature.nvs)] = .{ + .llvm_name = "nvs", + .description = "Support for new-value stores", + .dependencies = featureSet(&[_]Feature{ + .packets, + }), + }; + result[@enumToInt(Feature.packets)] = .{ + .llvm_name = "packets", + .description = "Support for instruction packets", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reserved_r19)] = .{ + .llvm_name = "reserved-r19", + .description = "Reserve register R19", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.small_data)] = .{ + .llvm_name = "small-data", + .description = "Allow GP-relative addressing of global variables", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.v5)] = .{ + .llvm_name = "v5", + .description = "Enable Hexagon V5 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.v55)] = .{ + .llvm_name = "v55", + .description = "Enable Hexagon V55 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.v60)] = .{ + .llvm_name = "v60", + .description = "Enable Hexagon V60 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.v62)] = .{ + .llvm_name = "v62", + .description = "Enable Hexagon V62 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.v65)] = .{ + .llvm_name = "v65", + .description = "Enable Hexagon V65 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.v66)] = .{ + .llvm_name = "v66", + .description = "Enable Hexagon V66 architecture", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.zreg)] = .{ + .llvm_name = "zreg", + .description = "Hexagon ZReg extension instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (result) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const generic = Cpu{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{ + .duplex, + .memops, + .nvj, + .nvs, + .packets, + .small_data, + .v5, + .v55, + .v60, + }), + }; + pub const hexagonv5 = Cpu{ + .name = "hexagonv5", + .llvm_name = "hexagonv5", + .features = featureSet(&[_]Feature{ + .duplex, + .memops, + .nvj, + .nvs, + .packets, + .small_data, + .v5, + }), + }; + pub const hexagonv55 = Cpu{ + .name = "hexagonv55", + .llvm_name = "hexagonv55", + .features = featureSet(&[_]Feature{ + .duplex, + .memops, + .nvj, + .nvs, + .packets, + .small_data, + .v5, + .v55, + }), + }; + pub const hexagonv60 = Cpu{ + .name = "hexagonv60", + .llvm_name = "hexagonv60", + .features = featureSet(&[_]Feature{ + .duplex, + .memops, + .nvj, + .nvs, + .packets, + .small_data, + .v5, + .v55, + .v60, + }), + }; + pub const hexagonv62 = Cpu{ + .name = "hexagonv62", + .llvm_name = "hexagonv62", + .features = featureSet(&[_]Feature{ + .duplex, + .memops, + .nvj, + .nvs, + .packets, + .small_data, + .v5, + .v55, + .v60, + .v62, + }), + }; + pub const hexagonv65 = Cpu{ + .name = "hexagonv65", + .llvm_name = "hexagonv65", + .features = featureSet(&[_]Feature{ + .duplex, + .mem_noshuf, + .memops, + .nvj, + .nvs, + .packets, + .small_data, + .v5, + .v55, + .v60, + .v62, + .v65, + }), + }; + pub const hexagonv66 = Cpu{ + .name = "hexagonv66", + .llvm_name = "hexagonv66", + .features = featureSet(&[_]Feature{ + .duplex, + .mem_noshuf, + .memops, + .nvj, + .nvs, + .packets, + .small_data, + .v5, + .v55, + .v60, + .v62, + .v65, + .v66, + }), + }; +}; + +/// All hexagon CPUs, sorted alphabetically by name. +/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 +/// compiler has inefficient memory and CPU usage, affecting build times. +pub const all_cpus = &[_]*const Cpu{ + &cpu.generic, + &cpu.hexagonv5, + &cpu.hexagonv55, + &cpu.hexagonv60, + &cpu.hexagonv62, + &cpu.hexagonv65, + &cpu.hexagonv66, +}; diff --git a/lib/std/target/mips.zig b/lib/std/target/mips.zig new file mode 100644 index 0000000000..fce7c9ce36 --- /dev/null +++ b/lib/std/target/mips.zig @@ -0,0 +1,518 @@ +const std = @import("../std.zig"); +const Cpu = std.Target.Cpu; + +pub const Feature = enum { + abs2008, + cnmips, + crc, + dsp, + dspr2, + dspr3, + eva, + fp64, + fpxx, + ginv, + gp64, + long_calls, + micromips, + mips1, + mips16, + mips2, + mips3, + mips32, + mips32r2, + mips32r3, + mips32r5, + mips32r6, + mips3_32, + mips3_32r2, + mips4, + mips4_32, + mips4_32r2, + mips5, + mips5_32r2, + mips64, + mips64r2, + mips64r3, + mips64r5, + mips64r6, + msa, + mt, + nan2008, + noabicalls, + nomadd4, + nooddspreg, + p5600, + ptr64, + single_float, + soft_float, + sym32, + use_indirect_jump_hazard, + use_tcc_in_div, + vfpu, + virt, +}; + +pub usingnamespace Cpu.Feature.feature_set_fns(Feature); + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); + var result: [len]Cpu.Feature = undefined; + result[@enumToInt(Feature.abs2008)] = .{ + .llvm_name = "abs2008", + .description = "Disable IEEE 754-2008 abs.fmt mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.cnmips)] = .{ + .llvm_name = "cnmips", + .description = "Octeon cnMIPS Support", + .dependencies = featureSet(&[_]Feature{ + .mips64r2, + }), + }; + result[@enumToInt(Feature.crc)] = .{ + .llvm_name = "crc", + .description = "Mips R6 CRC ASE", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dsp)] = .{ + .llvm_name = "dsp", + .description = "Mips DSP ASE", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dspr2)] = .{ + .llvm_name = "dspr2", + .description = "Mips DSP-R2 ASE", + .dependencies = featureSet(&[_]Feature{ + .dsp, + }), + }; + result[@enumToInt(Feature.dspr3)] = .{ + .llvm_name = "dspr3", + .description = "Mips DSP-R3 ASE", + .dependencies = featureSet(&[_]Feature{ + .dsp, + .dspr2, + }), + }; + result[@enumToInt(Feature.eva)] = .{ + .llvm_name = "eva", + .description = "Mips EVA ASE", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fp64)] = .{ + .llvm_name = "fp64", + .description = "Support 64-bit FP registers", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fpxx)] = .{ + .llvm_name = "fpxx", + .description = "Support for FPXX", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ginv)] = .{ + .llvm_name = "ginv", + .description = "Mips Global Invalidate ASE", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.gp64)] = .{ + .llvm_name = "gp64", + .description = "General Purpose Registers are 64-bit wide", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.long_calls)] = .{ + .llvm_name = "long-calls", + .description = "Disable use of the jal instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.micromips)] = .{ + .llvm_name = "micromips", + .description = "microMips mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mips1)] = .{ + .llvm_name = "mips1", + .description = "Mips I ISA Support [highly experimental]", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mips16)] = .{ + .llvm_name = "mips16", + .description = "Mips16 mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mips2)] = .{ + .llvm_name = "mips2", + .description = "Mips II ISA Support [highly experimental]", + .dependencies = featureSet(&[_]Feature{ + .mips1, + }), + }; + result[@enumToInt(Feature.mips3)] = .{ + .llvm_name = "mips3", + .description = "MIPS III ISA Support [highly experimental]", + .dependencies = featureSet(&[_]Feature{ + .fp64, + .gp64, + .mips2, + .mips3_32, + .mips3_32r2, + }), + }; + result[@enumToInt(Feature.mips32)] = .{ + .llvm_name = "mips32", + .description = "Mips32 ISA Support", + .dependencies = featureSet(&[_]Feature{ + .mips2, + .mips3_32, + .mips4_32, + }), + }; + result[@enumToInt(Feature.mips32r2)] = .{ + .llvm_name = "mips32r2", + .description = "Mips32r2 ISA Support", + .dependencies = featureSet(&[_]Feature{ + .mips32, + .mips3_32r2, + .mips4_32r2, + .mips5_32r2, + }), + }; + result[@enumToInt(Feature.mips32r3)] = .{ + .llvm_name = "mips32r3", + .description = "Mips32r3 ISA Support", + .dependencies = featureSet(&[_]Feature{ + .mips32r2, + }), + }; + result[@enumToInt(Feature.mips32r5)] = .{ + .llvm_name = "mips32r5", + .description = "Mips32r5 ISA Support", + .dependencies = featureSet(&[_]Feature{ + .mips32r3, + }), + }; + result[@enumToInt(Feature.mips32r6)] = .{ + .llvm_name = "mips32r6", + .description = "Mips32r6 ISA Support [experimental]", + .dependencies = featureSet(&[_]Feature{ + .abs2008, + .fp64, + .mips32r5, + .nan2008, + }), + }; + result[@enumToInt(Feature.mips3_32)] = .{ + .llvm_name = "mips3_32", + .description = "Subset of MIPS-III that is also in MIPS32 [highly experimental]", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mips3_32r2)] = .{ + .llvm_name = "mips3_32r2", + .description = "Subset of MIPS-III that is also in MIPS32r2 [highly experimental]", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mips4)] = .{ + .llvm_name = "mips4", + .description = "MIPS IV ISA Support", + .dependencies = featureSet(&[_]Feature{ + .mips3, + .mips4_32, + .mips4_32r2, + }), + }; + result[@enumToInt(Feature.mips4_32)] = .{ + .llvm_name = "mips4_32", + .description = "Subset of MIPS-IV that is also in MIPS32 [highly experimental]", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mips4_32r2)] = .{ + .llvm_name = "mips4_32r2", + .description = "Subset of MIPS-IV that is also in MIPS32r2 [highly experimental]", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mips5)] = .{ + .llvm_name = "mips5", + .description = "MIPS V ISA Support [highly experimental]", + .dependencies = featureSet(&[_]Feature{ + .mips4, + .mips5_32r2, + }), + }; + result[@enumToInt(Feature.mips5_32r2)] = .{ + .llvm_name = "mips5_32r2", + .description = "Subset of MIPS-V that is also in MIPS32r2 [highly experimental]", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mips64)] = .{ + .llvm_name = "mips64", + .description = "Mips64 ISA Support", + .dependencies = featureSet(&[_]Feature{ + .mips32, + .mips5, + }), + }; + result[@enumToInt(Feature.mips64r2)] = .{ + .llvm_name = "mips64r2", + .description = "Mips64r2 ISA Support", + .dependencies = featureSet(&[_]Feature{ + .mips32r2, + .mips64, + }), + }; + result[@enumToInt(Feature.mips64r3)] = .{ + .llvm_name = "mips64r3", + .description = "Mips64r3 ISA Support", + .dependencies = featureSet(&[_]Feature{ + .mips32r3, + .mips64r2, + }), + }; + result[@enumToInt(Feature.mips64r5)] = .{ + .llvm_name = "mips64r5", + .description = "Mips64r5 ISA Support", + .dependencies = featureSet(&[_]Feature{ + .mips32r5, + .mips64r3, + }), + }; + result[@enumToInt(Feature.mips64r6)] = .{ + .llvm_name = "mips64r6", + .description = "Mips64r6 ISA Support [experimental]", + .dependencies = featureSet(&[_]Feature{ + .abs2008, + .mips32r6, + .mips64r5, + .nan2008, + }), + }; + result[@enumToInt(Feature.msa)] = .{ + .llvm_name = "msa", + .description = "Mips MSA ASE", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mt)] = .{ + .llvm_name = "mt", + .description = "Mips MT ASE", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.nan2008)] = .{ + .llvm_name = "nan2008", + .description = "IEEE 754-2008 NaN encoding", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.noabicalls)] = .{ + .llvm_name = "noabicalls", + .description = "Disable SVR4-style position-independent code", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.nomadd4)] = .{ + .llvm_name = "nomadd4", + .description = "Disable 4-operand madd.fmt and related instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.nooddspreg)] = .{ + .llvm_name = "nooddspreg", + .description = "Disable odd numbered single-precision registers", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.p5600)] = .{ + .llvm_name = "p5600", + .description = "The P5600 Processor", + .dependencies = featureSet(&[_]Feature{ + .mips32r5, + }), + }; + result[@enumToInt(Feature.ptr64)] = .{ + .llvm_name = "ptr64", + .description = "Pointers are 64-bit wide", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.single_float)] = .{ + .llvm_name = "single-float", + .description = "Only supports single precision float", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.soft_float)] = .{ + .llvm_name = "soft-float", + .description = "Does not support floating point instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sym32)] = .{ + .llvm_name = "sym32", + .description = "Symbols are 32 bit on Mips64", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.use_indirect_jump_hazard)] = .{ + .llvm_name = "use-indirect-jump-hazard", + .description = "Use indirect jump guards to prevent certain speculation based attacks", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.use_tcc_in_div)] = .{ + .llvm_name = "use-tcc-in-div", + .description = "Force the assembler to use trapping", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vfpu)] = .{ + .llvm_name = "vfpu", + .description = "Enable vector FPU instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.virt)] = .{ + .llvm_name = "virt", + .description = "Mips Virtualization ASE", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (result) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const mips1 = Cpu{ + .name = "mips1", + .llvm_name = "mips1", + .features = featureSet(&[_]Feature{ + .mips1, + }), + }; + pub const mips2 = Cpu{ + .name = "mips2", + .llvm_name = "mips2", + .features = featureSet(&[_]Feature{ + .mips2, + }), + }; + pub const mips3 = Cpu{ + .name = "mips3", + .llvm_name = "mips3", + .features = featureSet(&[_]Feature{ + .mips3, + }), + }; + pub const mips32 = Cpu{ + .name = "mips32", + .llvm_name = "mips32", + .features = featureSet(&[_]Feature{ + .mips32, + }), + }; + pub const mips32r2 = Cpu{ + .name = "mips32r2", + .llvm_name = "mips32r2", + .features = featureSet(&[_]Feature{ + .mips32r2, + }), + }; + pub const mips32r3 = Cpu{ + .name = "mips32r3", + .llvm_name = "mips32r3", + .features = featureSet(&[_]Feature{ + .mips32r3, + }), + }; + pub const mips32r5 = Cpu{ + .name = "mips32r5", + .llvm_name = "mips32r5", + .features = featureSet(&[_]Feature{ + .mips32r5, + }), + }; + pub const mips32r6 = Cpu{ + .name = "mips32r6", + .llvm_name = "mips32r6", + .features = featureSet(&[_]Feature{ + .mips32r6, + }), + }; + pub const mips4 = Cpu{ + .name = "mips4", + .llvm_name = "mips4", + .features = featureSet(&[_]Feature{ + .mips4, + }), + }; + pub const mips5 = Cpu{ + .name = "mips5", + .llvm_name = "mips5", + .features = featureSet(&[_]Feature{ + .mips5, + }), + }; + pub const mips64 = Cpu{ + .name = "mips64", + .llvm_name = "mips64", + .features = featureSet(&[_]Feature{ + .mips64, + }), + }; + pub const mips64r2 = Cpu{ + .name = "mips64r2", + .llvm_name = "mips64r2", + .features = featureSet(&[_]Feature{ + .mips64r2, + }), + }; + pub const mips64r3 = Cpu{ + .name = "mips64r3", + .llvm_name = "mips64r3", + .features = featureSet(&[_]Feature{ + .mips64r3, + }), + }; + pub const mips64r5 = Cpu{ + .name = "mips64r5", + .llvm_name = "mips64r5", + .features = featureSet(&[_]Feature{ + .mips64r5, + }), + }; + pub const mips64r6 = Cpu{ + .name = "mips64r6", + .llvm_name = "mips64r6", + .features = featureSet(&[_]Feature{ + .mips64r6, + }), + }; + pub const octeon = Cpu{ + .name = "octeon", + .llvm_name = "octeon", + .features = featureSet(&[_]Feature{ + .cnmips, + .mips64r2, + }), + }; + pub const p5600 = Cpu{ + .name = "p5600", + .llvm_name = "p5600", + .features = featureSet(&[_]Feature{ + .p5600, + }), + }; +}; + +/// All mips CPUs, sorted alphabetically by name. +/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 +/// compiler has inefficient memory and CPU usage, affecting build times. +pub const all_cpus = &[_]*const Cpu{ + &cpu.mips1, + &cpu.mips2, + &cpu.mips3, + &cpu.mips32, + &cpu.mips32r2, + &cpu.mips32r3, + &cpu.mips32r5, + &cpu.mips32r6, + &cpu.mips4, + &cpu.mips5, + &cpu.mips64, + &cpu.mips64r2, + &cpu.mips64r3, + &cpu.mips64r5, + &cpu.mips64r6, + &cpu.octeon, + &cpu.p5600, +}; diff --git a/lib/std/target/msp430.zig b/lib/std/target/msp430.zig new file mode 100644 index 0000000000..bc932f2295 --- /dev/null +++ b/lib/std/target/msp430.zig @@ -0,0 +1,72 @@ +const std = @import("../std.zig"); +const Cpu = std.Target.Cpu; + +pub const Feature = enum { + ext, + hwmult16, + hwmult32, + hwmultf5, +}; + +pub usingnamespace Cpu.Feature.feature_set_fns(Feature); + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); + var result: [len]Cpu.Feature = undefined; + result[@enumToInt(Feature.ext)] = .{ + .llvm_name = "ext", + .description = "Enable MSP430-X extensions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.hwmult16)] = .{ + .llvm_name = "hwmult16", + .description = "Enable 16-bit hardware multiplier", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.hwmult32)] = .{ + .llvm_name = "hwmult32", + .description = "Enable 32-bit hardware multiplier", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.hwmultf5)] = .{ + .llvm_name = "hwmultf5", + .description = "Enable F5 series hardware multiplier", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (result) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const generic = Cpu{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{}), + }; + pub const msp430 = Cpu{ + .name = "msp430", + .llvm_name = "msp430", + .features = featureSet(&[_]Feature{}), + }; + pub const msp430x = Cpu{ + .name = "msp430x", + .llvm_name = "msp430x", + .features = featureSet(&[_]Feature{ + .ext, + }), + }; +}; + +/// All msp430 CPUs, sorted alphabetically by name. +/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 +/// compiler has inefficient memory and CPU usage, affecting build times. +pub const all_cpus = &[_]*const Cpu{ + &cpu.generic, + &cpu.msp430, + &cpu.msp430x, +}; diff --git a/lib/std/target/nvptx.zig b/lib/std/target/nvptx.zig new file mode 100644 index 0000000000..1800e320b4 --- /dev/null +++ b/lib/std/target/nvptx.zig @@ -0,0 +1,309 @@ +const std = @import("../std.zig"); +const Cpu = std.Target.Cpu; + +pub const Feature = enum { + ptx32, + ptx40, + ptx41, + ptx42, + ptx43, + ptx50, + ptx60, + ptx61, + ptx63, + ptx64, + sm_20, + sm_21, + sm_30, + sm_32, + sm_35, + sm_37, + sm_50, + sm_52, + sm_53, + sm_60, + sm_61, + sm_62, + sm_70, + sm_72, + sm_75, +}; + +pub usingnamespace Cpu.Feature.feature_set_fns(Feature); + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); + var result: [len]Cpu.Feature = undefined; + result[@enumToInt(Feature.ptx32)] = .{ + .llvm_name = "ptx32", + .description = "Use PTX version 3.2", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ptx40)] = .{ + .llvm_name = "ptx40", + .description = "Use PTX version 4.0", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ptx41)] = .{ + .llvm_name = "ptx41", + .description = "Use PTX version 4.1", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ptx42)] = .{ + .llvm_name = "ptx42", + .description = "Use PTX version 4.2", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ptx43)] = .{ + .llvm_name = "ptx43", + .description = "Use PTX version 4.3", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ptx50)] = .{ + .llvm_name = "ptx50", + .description = "Use PTX version 5.0", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ptx60)] = .{ + .llvm_name = "ptx60", + .description = "Use PTX version 6.0", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ptx61)] = .{ + .llvm_name = "ptx61", + .description = "Use PTX version 6.1", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ptx63)] = .{ + .llvm_name = "ptx63", + .description = "Use PTX version 6.3", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ptx64)] = .{ + .llvm_name = "ptx64", + .description = "Use PTX version 6.4", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sm_20)] = .{ + .llvm_name = "sm_20", + .description = "Target SM 2.0", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sm_21)] = .{ + .llvm_name = "sm_21", + .description = "Target SM 2.1", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sm_30)] = .{ + .llvm_name = "sm_30", + .description = "Target SM 3.0", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sm_32)] = .{ + .llvm_name = "sm_32", + .description = "Target SM 3.2", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sm_35)] = .{ + .llvm_name = "sm_35", + .description = "Target SM 3.5", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sm_37)] = .{ + .llvm_name = "sm_37", + .description = "Target SM 3.7", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sm_50)] = .{ + .llvm_name = "sm_50", + .description = "Target SM 5.0", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sm_52)] = .{ + .llvm_name = "sm_52", + .description = "Target SM 5.2", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sm_53)] = .{ + .llvm_name = "sm_53", + .description = "Target SM 5.3", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sm_60)] = .{ + .llvm_name = "sm_60", + .description = "Target SM 6.0", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sm_61)] = .{ + .llvm_name = "sm_61", + .description = "Target SM 6.1", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sm_62)] = .{ + .llvm_name = "sm_62", + .description = "Target SM 6.2", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sm_70)] = .{ + .llvm_name = "sm_70", + .description = "Target SM 7.0", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sm_72)] = .{ + .llvm_name = "sm_72", + .description = "Target SM 7.2", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sm_75)] = .{ + .llvm_name = "sm_75", + .description = "Target SM 7.5", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (result) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const sm_20 = Cpu{ + .name = "sm_20", + .llvm_name = "sm_20", + .features = featureSet(&[_]Feature{ + .sm_20, + }), + }; + pub const sm_21 = Cpu{ + .name = "sm_21", + .llvm_name = "sm_21", + .features = featureSet(&[_]Feature{ + .sm_21, + }), + }; + pub const sm_30 = Cpu{ + .name = "sm_30", + .llvm_name = "sm_30", + .features = featureSet(&[_]Feature{ + .sm_30, + }), + }; + pub const sm_32 = Cpu{ + .name = "sm_32", + .llvm_name = "sm_32", + .features = featureSet(&[_]Feature{ + .ptx40, + .sm_32, + }), + }; + pub const sm_35 = Cpu{ + .name = "sm_35", + .llvm_name = "sm_35", + .features = featureSet(&[_]Feature{ + .sm_35, + }), + }; + pub const sm_37 = Cpu{ + .name = "sm_37", + .llvm_name = "sm_37", + .features = featureSet(&[_]Feature{ + .ptx41, + .sm_37, + }), + }; + pub const sm_50 = Cpu{ + .name = "sm_50", + .llvm_name = "sm_50", + .features = featureSet(&[_]Feature{ + .ptx40, + .sm_50, + }), + }; + pub const sm_52 = Cpu{ + .name = "sm_52", + .llvm_name = "sm_52", + .features = featureSet(&[_]Feature{ + .ptx41, + .sm_52, + }), + }; + pub const sm_53 = Cpu{ + .name = "sm_53", + .llvm_name = "sm_53", + .features = featureSet(&[_]Feature{ + .ptx42, + .sm_53, + }), + }; + pub const sm_60 = Cpu{ + .name = "sm_60", + .llvm_name = "sm_60", + .features = featureSet(&[_]Feature{ + .ptx50, + .sm_60, + }), + }; + pub const sm_61 = Cpu{ + .name = "sm_61", + .llvm_name = "sm_61", + .features = featureSet(&[_]Feature{ + .ptx50, + .sm_61, + }), + }; + pub const sm_62 = Cpu{ + .name = "sm_62", + .llvm_name = "sm_62", + .features = featureSet(&[_]Feature{ + .ptx50, + .sm_62, + }), + }; + pub const sm_70 = Cpu{ + .name = "sm_70", + .llvm_name = "sm_70", + .features = featureSet(&[_]Feature{ + .ptx60, + .sm_70, + }), + }; + pub const sm_72 = Cpu{ + .name = "sm_72", + .llvm_name = "sm_72", + .features = featureSet(&[_]Feature{ + .ptx61, + .sm_72, + }), + }; + pub const sm_75 = Cpu{ + .name = "sm_75", + .llvm_name = "sm_75", + .features = featureSet(&[_]Feature{ + .ptx63, + .sm_75, + }), + }; +}; + +/// All nvptx CPUs, sorted alphabetically by name. +/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 +/// compiler has inefficient memory and CPU usage, affecting build times. +pub const all_cpus = &[_]*const Cpu{ + &cpu.sm_20, + &cpu.sm_21, + &cpu.sm_30, + &cpu.sm_32, + &cpu.sm_35, + &cpu.sm_37, + &cpu.sm_50, + &cpu.sm_52, + &cpu.sm_53, + &cpu.sm_60, + &cpu.sm_61, + &cpu.sm_62, + &cpu.sm_70, + &cpu.sm_72, + &cpu.sm_75, +}; diff --git a/lib/std/target/powerpc.zig b/lib/std/target/powerpc.zig new file mode 100644 index 0000000000..41321f7b04 --- /dev/null +++ b/lib/std/target/powerpc.zig @@ -0,0 +1,938 @@ +const std = @import("../std.zig"); +const Cpu = std.Target.Cpu; + +pub const Feature = enum { + @"64bit", + @"64bitregs", + altivec, + booke, + bpermd, + cmpb, + crbits, + crypto, + direct_move, + e500, + extdiv, + fcpsgn, + float128, + fpcvt, + fprnd, + fpu, + fre, + fres, + frsqrte, + frsqrtes, + fsqrt, + hard_float, + htm, + icbt, + invariant_function_descriptors, + isa_v30_instructions, + isel, + ldbrx, + lfiwax, + longcall, + mfocrf, + msync, + partword_atomics, + popcntd, + power8_altivec, + power8_vector, + power9_altivec, + power9_vector, + ppc_postra_sched, + ppc_prera_sched, + ppc4xx, + ppc6xx, + qpx, + recipprec, + secure_plt, + slow_popcntd, + spe, + stfiwx, + two_const_nr, + vectors_use_two_units, + vsx, +}; + +pub usingnamespace Cpu.Feature.feature_set_fns(Feature); + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); + var result: [len]Cpu.Feature = undefined; + result[@enumToInt(Feature.@"64bit")] = .{ + .llvm_name = "64bit", + .description = "Enable 64-bit instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.@"64bitregs")] = .{ + .llvm_name = "64bitregs", + .description = "Enable 64-bit registers usage for ppc32 [beta]", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.altivec)] = .{ + .llvm_name = "altivec", + .description = "Enable Altivec instructions", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@enumToInt(Feature.booke)] = .{ + .llvm_name = "booke", + .description = "Enable Book E instructions", + .dependencies = featureSet(&[_]Feature{ + .icbt, + }), + }; + result[@enumToInt(Feature.bpermd)] = .{ + .llvm_name = "bpermd", + .description = "Enable the bpermd instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.cmpb)] = .{ + .llvm_name = "cmpb", + .description = "Enable the cmpb instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.crbits)] = .{ + .llvm_name = "crbits", + .description = "Use condition-register bits individually", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.crypto)] = .{ + .llvm_name = "crypto", + .description = "Enable POWER8 Crypto instructions", + .dependencies = featureSet(&[_]Feature{ + .power8_altivec, + }), + }; + result[@enumToInt(Feature.direct_move)] = .{ + .llvm_name = "direct-move", + .description = "Enable Power8 direct move instructions", + .dependencies = featureSet(&[_]Feature{ + .vsx, + }), + }; + result[@enumToInt(Feature.e500)] = .{ + .llvm_name = "e500", + .description = "Enable E500/E500mc instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.extdiv)] = .{ + .llvm_name = "extdiv", + .description = "Enable extended divide instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fcpsgn)] = .{ + .llvm_name = "fcpsgn", + .description = "Enable the fcpsgn instruction", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@enumToInt(Feature.float128)] = .{ + .llvm_name = "float128", + .description = "Enable the __float128 data type for IEEE-754R Binary128.", + .dependencies = featureSet(&[_]Feature{ + .vsx, + }), + }; + result[@enumToInt(Feature.fpcvt)] = .{ + .llvm_name = "fpcvt", + .description = "Enable fc[ft]* (unsigned and single-precision) and lfiwzx instructions", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@enumToInt(Feature.fprnd)] = .{ + .llvm_name = "fprnd", + .description = "Enable the fri[mnpz] instructions", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@enumToInt(Feature.fpu)] = .{ + .llvm_name = "fpu", + .description = "Enable classic FPU instructions", + .dependencies = featureSet(&[_]Feature{ + .hard_float, + }), + }; + result[@enumToInt(Feature.fre)] = .{ + .llvm_name = "fre", + .description = "Enable the fre instruction", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@enumToInt(Feature.fres)] = .{ + .llvm_name = "fres", + .description = "Enable the fres instruction", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@enumToInt(Feature.frsqrte)] = .{ + .llvm_name = "frsqrte", + .description = "Enable the frsqrte instruction", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@enumToInt(Feature.frsqrtes)] = .{ + .llvm_name = "frsqrtes", + .description = "Enable the frsqrtes instruction", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@enumToInt(Feature.fsqrt)] = .{ + .llvm_name = "fsqrt", + .description = "Enable the fsqrt instruction", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@enumToInt(Feature.hard_float)] = .{ + .llvm_name = "hard-float", + .description = "Enable floating-point instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.htm)] = .{ + .llvm_name = "htm", + .description = "Enable Hardware Transactional Memory instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.icbt)] = .{ + .llvm_name = "icbt", + .description = "Enable icbt instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.invariant_function_descriptors)] = .{ + .llvm_name = "invariant-function-descriptors", + .description = "Assume function descriptors are invariant", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.isa_v30_instructions)] = .{ + .llvm_name = "isa-v30-instructions", + .description = "Enable instructions added in ISA 3.0.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.isel)] = .{ + .llvm_name = "isel", + .description = "Enable the isel instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ldbrx)] = .{ + .llvm_name = "ldbrx", + .description = "Enable the ldbrx instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.lfiwax)] = .{ + .llvm_name = "lfiwax", + .description = "Enable the lfiwax instruction", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@enumToInt(Feature.longcall)] = .{ + .llvm_name = "longcall", + .description = "Always use indirect calls", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mfocrf)] = .{ + .llvm_name = "mfocrf", + .description = "Enable the MFOCRF instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.msync)] = .{ + .llvm_name = "msync", + .description = "Has only the msync instruction instead of sync", + .dependencies = featureSet(&[_]Feature{ + .booke, + }), + }; + result[@enumToInt(Feature.partword_atomics)] = .{ + .llvm_name = "partword-atomics", + .description = "Enable l[bh]arx and st[bh]cx.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.popcntd)] = .{ + .llvm_name = "popcntd", + .description = "Enable the popcnt[dw] instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.power8_altivec)] = .{ + .llvm_name = "power8-altivec", + .description = "Enable POWER8 Altivec instructions", + .dependencies = featureSet(&[_]Feature{ + .altivec, + }), + }; + result[@enumToInt(Feature.power8_vector)] = .{ + .llvm_name = "power8-vector", + .description = "Enable POWER8 vector instructions", + .dependencies = featureSet(&[_]Feature{ + .power8_altivec, + .vsx, + }), + }; + result[@enumToInt(Feature.power9_altivec)] = .{ + .llvm_name = "power9-altivec", + .description = "Enable POWER9 Altivec instructions", + .dependencies = featureSet(&[_]Feature{ + .isa_v30_instructions, + .power8_altivec, + }), + }; + result[@enumToInt(Feature.power9_vector)] = .{ + .llvm_name = "power9-vector", + .description = "Enable POWER9 vector instructions", + .dependencies = featureSet(&[_]Feature{ + .isa_v30_instructions, + .power8_vector, + .power9_altivec, + }), + }; + result[@enumToInt(Feature.ppc_postra_sched)] = .{ + .llvm_name = "ppc-postra-sched", + .description = "Use PowerPC post-RA scheduling strategy", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ppc_prera_sched)] = .{ + .llvm_name = "ppc-prera-sched", + .description = "Use PowerPC pre-RA scheduling strategy", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ppc4xx)] = .{ + .llvm_name = "ppc4xx", + .description = "Enable PPC 4xx instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ppc6xx)] = .{ + .llvm_name = "ppc6xx", + .description = "Enable PPC 6xx instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.qpx)] = .{ + .llvm_name = "qpx", + .description = "Enable QPX instructions", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@enumToInt(Feature.recipprec)] = .{ + .llvm_name = "recipprec", + .description = "Assume higher precision reciprocal estimates", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.secure_plt)] = .{ + .llvm_name = "secure-plt", + .description = "Enable secure plt mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.slow_popcntd)] = .{ + .llvm_name = "slow-popcntd", + .description = "Has slow popcnt[dw] instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.spe)] = .{ + .llvm_name = "spe", + .description = "Enable SPE instructions", + .dependencies = featureSet(&[_]Feature{ + .hard_float, + }), + }; + result[@enumToInt(Feature.stfiwx)] = .{ + .llvm_name = "stfiwx", + .description = "Enable the stfiwx instruction", + .dependencies = featureSet(&[_]Feature{ + .fpu, + }), + }; + result[@enumToInt(Feature.two_const_nr)] = .{ + .llvm_name = "two-const-nr", + .description = "Requires two constant Newton-Raphson computation", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vectors_use_two_units)] = .{ + .llvm_name = "vectors-use-two-units", + .description = "Vectors use two units", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vsx)] = .{ + .llvm_name = "vsx", + .description = "Enable VSX instructions", + .dependencies = featureSet(&[_]Feature{ + .altivec, + }), + }; + const ti = @typeInfo(Feature); + for (result) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const @"440" = Cpu{ + .name = "440", + .llvm_name = "440", + .features = featureSet(&[_]Feature{ + .booke, + .fres, + .frsqrte, + .icbt, + .isel, + .msync, + }), + }; + pub const @"450" = Cpu{ + .name = "450", + .llvm_name = "450", + .features = featureSet(&[_]Feature{ + .booke, + .fres, + .frsqrte, + .icbt, + .isel, + .msync, + }), + }; + pub const @"601" = Cpu{ + .name = "601", + .llvm_name = "601", + .features = featureSet(&[_]Feature{ + .fpu, + }), + }; + pub const @"602" = Cpu{ + .name = "602", + .llvm_name = "602", + .features = featureSet(&[_]Feature{ + .fpu, + }), + }; + pub const @"603" = Cpu{ + .name = "603", + .llvm_name = "603", + .features = featureSet(&[_]Feature{ + .fres, + .frsqrte, + }), + }; + pub const @"603e" = Cpu{ + .name = "603e", + .llvm_name = "603e", + .features = featureSet(&[_]Feature{ + .fres, + .frsqrte, + }), + }; + pub const @"603ev" = Cpu{ + .name = "603ev", + .llvm_name = "603ev", + .features = featureSet(&[_]Feature{ + .fres, + .frsqrte, + }), + }; + pub const @"604" = Cpu{ + .name = "604", + .llvm_name = "604", + .features = featureSet(&[_]Feature{ + .fres, + .frsqrte, + }), + }; + pub const @"604e" = Cpu{ + .name = "604e", + .llvm_name = "604e", + .features = featureSet(&[_]Feature{ + .fres, + .frsqrte, + }), + }; + pub const @"620" = Cpu{ + .name = "620", + .llvm_name = "620", + .features = featureSet(&[_]Feature{ + .fres, + .frsqrte, + }), + }; + pub const @"7400" = Cpu{ + .name = "7400", + .llvm_name = "7400", + .features = featureSet(&[_]Feature{ + .altivec, + .fres, + .frsqrte, + }), + }; + pub const @"7450" = Cpu{ + .name = "7450", + .llvm_name = "7450", + .features = featureSet(&[_]Feature{ + .altivec, + .fres, + .frsqrte, + }), + }; + pub const @"750" = Cpu{ + .name = "750", + .llvm_name = "750", + .features = featureSet(&[_]Feature{ + .fres, + .frsqrte, + }), + }; + pub const @"970" = Cpu{ + .name = "970", + .llvm_name = "970", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .fres, + .frsqrte, + .fsqrt, + .mfocrf, + .stfiwx, + }), + }; + pub const a2 = Cpu{ + .name = "a2", + .llvm_name = "a2", + .features = featureSet(&[_]Feature{ + .@"64bit", + .booke, + .cmpb, + .fcpsgn, + .fpcvt, + .fprnd, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .icbt, + .isel, + .ldbrx, + .lfiwax, + .mfocrf, + .recipprec, + .slow_popcntd, + .stfiwx, + }), + }; + pub const a2q = Cpu{ + .name = "a2q", + .llvm_name = "a2q", + .features = featureSet(&[_]Feature{ + .@"64bit", + .booke, + .cmpb, + .fcpsgn, + .fpcvt, + .fprnd, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .icbt, + .isel, + .ldbrx, + .lfiwax, + .mfocrf, + .qpx, + .recipprec, + .slow_popcntd, + .stfiwx, + }), + }; + pub const e500 = Cpu{ + .name = "e500", + .llvm_name = "e500", + .features = featureSet(&[_]Feature{ + .booke, + .icbt, + .isel, + }), + }; + pub const e500mc = Cpu{ + .name = "e500mc", + .llvm_name = "e500mc", + .features = featureSet(&[_]Feature{ + .booke, + .icbt, + .isel, + .stfiwx, + }), + }; + pub const e5500 = Cpu{ + .name = "e5500", + .llvm_name = "e5500", + .features = featureSet(&[_]Feature{ + .@"64bit", + .booke, + .icbt, + .isel, + .mfocrf, + .stfiwx, + }), + }; + pub const g3 = Cpu{ + .name = "g3", + .llvm_name = "g3", + .features = featureSet(&[_]Feature{ + .fres, + .frsqrte, + }), + }; + pub const g4 = Cpu{ + .name = "g4", + .llvm_name = "g4", + .features = featureSet(&[_]Feature{ + .altivec, + .fres, + .frsqrte, + }), + }; + pub const @"g4+" = Cpu{ + .name = "g4+", + .llvm_name = "g4+", + .features = featureSet(&[_]Feature{ + .altivec, + .fres, + .frsqrte, + }), + }; + pub const g5 = Cpu{ + .name = "g5", + .llvm_name = "g5", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .fres, + .frsqrte, + .fsqrt, + .mfocrf, + .stfiwx, + }), + }; + pub const generic = Cpu{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{ + .hard_float, + }), + }; + pub const ppc = Cpu{ + .name = "ppc", + .llvm_name = "ppc", + .features = featureSet(&[_]Feature{ + .hard_float, + }), + }; + pub const ppc32 = Cpu{ + .name = "ppc32", + .llvm_name = "ppc32", + .features = featureSet(&[_]Feature{ + .hard_float, + }), + }; + pub const ppc64 = Cpu{ + .name = "ppc64", + .llvm_name = "ppc64", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .fres, + .frsqrte, + .fsqrt, + .mfocrf, + .stfiwx, + }), + }; + pub const ppc64le = Cpu{ + .name = "ppc64le", + .llvm_name = "ppc64le", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .bpermd, + .cmpb, + .crypto, + .direct_move, + .extdiv, + .fcpsgn, + .fpcvt, + .fprnd, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .htm, + .icbt, + .isel, + .ldbrx, + .lfiwax, + .mfocrf, + .partword_atomics, + .popcntd, + .power8_altivec, + .power8_vector, + .recipprec, + .stfiwx, + .two_const_nr, + .vsx, + }), + }; + pub const pwr3 = Cpu{ + .name = "pwr3", + .llvm_name = "pwr3", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .fres, + .frsqrte, + .mfocrf, + .stfiwx, + }), + }; + pub const pwr4 = Cpu{ + .name = "pwr4", + .llvm_name = "pwr4", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .fres, + .frsqrte, + .fsqrt, + .mfocrf, + .stfiwx, + }), + }; + pub const pwr5 = Cpu{ + .name = "pwr5", + .llvm_name = "pwr5", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .mfocrf, + .stfiwx, + }), + }; + pub const pwr5x = Cpu{ + .name = "pwr5x", + .llvm_name = "pwr5x", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .fprnd, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .mfocrf, + .stfiwx, + }), + }; + pub const pwr6 = Cpu{ + .name = "pwr6", + .llvm_name = "pwr6", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .cmpb, + .fcpsgn, + .fprnd, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .lfiwax, + .mfocrf, + .recipprec, + .stfiwx, + }), + }; + pub const pwr6x = Cpu{ + .name = "pwr6x", + .llvm_name = "pwr6x", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .cmpb, + .fcpsgn, + .fprnd, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .lfiwax, + .mfocrf, + .recipprec, + .stfiwx, + }), + }; + pub const pwr7 = Cpu{ + .name = "pwr7", + .llvm_name = "pwr7", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .bpermd, + .cmpb, + .extdiv, + .fcpsgn, + .fpcvt, + .fprnd, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .isel, + .ldbrx, + .lfiwax, + .mfocrf, + .popcntd, + .recipprec, + .stfiwx, + .two_const_nr, + .vsx, + }), + }; + pub const pwr8 = Cpu{ + .name = "pwr8", + .llvm_name = "pwr8", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .bpermd, + .cmpb, + .crypto, + .direct_move, + .extdiv, + .fcpsgn, + .fpcvt, + .fprnd, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .htm, + .icbt, + .isel, + .ldbrx, + .lfiwax, + .mfocrf, + .partword_atomics, + .popcntd, + .power8_altivec, + .power8_vector, + .recipprec, + .stfiwx, + .two_const_nr, + .vsx, + }), + }; + pub const pwr9 = Cpu{ + .name = "pwr9", + .llvm_name = "pwr9", + .features = featureSet(&[_]Feature{ + .@"64bit", + .altivec, + .bpermd, + .cmpb, + .crypto, + .direct_move, + .extdiv, + .fcpsgn, + .fpcvt, + .fprnd, + .fre, + .fres, + .frsqrte, + .frsqrtes, + .fsqrt, + .htm, + .icbt, + .isa_v30_instructions, + .isel, + .ldbrx, + .lfiwax, + .mfocrf, + .partword_atomics, + .popcntd, + .power8_altivec, + .power8_vector, + .power9_altivec, + .power9_vector, + .ppc_postra_sched, + .ppc_prera_sched, + .recipprec, + .stfiwx, + .two_const_nr, + .vectors_use_two_units, + .vsx, + }), + }; +}; + +/// All powerpc CPUs, sorted alphabetically by name. +/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 +/// compiler has inefficient memory and CPU usage, affecting build times. +pub const all_cpus = &[_]*const Cpu{ + &cpu.@"440", + &cpu.@"450", + &cpu.@"601", + &cpu.@"602", + &cpu.@"603", + &cpu.@"603e", + &cpu.@"603ev", + &cpu.@"604", + &cpu.@"604e", + &cpu.@"620", + &cpu.@"7400", + &cpu.@"7450", + &cpu.@"750", + &cpu.@"970", + &cpu.a2, + &cpu.a2q, + &cpu.e500, + &cpu.e500mc, + &cpu.e5500, + &cpu.g3, + &cpu.g4, + &cpu.@"g4+", + &cpu.g5, + &cpu.generic, + &cpu.ppc, + &cpu.ppc32, + &cpu.ppc64, + &cpu.ppc64le, + &cpu.pwr3, + &cpu.pwr4, + &cpu.pwr5, + &cpu.pwr5x, + &cpu.pwr6, + &cpu.pwr6x, + &cpu.pwr7, + &cpu.pwr8, + &cpu.pwr9, +}; diff --git a/lib/std/target/riscv.zig b/lib/std/target/riscv.zig new file mode 100644 index 0000000000..315329306e --- /dev/null +++ b/lib/std/target/riscv.zig @@ -0,0 +1,122 @@ +const std = @import("../std.zig"); +const Cpu = std.Target.Cpu; + +pub const Feature = enum { + @"64bit", + a, + c, + d, + e, + f, + m, + relax, +}; + +pub usingnamespace Cpu.Feature.feature_set_fns(Feature); + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); + var result: [len]Cpu.Feature = undefined; + result[@enumToInt(Feature.@"64bit")] = .{ + .llvm_name = "64bit", + .description = "Implements RV64", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.a)] = .{ + .llvm_name = "a", + .description = "'A' (Atomic Instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.c)] = .{ + .llvm_name = "c", + .description = "'C' (Compressed Instructions)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.d)] = .{ + .llvm_name = "d", + .description = "'D' (Double-Precision Floating-Point)", + .dependencies = featureSet(&[_]Feature{ + .f, + }), + }; + result[@enumToInt(Feature.e)] = .{ + .llvm_name = "e", + .description = "Implements RV32E (provides 16 rather than 32 GPRs)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.f)] = .{ + .llvm_name = "f", + .description = "'F' (Single-Precision Floating-Point)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.m)] = .{ + .llvm_name = "m", + .description = "'M' (Integer Multiplication and Division)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.relax)] = .{ + .llvm_name = "relax", + .description = "Enable Linker relaxation.", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (result) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const baseline_rv32 = Cpu{ + .name = "baseline_rv32", + .llvm_name = "generic-rv32", + .features = featureSet(&[_]Feature{ + .a, + .c, + .d, + .f, + .m, + .relax, + }), + }; + + pub const baseline_rv64 = Cpu{ + .name = "baseline_rv64", + .llvm_name = "generic-rv64", + .features = featureSet(&[_]Feature{ + .@"64bit", + .a, + .c, + .d, + .f, + .m, + .relax, + }), + }; + + pub const generic_rv32 = Cpu{ + .name = "generic_rv32", + .llvm_name = "generic-rv32", + .features = featureSet(&[_]Feature{}), + }; + + pub const generic_rv64 = Cpu{ + .name = "generic_rv64", + .llvm_name = "generic-rv64", + .features = featureSet(&[_]Feature{ + .@"64bit", + }), + }; +}; + +/// All riscv CPUs, sorted alphabetically by name. +/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 +/// compiler has inefficient memory and CPU usage, affecting build times. +pub const all_cpus = &[_]*const Cpu{ + &cpu.baseline_rv32, + &cpu.baseline_rv64, + &cpu.generic_rv32, + &cpu.generic_rv64, +}; diff --git a/lib/std/target/sparc.zig b/lib/std/target/sparc.zig new file mode 100644 index 0000000000..923cc0732c --- /dev/null +++ b/lib/std/target/sparc.zig @@ -0,0 +1,495 @@ +const std = @import("../std.zig"); +const Cpu = std.Target.Cpu; + +pub const Feature = enum { + deprecated_v8, + detectroundchange, + fixallfdivsqrt, + hard_quad_float, + hasleoncasa, + hasumacsmac, + insertnopload, + leon, + leoncyclecounter, + leonpwrpsr, + no_fmuls, + no_fsmuld, + popc, + soft_float, + soft_mul_div, + v9, + vis, + vis2, + vis3, +}; + +pub usingnamespace Cpu.Feature.feature_set_fns(Feature); + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); + var result: [len]Cpu.Feature = undefined; + result[@enumToInt(Feature.deprecated_v8)] = .{ + .llvm_name = "deprecated-v8", + .description = "Enable deprecated V8 instructions in V9 mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.detectroundchange)] = .{ + .llvm_name = "detectroundchange", + .description = "LEON3 erratum detection: Detects any rounding mode change request: use only the round-to-nearest rounding mode", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fixallfdivsqrt)] = .{ + .llvm_name = "fixallfdivsqrt", + .description = "LEON erratum fix: Fix FDIVS/FDIVD/FSQRTS/FSQRTD instructions with NOPs and floating-point store", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.hard_quad_float)] = .{ + .llvm_name = "hard-quad-float", + .description = "Enable quad-word floating point instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.hasleoncasa)] = .{ + .llvm_name = "hasleoncasa", + .description = "Enable CASA instruction for LEON3 and LEON4 processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.hasumacsmac)] = .{ + .llvm_name = "hasumacsmac", + .description = "Enable UMAC and SMAC for LEON3 and LEON4 processors", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.insertnopload)] = .{ + .llvm_name = "insertnopload", + .description = "LEON3 erratum fix: Insert a NOP instruction after every single-cycle load instruction when the next instruction is another load/store instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.leon)] = .{ + .llvm_name = "leon", + .description = "Enable LEON extensions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.leoncyclecounter)] = .{ + .llvm_name = "leoncyclecounter", + .description = "Use the Leon cycle counter register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.leonpwrpsr)] = .{ + .llvm_name = "leonpwrpsr", + .description = "Enable the PWRPSR instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.no_fmuls)] = .{ + .llvm_name = "no-fmuls", + .description = "Disable the fmuls instruction.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.no_fsmuld)] = .{ + .llvm_name = "no-fsmuld", + .description = "Disable the fsmuld instruction.", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.popc)] = .{ + .llvm_name = "popc", + .description = "Use the popc (population count) instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.soft_float)] = .{ + .llvm_name = "soft-float", + .description = "Use software emulation for floating point", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.soft_mul_div)] = .{ + .llvm_name = "soft-mul-div", + .description = "Use software emulation for integer multiply and divide", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.v9)] = .{ + .llvm_name = "v9", + .description = "Enable SPARC-V9 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vis)] = .{ + .llvm_name = "vis", + .description = "Enable UltraSPARC Visual Instruction Set extensions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vis2)] = .{ + .llvm_name = "vis2", + .description = "Enable Visual Instruction Set extensions II", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vis3)] = .{ + .llvm_name = "vis3", + .description = "Enable Visual Instruction Set extensions III", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (result) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const at697e = Cpu{ + .name = "at697e", + .llvm_name = "at697e", + .features = featureSet(&[_]Feature{ + .insertnopload, + .leon, + }), + }; + pub const at697f = Cpu{ + .name = "at697f", + .llvm_name = "at697f", + .features = featureSet(&[_]Feature{ + .insertnopload, + .leon, + }), + }; + pub const f934 = Cpu{ + .name = "f934", + .llvm_name = "f934", + .features = featureSet(&[_]Feature{}), + }; + pub const generic = Cpu{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{}), + }; + pub const gr712rc = Cpu{ + .name = "gr712rc", + .llvm_name = "gr712rc", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const gr740 = Cpu{ + .name = "gr740", + .llvm_name = "gr740", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .hasumacsmac, + .leon, + .leoncyclecounter, + .leonpwrpsr, + }), + }; + pub const hypersparc = Cpu{ + .name = "hypersparc", + .llvm_name = "hypersparc", + .features = featureSet(&[_]Feature{}), + }; + pub const leon2 = Cpu{ + .name = "leon2", + .llvm_name = "leon2", + .features = featureSet(&[_]Feature{ + .leon, + }), + }; + pub const leon3 = Cpu{ + .name = "leon3", + .llvm_name = "leon3", + .features = featureSet(&[_]Feature{ + .hasumacsmac, + .leon, + }), + }; + pub const leon4 = Cpu{ + .name = "leon4", + .llvm_name = "leon4", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .hasumacsmac, + .leon, + }), + }; + pub const ma2080 = Cpu{ + .name = "ma2080", + .llvm_name = "ma2080", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2085 = Cpu{ + .name = "ma2085", + .llvm_name = "ma2085", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2100 = Cpu{ + .name = "ma2100", + .llvm_name = "ma2100", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2150 = Cpu{ + .name = "ma2150", + .llvm_name = "ma2150", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2155 = Cpu{ + .name = "ma2155", + .llvm_name = "ma2155", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2450 = Cpu{ + .name = "ma2450", + .llvm_name = "ma2450", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2455 = Cpu{ + .name = "ma2455", + .llvm_name = "ma2455", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2480 = Cpu{ + .name = "ma2480", + .llvm_name = "ma2480", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2485 = Cpu{ + .name = "ma2485", + .llvm_name = "ma2485", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2x5x = Cpu{ + .name = "ma2x5x", + .llvm_name = "ma2x5x", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const ma2x8x = Cpu{ + .name = "ma2x8x", + .llvm_name = "ma2x8x", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const myriad2 = Cpu{ + .name = "myriad2", + .llvm_name = "myriad2", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const myriad2_1 = Cpu{ + .name = "myriad2_1", + .llvm_name = "myriad2.1", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const myriad2_2 = Cpu{ + .name = "myriad2_2", + .llvm_name = "myriad2.2", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const myriad2_3 = Cpu{ + .name = "myriad2_3", + .llvm_name = "myriad2.3", + .features = featureSet(&[_]Feature{ + .hasleoncasa, + .leon, + }), + }; + pub const niagara = Cpu{ + .name = "niagara", + .llvm_name = "niagara", + .features = featureSet(&[_]Feature{ + .deprecated_v8, + .v9, + .vis, + .vis2, + }), + }; + pub const niagara2 = Cpu{ + .name = "niagara2", + .llvm_name = "niagara2", + .features = featureSet(&[_]Feature{ + .deprecated_v8, + .popc, + .v9, + .vis, + .vis2, + }), + }; + pub const niagara3 = Cpu{ + .name = "niagara3", + .llvm_name = "niagara3", + .features = featureSet(&[_]Feature{ + .deprecated_v8, + .popc, + .v9, + .vis, + .vis2, + }), + }; + pub const niagara4 = Cpu{ + .name = "niagara4", + .llvm_name = "niagara4", + .features = featureSet(&[_]Feature{ + .deprecated_v8, + .popc, + .v9, + .vis, + .vis2, + .vis3, + }), + }; + pub const sparclet = Cpu{ + .name = "sparclet", + .llvm_name = "sparclet", + .features = featureSet(&[_]Feature{}), + }; + pub const sparclite = Cpu{ + .name = "sparclite", + .llvm_name = "sparclite", + .features = featureSet(&[_]Feature{}), + }; + pub const sparclite86x = Cpu{ + .name = "sparclite86x", + .llvm_name = "sparclite86x", + .features = featureSet(&[_]Feature{}), + }; + pub const supersparc = Cpu{ + .name = "supersparc", + .llvm_name = "supersparc", + .features = featureSet(&[_]Feature{}), + }; + pub const tsc701 = Cpu{ + .name = "tsc701", + .llvm_name = "tsc701", + .features = featureSet(&[_]Feature{}), + }; + pub const ultrasparc = Cpu{ + .name = "ultrasparc", + .llvm_name = "ultrasparc", + .features = featureSet(&[_]Feature{ + .deprecated_v8, + .v9, + .vis, + }), + }; + pub const ultrasparc3 = Cpu{ + .name = "ultrasparc3", + .llvm_name = "ultrasparc3", + .features = featureSet(&[_]Feature{ + .deprecated_v8, + .v9, + .vis, + .vis2, + }), + }; + pub const ut699 = Cpu{ + .name = "ut699", + .llvm_name = "ut699", + .features = featureSet(&[_]Feature{ + .fixallfdivsqrt, + .insertnopload, + .leon, + .no_fmuls, + .no_fsmuld, + }), + }; + pub const v7 = Cpu{ + .name = "v7", + .llvm_name = "v7", + .features = featureSet(&[_]Feature{ + .no_fsmuld, + .soft_mul_div, + }), + }; + pub const v8 = Cpu{ + .name = "v8", + .llvm_name = "v8", + .features = featureSet(&[_]Feature{}), + }; + pub const v9 = Cpu{ + .name = "v9", + .llvm_name = "v9", + .features = featureSet(&[_]Feature{ + .v9, + }), + }; +}; + +/// All sparc CPUs, sorted alphabetically by name. +/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 +/// compiler has inefficient memory and CPU usage, affecting build times. +pub const all_cpus = &[_]*const Cpu{ + &cpu.at697e, + &cpu.at697f, + &cpu.f934, + &cpu.generic, + &cpu.gr712rc, + &cpu.gr740, + &cpu.hypersparc, + &cpu.leon2, + &cpu.leon3, + &cpu.leon4, + &cpu.ma2080, + &cpu.ma2085, + &cpu.ma2100, + &cpu.ma2150, + &cpu.ma2155, + &cpu.ma2450, + &cpu.ma2455, + &cpu.ma2480, + &cpu.ma2485, + &cpu.ma2x5x, + &cpu.ma2x8x, + &cpu.myriad2, + &cpu.myriad2_1, + &cpu.myriad2_2, + &cpu.myriad2_3, + &cpu.niagara, + &cpu.niagara2, + &cpu.niagara3, + &cpu.niagara4, + &cpu.sparclet, + &cpu.sparclite, + &cpu.sparclite86x, + &cpu.supersparc, + &cpu.tsc701, + &cpu.ultrasparc, + &cpu.ultrasparc3, + &cpu.ut699, + &cpu.v7, + &cpu.v8, + &cpu.v9, +}; diff --git a/lib/std/target/systemz.zig b/lib/std/target/systemz.zig new file mode 100644 index 0000000000..c924af6e70 --- /dev/null +++ b/lib/std/target/systemz.zig @@ -0,0 +1,510 @@ +const std = @import("../std.zig"); +const Cpu = std.Target.Cpu; + +pub const Feature = enum { + deflate_conversion, + dfp_packed_conversion, + dfp_zoned_conversion, + distinct_ops, + enhanced_dat_2, + enhanced_sort, + execution_hint, + fast_serialization, + fp_extension, + guarded_storage, + high_word, + insert_reference_bits_multiple, + interlocked_access1, + load_and_trap, + load_and_zero_rightmost_byte, + load_store_on_cond, + load_store_on_cond_2, + message_security_assist_extension3, + message_security_assist_extension4, + message_security_assist_extension5, + message_security_assist_extension7, + message_security_assist_extension8, + message_security_assist_extension9, + miscellaneous_extensions, + miscellaneous_extensions_2, + miscellaneous_extensions_3, + population_count, + processor_assist, + reset_reference_bits_multiple, + transactional_execution, + vector, + vector_enhancements_1, + vector_enhancements_2, + vector_packed_decimal, + vector_packed_decimal_enhancement, +}; + +pub usingnamespace Cpu.Feature.feature_set_fns(Feature); + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); + var result: [len]Cpu.Feature = undefined; + result[@enumToInt(Feature.deflate_conversion)] = .{ + .llvm_name = "deflate-conversion", + .description = "Assume that the deflate-conversion facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dfp_packed_conversion)] = .{ + .llvm_name = "dfp-packed-conversion", + .description = "Assume that the DFP packed-conversion facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.dfp_zoned_conversion)] = .{ + .llvm_name = "dfp-zoned-conversion", + .description = "Assume that the DFP zoned-conversion facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.distinct_ops)] = .{ + .llvm_name = "distinct-ops", + .description = "Assume that the distinct-operands facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.enhanced_dat_2)] = .{ + .llvm_name = "enhanced-dat-2", + .description = "Assume that the enhanced-DAT facility 2 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.enhanced_sort)] = .{ + .llvm_name = "enhanced-sort", + .description = "Assume that the enhanced-sort facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.execution_hint)] = .{ + .llvm_name = "execution-hint", + .description = "Assume that the execution-hint facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fast_serialization)] = .{ + .llvm_name = "fast-serialization", + .description = "Assume that the fast-serialization facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fp_extension)] = .{ + .llvm_name = "fp-extension", + .description = "Assume that the floating-point extension facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.guarded_storage)] = .{ + .llvm_name = "guarded-storage", + .description = "Assume that the guarded-storage facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.high_word)] = .{ + .llvm_name = "high-word", + .description = "Assume that the high-word facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.insert_reference_bits_multiple)] = .{ + .llvm_name = "insert-reference-bits-multiple", + .description = "Assume that the insert-reference-bits-multiple facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.interlocked_access1)] = .{ + .llvm_name = "interlocked-access1", + .description = "Assume that interlocked-access facility 1 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.load_and_trap)] = .{ + .llvm_name = "load-and-trap", + .description = "Assume that the load-and-trap facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.load_and_zero_rightmost_byte)] = .{ + .llvm_name = "load-and-zero-rightmost-byte", + .description = "Assume that the load-and-zero-rightmost-byte facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.load_store_on_cond)] = .{ + .llvm_name = "load-store-on-cond", + .description = "Assume that the load/store-on-condition facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.load_store_on_cond_2)] = .{ + .llvm_name = "load-store-on-cond-2", + .description = "Assume that the load/store-on-condition facility 2 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.message_security_assist_extension3)] = .{ + .llvm_name = "message-security-assist-extension3", + .description = "Assume that the message-security-assist extension facility 3 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.message_security_assist_extension4)] = .{ + .llvm_name = "message-security-assist-extension4", + .description = "Assume that the message-security-assist extension facility 4 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.message_security_assist_extension5)] = .{ + .llvm_name = "message-security-assist-extension5", + .description = "Assume that the message-security-assist extension facility 5 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.message_security_assist_extension7)] = .{ + .llvm_name = "message-security-assist-extension7", + .description = "Assume that the message-security-assist extension facility 7 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.message_security_assist_extension8)] = .{ + .llvm_name = "message-security-assist-extension8", + .description = "Assume that the message-security-assist extension facility 8 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.message_security_assist_extension9)] = .{ + .llvm_name = "message-security-assist-extension9", + .description = "Assume that the message-security-assist extension facility 9 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.miscellaneous_extensions)] = .{ + .llvm_name = "miscellaneous-extensions", + .description = "Assume that the miscellaneous-extensions facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.miscellaneous_extensions_2)] = .{ + .llvm_name = "miscellaneous-extensions-2", + .description = "Assume that the miscellaneous-extensions facility 2 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.miscellaneous_extensions_3)] = .{ + .llvm_name = "miscellaneous-extensions-3", + .description = "Assume that the miscellaneous-extensions facility 3 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.population_count)] = .{ + .llvm_name = "population-count", + .description = "Assume that the population-count facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.processor_assist)] = .{ + .llvm_name = "processor-assist", + .description = "Assume that the processor-assist facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.reset_reference_bits_multiple)] = .{ + .llvm_name = "reset-reference-bits-multiple", + .description = "Assume that the reset-reference-bits-multiple facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.transactional_execution)] = .{ + .llvm_name = "transactional-execution", + .description = "Assume that the transactional-execution facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vector)] = .{ + .llvm_name = "vector", + .description = "Assume that the vectory facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vector_enhancements_1)] = .{ + .llvm_name = "vector-enhancements-1", + .description = "Assume that the vector enhancements facility 1 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vector_enhancements_2)] = .{ + .llvm_name = "vector-enhancements-2", + .description = "Assume that the vector enhancements facility 2 is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vector_packed_decimal)] = .{ + .llvm_name = "vector-packed-decimal", + .description = "Assume that the vector packed decimal facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vector_packed_decimal_enhancement)] = .{ + .llvm_name = "vector-packed-decimal-enhancement", + .description = "Assume that the vector packed decimal enhancement facility is installed", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (result) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const arch10 = Cpu{ + .name = "arch10", + .llvm_name = "arch10", + .features = featureSet(&[_]Feature{ + .dfp_zoned_conversion, + .distinct_ops, + .enhanced_dat_2, + .execution_hint, + .fast_serialization, + .fp_extension, + .high_word, + .interlocked_access1, + .load_and_trap, + .load_store_on_cond, + .message_security_assist_extension3, + .message_security_assist_extension4, + .miscellaneous_extensions, + .population_count, + .processor_assist, + .reset_reference_bits_multiple, + .transactional_execution, + }), + }; + pub const arch11 = Cpu{ + .name = "arch11", + .llvm_name = "arch11", + .features = featureSet(&[_]Feature{ + .dfp_packed_conversion, + .dfp_zoned_conversion, + .distinct_ops, + .enhanced_dat_2, + .execution_hint, + .fast_serialization, + .fp_extension, + .high_word, + .interlocked_access1, + .load_and_trap, + .load_and_zero_rightmost_byte, + .load_store_on_cond, + .load_store_on_cond_2, + .message_security_assist_extension3, + .message_security_assist_extension4, + .message_security_assist_extension5, + .miscellaneous_extensions, + .population_count, + .processor_assist, + .reset_reference_bits_multiple, + .transactional_execution, + .vector, + }), + }; + pub const arch12 = Cpu{ + .name = "arch12", + .llvm_name = "arch12", + .features = featureSet(&[_]Feature{ + .dfp_packed_conversion, + .dfp_zoned_conversion, + .distinct_ops, + .enhanced_dat_2, + .execution_hint, + .fast_serialization, + .fp_extension, + .guarded_storage, + .high_word, + .insert_reference_bits_multiple, + .interlocked_access1, + .load_and_trap, + .load_and_zero_rightmost_byte, + .load_store_on_cond, + .load_store_on_cond_2, + .message_security_assist_extension3, + .message_security_assist_extension4, + .message_security_assist_extension5, + .message_security_assist_extension7, + .message_security_assist_extension8, + .miscellaneous_extensions, + .miscellaneous_extensions_2, + .population_count, + .processor_assist, + .reset_reference_bits_multiple, + .transactional_execution, + .vector, + .vector_enhancements_1, + .vector_packed_decimal, + }), + }; + pub const arch13 = Cpu{ + .name = "arch13", + .llvm_name = "arch13", + .features = featureSet(&[_]Feature{ + .deflate_conversion, + .dfp_packed_conversion, + .dfp_zoned_conversion, + .distinct_ops, + .enhanced_dat_2, + .enhanced_sort, + .execution_hint, + .fast_serialization, + .fp_extension, + .guarded_storage, + .high_word, + .insert_reference_bits_multiple, + .interlocked_access1, + .load_and_trap, + .load_and_zero_rightmost_byte, + .load_store_on_cond, + .load_store_on_cond_2, + .message_security_assist_extension3, + .message_security_assist_extension4, + .message_security_assist_extension5, + .message_security_assist_extension7, + .message_security_assist_extension8, + .message_security_assist_extension9, + .miscellaneous_extensions, + .miscellaneous_extensions_2, + .miscellaneous_extensions_3, + .population_count, + .processor_assist, + .reset_reference_bits_multiple, + .transactional_execution, + .vector, + .vector_enhancements_1, + .vector_enhancements_2, + .vector_packed_decimal, + .vector_packed_decimal_enhancement, + }), + }; + pub const arch8 = Cpu{ + .name = "arch8", + .llvm_name = "arch8", + .features = featureSet(&[_]Feature{}), + }; + pub const arch9 = Cpu{ + .name = "arch9", + .llvm_name = "arch9", + .features = featureSet(&[_]Feature{ + .distinct_ops, + .fast_serialization, + .fp_extension, + .high_word, + .interlocked_access1, + .load_store_on_cond, + .message_security_assist_extension3, + .message_security_assist_extension4, + .population_count, + .reset_reference_bits_multiple, + }), + }; + pub const generic = Cpu{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{}), + }; + pub const z10 = Cpu{ + .name = "z10", + .llvm_name = "z10", + .features = featureSet(&[_]Feature{}), + }; + pub const z13 = Cpu{ + .name = "z13", + .llvm_name = "z13", + .features = featureSet(&[_]Feature{ + .dfp_packed_conversion, + .dfp_zoned_conversion, + .distinct_ops, + .enhanced_dat_2, + .execution_hint, + .fast_serialization, + .fp_extension, + .high_word, + .interlocked_access1, + .load_and_trap, + .load_and_zero_rightmost_byte, + .load_store_on_cond, + .load_store_on_cond_2, + .message_security_assist_extension3, + .message_security_assist_extension4, + .message_security_assist_extension5, + .miscellaneous_extensions, + .population_count, + .processor_assist, + .reset_reference_bits_multiple, + .transactional_execution, + .vector, + }), + }; + pub const z14 = Cpu{ + .name = "z14", + .llvm_name = "z14", + .features = featureSet(&[_]Feature{ + .dfp_packed_conversion, + .dfp_zoned_conversion, + .distinct_ops, + .enhanced_dat_2, + .execution_hint, + .fast_serialization, + .fp_extension, + .guarded_storage, + .high_word, + .insert_reference_bits_multiple, + .interlocked_access1, + .load_and_trap, + .load_and_zero_rightmost_byte, + .load_store_on_cond, + .load_store_on_cond_2, + .message_security_assist_extension3, + .message_security_assist_extension4, + .message_security_assist_extension5, + .message_security_assist_extension7, + .message_security_assist_extension8, + .miscellaneous_extensions, + .miscellaneous_extensions_2, + .population_count, + .processor_assist, + .reset_reference_bits_multiple, + .transactional_execution, + .vector, + .vector_enhancements_1, + .vector_packed_decimal, + }), + }; + pub const z196 = Cpu{ + .name = "z196", + .llvm_name = "z196", + .features = featureSet(&[_]Feature{ + .distinct_ops, + .fast_serialization, + .fp_extension, + .high_word, + .interlocked_access1, + .load_store_on_cond, + .message_security_assist_extension3, + .message_security_assist_extension4, + .population_count, + .reset_reference_bits_multiple, + }), + }; + pub const zEC12 = Cpu{ + .name = "zEC12", + .llvm_name = "zEC12", + .features = featureSet(&[_]Feature{ + .dfp_zoned_conversion, + .distinct_ops, + .enhanced_dat_2, + .execution_hint, + .fast_serialization, + .fp_extension, + .high_word, + .interlocked_access1, + .load_and_trap, + .load_store_on_cond, + .message_security_assist_extension3, + .message_security_assist_extension4, + .miscellaneous_extensions, + .population_count, + .processor_assist, + .reset_reference_bits_multiple, + .transactional_execution, + }), + }; +}; + +/// All systemz CPUs, sorted alphabetically by name. +/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 +/// compiler has inefficient memory and CPU usage, affecting build times. +pub const all_cpus = &[_]*const Cpu{ + &cpu.arch10, + &cpu.arch11, + &cpu.arch12, + &cpu.arch13, + &cpu.arch8, + &cpu.arch9, + &cpu.generic, + &cpu.z10, + &cpu.z13, + &cpu.z14, + &cpu.z196, + &cpu.zEC12, +}; diff --git a/lib/std/target/wasm.zig b/lib/std/target/wasm.zig new file mode 100644 index 0000000000..6d79bbb282 --- /dev/null +++ b/lib/std/target/wasm.zig @@ -0,0 +1,114 @@ +const std = @import("../std.zig"); +const Cpu = std.Target.Cpu; + +pub const Feature = enum { + atomics, + bulk_memory, + exception_handling, + multivalue, + mutable_globals, + nontrapping_fptoint, + sign_ext, + simd128, + tail_call, + unimplemented_simd128, +}; + +pub usingnamespace Cpu.Feature.feature_set_fns(Feature); + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); + var result: [len]Cpu.Feature = undefined; + result[@enumToInt(Feature.atomics)] = .{ + .llvm_name = "atomics", + .description = "Enable Atomics", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.bulk_memory)] = .{ + .llvm_name = "bulk-memory", + .description = "Enable bulk memory operations", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.exception_handling)] = .{ + .llvm_name = "exception-handling", + .description = "Enable Wasm exception handling", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.multivalue)] = .{ + .llvm_name = "multivalue", + .description = "Enable multivalue blocks, instructions, and functions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mutable_globals)] = .{ + .llvm_name = "mutable-globals", + .description = "Enable mutable globals", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.nontrapping_fptoint)] = .{ + .llvm_name = "nontrapping-fptoint", + .description = "Enable non-trapping float-to-int conversion operators", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sign_ext)] = .{ + .llvm_name = "sign-ext", + .description = "Enable sign extension operators", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.simd128)] = .{ + .llvm_name = "simd128", + .description = "Enable 128-bit SIMD", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.tail_call)] = .{ + .llvm_name = "tail-call", + .description = "Enable tail call instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.unimplemented_simd128)] = .{ + .llvm_name = "unimplemented-simd128", + .description = "Enable 128-bit SIMD not yet implemented in engines", + .dependencies = featureSet(&[_]Feature{ + .simd128, + }), + }; + const ti = @typeInfo(Feature); + for (result) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const bleeding_edge = Cpu{ + .name = "bleeding_edge", + .llvm_name = "bleeding-edge", + .features = featureSet(&[_]Feature{ + .atomics, + .mutable_globals, + .nontrapping_fptoint, + .sign_ext, + .simd128, + }), + }; + pub const generic = Cpu{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{}), + }; + pub const mvp = Cpu{ + .name = "mvp", + .llvm_name = "mvp", + .features = featureSet(&[_]Feature{}), + }; +}; + +/// All wasm CPUs, sorted alphabetically by name. +/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 +/// compiler has inefficient memory and CPU usage, affecting build times. +pub const all_cpus = &[_]*const Cpu{ + &cpu.bleeding_edge, + &cpu.generic, + &cpu.mvp, +}; diff --git a/lib/std/target/x86.zig b/lib/std/target/x86.zig new file mode 100644 index 0000000000..3c2e306e79 --- /dev/null +++ b/lib/std/target/x86.zig @@ -0,0 +1,2859 @@ +const std = @import("../std.zig"); +const Cpu = std.Target.Cpu; + +pub const Feature = enum { + @"3dnow", + @"3dnowa", + @"64bit", + adx, + aes, + avx, + avx2, + avx512bf16, + avx512bitalg, + avx512bw, + avx512cd, + avx512dq, + avx512er, + avx512f, + avx512ifma, + avx512pf, + avx512vbmi, + avx512vbmi2, + avx512vl, + avx512vnni, + avx512vp2intersect, + avx512vpopcntdq, + bmi, + bmi2, + branchfusion, + cldemote, + clflushopt, + clwb, + clzero, + cmov, + cx16, + cx8, + enqcmd, + ermsb, + f16c, + false_deps_lzcnt_tzcnt, + false_deps_popcnt, + fast_11bytenop, + fast_15bytenop, + fast_bextr, + fast_gather, + fast_hops, + fast_lzcnt, + fast_partial_ymm_or_zmm_write, + fast_scalar_fsqrt, + fast_scalar_shift_masks, + fast_shld_rotate, + fast_variable_shuffle, + fast_vector_fsqrt, + fast_vector_shift_masks, + fma, + fma4, + fsgsbase, + fxsr, + gfni, + idivl_to_divb, + idivq_to_divl, + invpcid, + lea_sp, + lea_uses_ag, + lwp, + lzcnt, + macrofusion, + merge_to_threeway_branch, + mmx, + movbe, + movdir64b, + movdiri, + mpx, + mwaitx, + nopl, + pad_short_functions, + pclmul, + pconfig, + pku, + popcnt, + prefer_256_bit, + prefetchwt1, + prfchw, + ptwrite, + rdpid, + rdrnd, + rdseed, + retpoline, + retpoline_external_thunk, + retpoline_indirect_branches, + retpoline_indirect_calls, + rtm, + sahf, + sgx, + sha, + shstk, + slow_3ops_lea, + slow_incdec, + slow_lea, + slow_pmaddwd, + slow_pmulld, + slow_shld, + slow_two_mem_ops, + slow_unaligned_mem_16, + slow_unaligned_mem_32, + soft_float, + sse, + sse_unaligned_mem, + sse2, + sse3, + sse4_1, + sse4_2, + sse4a, + ssse3, + tbm, + vaes, + vpclmulqdq, + waitpkg, + wbnoinvd, + x87, + xop, + xsave, + xsavec, + xsaveopt, + xsaves, +}; + +pub usingnamespace Cpu.Feature.feature_set_fns(Feature); + +pub const all_features = blk: { + const len = @typeInfo(Feature).Enum.fields.len; + std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count); + var result: [len]Cpu.Feature = undefined; + result[@enumToInt(Feature.@"3dnow")] = .{ + .llvm_name = "3dnow", + .description = "Enable 3DNow! instructions", + .dependencies = featureSet(&[_]Feature{ + .mmx, + }), + }; + result[@enumToInt(Feature.@"3dnowa")] = .{ + .llvm_name = "3dnowa", + .description = "Enable 3DNow! Athlon instructions", + .dependencies = featureSet(&[_]Feature{ + .@"3dnow", + }), + }; + result[@enumToInt(Feature.@"64bit")] = .{ + .llvm_name = "64bit", + .description = "Support 64-bit instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.adx)] = .{ + .llvm_name = "adx", + .description = "Support ADX instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.aes)] = .{ + .llvm_name = "aes", + .description = "Enable AES instructions", + .dependencies = featureSet(&[_]Feature{ + .sse2, + }), + }; + result[@enumToInt(Feature.avx)] = .{ + .llvm_name = "avx", + .description = "Enable AVX instructions", + .dependencies = featureSet(&[_]Feature{ + .sse4_2, + }), + }; + result[@enumToInt(Feature.avx2)] = .{ + .llvm_name = "avx2", + .description = "Enable AVX2 instructions", + .dependencies = featureSet(&[_]Feature{ + .avx, + }), + }; + result[@enumToInt(Feature.avx512bf16)] = .{ + .llvm_name = "avx512bf16", + .description = "Support bfloat16 floating point", + .dependencies = featureSet(&[_]Feature{ + .avx512bw, + }), + }; + result[@enumToInt(Feature.avx512bitalg)] = .{ + .llvm_name = "avx512bitalg", + .description = "Enable AVX-512 Bit Algorithms", + .dependencies = featureSet(&[_]Feature{ + .avx512bw, + }), + }; + result[@enumToInt(Feature.avx512bw)] = .{ + .llvm_name = "avx512bw", + .description = "Enable AVX-512 Byte and Word Instructions", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@enumToInt(Feature.avx512cd)] = .{ + .llvm_name = "avx512cd", + .description = "Enable AVX-512 Conflict Detection Instructions", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@enumToInt(Feature.avx512dq)] = .{ + .llvm_name = "avx512dq", + .description = "Enable AVX-512 Doubleword and Quadword Instructions", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@enumToInt(Feature.avx512er)] = .{ + .llvm_name = "avx512er", + .description = "Enable AVX-512 Exponential and Reciprocal Instructions", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@enumToInt(Feature.avx512f)] = .{ + .llvm_name = "avx512f", + .description = "Enable AVX-512 instructions", + .dependencies = featureSet(&[_]Feature{ + .avx2, + .f16c, + .fma, + }), + }; + result[@enumToInt(Feature.avx512ifma)] = .{ + .llvm_name = "avx512ifma", + .description = "Enable AVX-512 Integer Fused Multiple-Add", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@enumToInt(Feature.avx512pf)] = .{ + .llvm_name = "avx512pf", + .description = "Enable AVX-512 PreFetch Instructions", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@enumToInt(Feature.avx512vbmi)] = .{ + .llvm_name = "avx512vbmi", + .description = "Enable AVX-512 Vector Byte Manipulation Instructions", + .dependencies = featureSet(&[_]Feature{ + .avx512bw, + }), + }; + result[@enumToInt(Feature.avx512vbmi2)] = .{ + .llvm_name = "avx512vbmi2", + .description = "Enable AVX-512 further Vector Byte Manipulation Instructions", + .dependencies = featureSet(&[_]Feature{ + .avx512bw, + }), + }; + result[@enumToInt(Feature.avx512vl)] = .{ + .llvm_name = "avx512vl", + .description = "Enable AVX-512 Vector Length eXtensions", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@enumToInt(Feature.avx512vnni)] = .{ + .llvm_name = "avx512vnni", + .description = "Enable AVX-512 Vector Neural Network Instructions", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@enumToInt(Feature.avx512vp2intersect)] = .{ + .llvm_name = "avx512vp2intersect", + .description = "Enable AVX-512 vp2intersect", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@enumToInt(Feature.avx512vpopcntdq)] = .{ + .llvm_name = "avx512vpopcntdq", + .description = "Enable AVX-512 Population Count Instructions", + .dependencies = featureSet(&[_]Feature{ + .avx512f, + }), + }; + result[@enumToInt(Feature.bmi)] = .{ + .llvm_name = "bmi", + .description = "Support BMI instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.bmi2)] = .{ + .llvm_name = "bmi2", + .description = "Support BMI2 instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.branchfusion)] = .{ + .llvm_name = "branchfusion", + .description = "CMP/TEST can be fused with conditional branches", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.cldemote)] = .{ + .llvm_name = "cldemote", + .description = "Enable Cache Demote", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.clflushopt)] = .{ + .llvm_name = "clflushopt", + .description = "Flush A Cache Line Optimized", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.clwb)] = .{ + .llvm_name = "clwb", + .description = "Cache Line Write Back", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.clzero)] = .{ + .llvm_name = "clzero", + .description = "Enable Cache Line Zero", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.cmov)] = .{ + .llvm_name = "cmov", + .description = "Enable conditional move instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.cx16)] = .{ + .llvm_name = "cx16", + .description = "64-bit with cmpxchg16b", + .dependencies = featureSet(&[_]Feature{ + .cx8, + }), + }; + result[@enumToInt(Feature.cx8)] = .{ + .llvm_name = "cx8", + .description = "Support CMPXCHG8B instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.enqcmd)] = .{ + .llvm_name = "enqcmd", + .description = "Has ENQCMD instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ermsb)] = .{ + .llvm_name = "ermsb", + .description = "REP MOVS/STOS are fast", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.f16c)] = .{ + .llvm_name = "f16c", + .description = "Support 16-bit floating point conversion instructions", + .dependencies = featureSet(&[_]Feature{ + .avx, + }), + }; + result[@enumToInt(Feature.false_deps_lzcnt_tzcnt)] = .{ + .llvm_name = "false-deps-lzcnt-tzcnt", + .description = "LZCNT/TZCNT have a false dependency on dest register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.false_deps_popcnt)] = .{ + .llvm_name = "false-deps-popcnt", + .description = "POPCNT has a false dependency on dest register", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fast_11bytenop)] = .{ + .llvm_name = "fast-11bytenop", + .description = "Target can quickly decode up to 11 byte NOPs", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fast_15bytenop)] = .{ + .llvm_name = "fast-15bytenop", + .description = "Target can quickly decode up to 15 byte NOPs", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fast_bextr)] = .{ + .llvm_name = "fast-bextr", + .description = "Indicates that the BEXTR instruction is implemented as a single uop with good throughput", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fast_gather)] = .{ + .llvm_name = "fast-gather", + .description = "Indicates if gather is reasonably fast", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fast_hops)] = .{ + .llvm_name = "fast-hops", + .description = "Prefer horizontal vector math instructions (haddp, phsub, etc.) over normal vector instructions with shuffles", + .dependencies = featureSet(&[_]Feature{ + .sse3, + }), + }; + result[@enumToInt(Feature.fast_lzcnt)] = .{ + .llvm_name = "fast-lzcnt", + .description = "LZCNT instructions are as fast as most simple integer ops", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fast_partial_ymm_or_zmm_write)] = .{ + .llvm_name = "fast-partial-ymm-or-zmm-write", + .description = "Partial writes to YMM/ZMM registers are fast", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fast_scalar_fsqrt)] = .{ + .llvm_name = "fast-scalar-fsqrt", + .description = "Scalar SQRT is fast (disable Newton-Raphson)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fast_scalar_shift_masks)] = .{ + .llvm_name = "fast-scalar-shift-masks", + .description = "Prefer a left/right scalar logical shift pair over a shift+and pair", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fast_shld_rotate)] = .{ + .llvm_name = "fast-shld-rotate", + .description = "SHLD can be used as a faster rotate", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fast_variable_shuffle)] = .{ + .llvm_name = "fast-variable-shuffle", + .description = "Shuffles with variable masks are fast", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fast_vector_fsqrt)] = .{ + .llvm_name = "fast-vector-fsqrt", + .description = "Vector SQRT is fast (disable Newton-Raphson)", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fast_vector_shift_masks)] = .{ + .llvm_name = "fast-vector-shift-masks", + .description = "Prefer a left/right vector logical shift pair over a shift+and pair", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fma)] = .{ + .llvm_name = "fma", + .description = "Enable three-operand fused multiple-add", + .dependencies = featureSet(&[_]Feature{ + .avx, + }), + }; + result[@enumToInt(Feature.fma4)] = .{ + .llvm_name = "fma4", + .description = "Enable four-operand fused multiple-add", + .dependencies = featureSet(&[_]Feature{ + .avx, + .sse4a, + }), + }; + result[@enumToInt(Feature.fsgsbase)] = .{ + .llvm_name = "fsgsbase", + .description = "Support FS/GS Base instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.fxsr)] = .{ + .llvm_name = "fxsr", + .description = "Support fxsave/fxrestore instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.gfni)] = .{ + .llvm_name = "gfni", + .description = "Enable Galois Field Arithmetic Instructions", + .dependencies = featureSet(&[_]Feature{ + .sse2, + }), + }; + result[@enumToInt(Feature.idivl_to_divb)] = .{ + .llvm_name = "idivl-to-divb", + .description = "Use 8-bit divide for positive values less than 256", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.idivq_to_divl)] = .{ + .llvm_name = "idivq-to-divl", + .description = "Use 32-bit divide for positive values less than 2^32", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.invpcid)] = .{ + .llvm_name = "invpcid", + .description = "Invalidate Process-Context Identifier", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.lea_sp)] = .{ + .llvm_name = "lea-sp", + .description = "Use LEA for adjusting the stack pointer", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.lea_uses_ag)] = .{ + .llvm_name = "lea-uses-ag", + .description = "LEA instruction needs inputs at AG stage", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.lwp)] = .{ + .llvm_name = "lwp", + .description = "Enable LWP instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.lzcnt)] = .{ + .llvm_name = "lzcnt", + .description = "Support LZCNT instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.macrofusion)] = .{ + .llvm_name = "macrofusion", + .description = "Various instructions can be fused with conditional branches", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.merge_to_threeway_branch)] = .{ + .llvm_name = "merge-to-threeway-branch", + .description = "Merge branches to a three-way conditional branch", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mmx)] = .{ + .llvm_name = "mmx", + .description = "Enable MMX instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.movbe)] = .{ + .llvm_name = "movbe", + .description = "Support MOVBE instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.movdir64b)] = .{ + .llvm_name = "movdir64b", + .description = "Support movdir64b instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.movdiri)] = .{ + .llvm_name = "movdiri", + .description = "Support movdiri instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mpx)] = .{ + .llvm_name = "mpx", + .description = "Support MPX instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.mwaitx)] = .{ + .llvm_name = "mwaitx", + .description = "Enable MONITORX/MWAITX timer functionality", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.nopl)] = .{ + .llvm_name = "nopl", + .description = "Enable NOPL instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.pad_short_functions)] = .{ + .llvm_name = "pad-short-functions", + .description = "Pad short functions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.pclmul)] = .{ + .llvm_name = "pclmul", + .description = "Enable packed carry-less multiplication instructions", + .dependencies = featureSet(&[_]Feature{ + .sse2, + }), + }; + result[@enumToInt(Feature.pconfig)] = .{ + .llvm_name = "pconfig", + .description = "platform configuration instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.pku)] = .{ + .llvm_name = "pku", + .description = "Enable protection keys", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.popcnt)] = .{ + .llvm_name = "popcnt", + .description = "Support POPCNT instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.prefer_256_bit)] = .{ + .llvm_name = "prefer-256-bit", + .description = "Prefer 256-bit AVX instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.prefetchwt1)] = .{ + .llvm_name = "prefetchwt1", + .description = "Prefetch with Intent to Write and T1 Hint", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.prfchw)] = .{ + .llvm_name = "prfchw", + .description = "Support PRFCHW instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.ptwrite)] = .{ + .llvm_name = "ptwrite", + .description = "Support ptwrite instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.rdpid)] = .{ + .llvm_name = "rdpid", + .description = "Support RDPID instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.rdrnd)] = .{ + .llvm_name = "rdrnd", + .description = "Support RDRAND instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.rdseed)] = .{ + .llvm_name = "rdseed", + .description = "Support RDSEED instruction", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.retpoline)] = .{ + .llvm_name = "retpoline", + .description = "Remove speculation of indirect branches from the generated code, either by avoiding them entirely or lowering them with a speculation blocking construct", + .dependencies = featureSet(&[_]Feature{ + .retpoline_indirect_branches, + .retpoline_indirect_calls, + }), + }; + result[@enumToInt(Feature.retpoline_external_thunk)] = .{ + .llvm_name = "retpoline-external-thunk", + .description = "When lowering an indirect call or branch using a `retpoline`, rely on the specified user provided thunk rather than emitting one ourselves. Only has effect when combined with some other retpoline feature", + .dependencies = featureSet(&[_]Feature{ + .retpoline_indirect_calls, + }), + }; + result[@enumToInt(Feature.retpoline_indirect_branches)] = .{ + .llvm_name = "retpoline-indirect-branches", + .description = "Remove speculation of indirect branches from the generated code", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.retpoline_indirect_calls)] = .{ + .llvm_name = "retpoline-indirect-calls", + .description = "Remove speculation of indirect calls from the generated code", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.rtm)] = .{ + .llvm_name = "rtm", + .description = "Support RTM instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sahf)] = .{ + .llvm_name = "sahf", + .description = "Support LAHF and SAHF instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sgx)] = .{ + .llvm_name = "sgx", + .description = "Enable Software Guard Extensions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sha)] = .{ + .llvm_name = "sha", + .description = "Enable SHA instructions", + .dependencies = featureSet(&[_]Feature{ + .sse2, + }), + }; + result[@enumToInt(Feature.shstk)] = .{ + .llvm_name = "shstk", + .description = "Support CET Shadow-Stack instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.slow_3ops_lea)] = .{ + .llvm_name = "slow-3ops-lea", + .description = "LEA instruction with 3 ops or certain registers is slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.slow_incdec)] = .{ + .llvm_name = "slow-incdec", + .description = "INC and DEC instructions are slower than ADD and SUB", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.slow_lea)] = .{ + .llvm_name = "slow-lea", + .description = "LEA instruction with certain arguments is slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.slow_pmaddwd)] = .{ + .llvm_name = "slow-pmaddwd", + .description = "PMADDWD is slower than PMULLD", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.slow_pmulld)] = .{ + .llvm_name = "slow-pmulld", + .description = "PMULLD instruction is slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.slow_shld)] = .{ + .llvm_name = "slow-shld", + .description = "SHLD instruction is slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.slow_two_mem_ops)] = .{ + .llvm_name = "slow-two-mem-ops", + .description = "Two memory operand instructions are slow", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.slow_unaligned_mem_16)] = .{ + .llvm_name = "slow-unaligned-mem-16", + .description = "Slow unaligned 16-byte memory access", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.slow_unaligned_mem_32)] = .{ + .llvm_name = "slow-unaligned-mem-32", + .description = "Slow unaligned 32-byte memory access", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.soft_float)] = .{ + .llvm_name = "soft-float", + .description = "Use software floating point features", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sse)] = .{ + .llvm_name = "sse", + .description = "Enable SSE instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sse_unaligned_mem)] = .{ + .llvm_name = "sse-unaligned-mem", + .description = "Allow unaligned memory operands with SSE instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.sse2)] = .{ + .llvm_name = "sse2", + .description = "Enable SSE2 instructions", + .dependencies = featureSet(&[_]Feature{ + .sse, + }), + }; + result[@enumToInt(Feature.sse3)] = .{ + .llvm_name = "sse3", + .description = "Enable SSE3 instructions", + .dependencies = featureSet(&[_]Feature{ + .sse2, + }), + }; + result[@enumToInt(Feature.sse4_1)] = .{ + .llvm_name = "sse4.1", + .description = "Enable SSE 4.1 instructions", + .dependencies = featureSet(&[_]Feature{ + .ssse3, + }), + }; + result[@enumToInt(Feature.sse4_2)] = .{ + .llvm_name = "sse4.2", + .description = "Enable SSE 4.2 instructions", + .dependencies = featureSet(&[_]Feature{ + .sse4_1, + }), + }; + result[@enumToInt(Feature.sse4a)] = .{ + .llvm_name = "sse4a", + .description = "Support SSE 4a instructions", + .dependencies = featureSet(&[_]Feature{ + .sse3, + }), + }; + result[@enumToInt(Feature.ssse3)] = .{ + .llvm_name = "ssse3", + .description = "Enable SSSE3 instructions", + .dependencies = featureSet(&[_]Feature{ + .sse3, + }), + }; + result[@enumToInt(Feature.tbm)] = .{ + .llvm_name = "tbm", + .description = "Enable TBM instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.vaes)] = .{ + .llvm_name = "vaes", + .description = "Promote selected AES instructions to AVX512/AVX registers", + .dependencies = featureSet(&[_]Feature{ + .aes, + .avx, + }), + }; + result[@enumToInt(Feature.vpclmulqdq)] = .{ + .llvm_name = "vpclmulqdq", + .description = "Enable vpclmulqdq instructions", + .dependencies = featureSet(&[_]Feature{ + .avx, + .pclmul, + }), + }; + result[@enumToInt(Feature.waitpkg)] = .{ + .llvm_name = "waitpkg", + .description = "Wait and pause enhancements", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.wbnoinvd)] = .{ + .llvm_name = "wbnoinvd", + .description = "Write Back No Invalidate", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.x87)] = .{ + .llvm_name = "x87", + .description = "Enable X87 float instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.xop)] = .{ + .llvm_name = "xop", + .description = "Enable XOP instructions", + .dependencies = featureSet(&[_]Feature{ + .fma4, + }), + }; + result[@enumToInt(Feature.xsave)] = .{ + .llvm_name = "xsave", + .description = "Support xsave instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.xsavec)] = .{ + .llvm_name = "xsavec", + .description = "Support xsavec instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.xsaveopt)] = .{ + .llvm_name = "xsaveopt", + .description = "Support xsaveopt instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + result[@enumToInt(Feature.xsaves)] = .{ + .llvm_name = "xsaves", + .description = "Support xsaves instructions", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (result) |*elem, i| { + elem.index = i; + elem.name = ti.Enum.fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const amdfam10 = Cpu{ + .name = "amdfam10", + .llvm_name = "amdfam10", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .@"64bit", + .cmov, + .cx16, + .cx8, + .fast_scalar_shift_masks, + .fxsr, + .lzcnt, + .nopl, + .popcnt, + .sahf, + .slow_shld, + .sse4a, + .x87, + }), + }; + pub const athlon = Cpu{ + .name = "athlon", + .llvm_name = "athlon", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .cmov, + .cx8, + .nopl, + .slow_shld, + .slow_unaligned_mem_16, + .x87, + }), + }; + pub const athlon_4 = Cpu{ + .name = "athlon_4", + .llvm_name = "athlon-4", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .cmov, + .cx8, + .fxsr, + .nopl, + .slow_shld, + .slow_unaligned_mem_16, + .sse, + .x87, + }), + }; + pub const athlon_fx = Cpu{ + .name = "athlon_fx", + .llvm_name = "athlon-fx", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .@"64bit", + .cmov, + .cx8, + .fast_scalar_shift_masks, + .fxsr, + .nopl, + .slow_shld, + .slow_unaligned_mem_16, + .sse2, + .x87, + }), + }; + pub const athlon_mp = Cpu{ + .name = "athlon_mp", + .llvm_name = "athlon-mp", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .cmov, + .cx8, + .fxsr, + .nopl, + .slow_shld, + .slow_unaligned_mem_16, + .sse, + .x87, + }), + }; + pub const athlon_tbird = Cpu{ + .name = "athlon_tbird", + .llvm_name = "athlon-tbird", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .cmov, + .cx8, + .nopl, + .slow_shld, + .slow_unaligned_mem_16, + .x87, + }), + }; + pub const athlon_xp = Cpu{ + .name = "athlon_xp", + .llvm_name = "athlon-xp", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .cmov, + .cx8, + .fxsr, + .nopl, + .slow_shld, + .slow_unaligned_mem_16, + .sse, + .x87, + }), + }; + pub const athlon64 = Cpu{ + .name = "athlon64", + .llvm_name = "athlon64", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .@"64bit", + .cmov, + .cx8, + .fast_scalar_shift_masks, + .fxsr, + .nopl, + .slow_shld, + .slow_unaligned_mem_16, + .sse2, + .x87, + }), + }; + pub const athlon64_sse3 = Cpu{ + .name = "athlon64_sse3", + .llvm_name = "athlon64-sse3", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .@"64bit", + .cmov, + .cx16, + .cx8, + .fast_scalar_shift_masks, + .fxsr, + .nopl, + .slow_shld, + .slow_unaligned_mem_16, + .sse3, + .x87, + }), + }; + pub const atom = Cpu{ + .name = "atom", + .llvm_name = "atom", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .cx16, + .cx8, + .fxsr, + .idivl_to_divb, + .idivq_to_divl, + .lea_sp, + .lea_uses_ag, + .mmx, + .movbe, + .nopl, + .pad_short_functions, + .sahf, + .slow_two_mem_ops, + .slow_unaligned_mem_16, + .ssse3, + .x87, + }), + }; + pub const barcelona = Cpu{ + .name = "barcelona", + .llvm_name = "barcelona", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .@"64bit", + .cmov, + .cx16, + .cx8, + .fast_scalar_shift_masks, + .fxsr, + .lzcnt, + .nopl, + .popcnt, + .sahf, + .slow_shld, + .sse4a, + .x87, + }), + }; + pub const bdver1 = Cpu{ + .name = "bdver1", + .llvm_name = "bdver1", + .features = featureSet(&[_]Feature{ + .@"64bit", + .aes, + .branchfusion, + .cmov, + .cx16, + .cx8, + .fast_11bytenop, + .fast_scalar_shift_masks, + .fxsr, + .lwp, + .lzcnt, + .mmx, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .sahf, + .slow_shld, + .x87, + .xop, + .xsave, + }), + }; + pub const bdver2 = Cpu{ + .name = "bdver2", + .llvm_name = "bdver2", + .features = featureSet(&[_]Feature{ + .@"64bit", + .aes, + .bmi, + .branchfusion, + .cmov, + .cx16, + .cx8, + .f16c, + .fast_11bytenop, + .fast_bextr, + .fast_scalar_shift_masks, + .fma, + .fxsr, + .lwp, + .lzcnt, + .mmx, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .sahf, + .slow_shld, + .tbm, + .x87, + .xop, + .xsave, + }), + }; + pub const bdver3 = Cpu{ + .name = "bdver3", + .llvm_name = "bdver3", + .features = featureSet(&[_]Feature{ + .@"64bit", + .aes, + .bmi, + .branchfusion, + .cmov, + .cx16, + .cx8, + .f16c, + .fast_11bytenop, + .fast_bextr, + .fast_scalar_shift_masks, + .fma, + .fsgsbase, + .fxsr, + .lwp, + .lzcnt, + .mmx, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .sahf, + .slow_shld, + .tbm, + .x87, + .xop, + .xsave, + .xsaveopt, + }), + }; + pub const bdver4 = Cpu{ + .name = "bdver4", + .llvm_name = "bdver4", + .features = featureSet(&[_]Feature{ + .@"64bit", + .aes, + .avx2, + .bmi, + .bmi2, + .branchfusion, + .cmov, + .cx16, + .cx8, + .f16c, + .fast_11bytenop, + .fast_bextr, + .fast_scalar_shift_masks, + .fma, + .fsgsbase, + .fxsr, + .lwp, + .lzcnt, + .mmx, + .mwaitx, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .sahf, + .slow_shld, + .tbm, + .x87, + .xop, + .xsave, + .xsaveopt, + }), + }; + pub const bonnell = Cpu{ + .name = "bonnell", + .llvm_name = "bonnell", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .cx16, + .cx8, + .fxsr, + .idivl_to_divb, + .idivq_to_divl, + .lea_sp, + .lea_uses_ag, + .mmx, + .movbe, + .nopl, + .pad_short_functions, + .sahf, + .slow_two_mem_ops, + .slow_unaligned_mem_16, + .ssse3, + .x87, + }), + }; + pub const broadwell = Cpu{ + .name = "broadwell", + .llvm_name = "broadwell", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .avx, + .avx2, + .bmi, + .bmi2, + .cmov, + .cx16, + .cx8, + .ermsb, + .f16c, + .false_deps_lzcnt_tzcnt, + .false_deps_popcnt, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_shuffle, + .fma, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .merge_to_threeway_branch, + .mmx, + .movbe, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .slow_3ops_lea, + .sse4_2, + .x87, + .xsave, + .xsaveopt, + }), + }; + pub const btver1 = Cpu{ + .name = "btver1", + .llvm_name = "btver1", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .cx16, + .cx8, + .fast_15bytenop, + .fast_scalar_shift_masks, + .fast_vector_shift_masks, + .fxsr, + .lzcnt, + .mmx, + .nopl, + .popcnt, + .prfchw, + .sahf, + .slow_shld, + .sse4a, + .ssse3, + .x87, + }), + }; + pub const btver2 = Cpu{ + .name = "btver2", + .llvm_name = "btver2", + .features = featureSet(&[_]Feature{ + .@"64bit", + .aes, + .avx, + .bmi, + .cmov, + .cx16, + .cx8, + .f16c, + .fast_15bytenop, + .fast_bextr, + .fast_hops, + .fast_lzcnt, + .fast_partial_ymm_or_zmm_write, + .fast_scalar_shift_masks, + .fast_vector_shift_masks, + .fxsr, + .lzcnt, + .mmx, + .movbe, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .sahf, + .slow_shld, + .sse4a, + .ssse3, + .x87, + .xsave, + .xsaveopt, + }), + }; + pub const c3 = Cpu{ + .name = "c3", + .llvm_name = "c3", + .features = featureSet(&[_]Feature{ + .@"3dnow", + .slow_unaligned_mem_16, + .x87, + }), + }; + pub const c3_2 = Cpu{ + .name = "c3_2", + .llvm_name = "c3-2", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .fxsr, + .mmx, + .slow_unaligned_mem_16, + .sse, + .x87, + }), + }; + pub const cannonlake = Cpu{ + .name = "cannonlake", + .llvm_name = "cannonlake", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .avx, + .avx2, + .avx512bw, + .avx512cd, + .avx512dq, + .avx512f, + .avx512ifma, + .avx512vbmi, + .avx512vl, + .bmi, + .bmi2, + .clflushopt, + .cmov, + .cx16, + .cx8, + .ermsb, + .f16c, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_shuffle, + .fast_vector_fsqrt, + .fma, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .merge_to_threeway_branch, + .mmx, + .movbe, + .mpx, + .nopl, + .pclmul, + .pku, + .popcnt, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .sgx, + .sha, + .slow_3ops_lea, + .sse4_2, + .x87, + .xsave, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const cascadelake = Cpu{ + .name = "cascadelake", + .llvm_name = "cascadelake", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .avx, + .avx2, + .avx512bw, + .avx512cd, + .avx512dq, + .avx512f, + .avx512vl, + .avx512vnni, + .bmi, + .bmi2, + .clflushopt, + .clwb, + .cmov, + .cx16, + .cx8, + .ermsb, + .f16c, + .false_deps_popcnt, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_shuffle, + .fast_vector_fsqrt, + .fma, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .merge_to_threeway_branch, + .mmx, + .movbe, + .mpx, + .nopl, + .pclmul, + .pku, + .popcnt, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .slow_3ops_lea, + .sse4_2, + .x87, + .xsave, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const cooperlake = Cpu{ + .name = "cooperlake", + .llvm_name = "cooperlake", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .avx, + .avx2, + .avx512bf16, + .avx512bw, + .avx512cd, + .avx512dq, + .avx512f, + .avx512vl, + .avx512vnni, + .bmi, + .bmi2, + .clflushopt, + .clwb, + .cmov, + .cx16, + .cx8, + .ermsb, + .f16c, + .false_deps_popcnt, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_shuffle, + .fast_vector_fsqrt, + .fma, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .merge_to_threeway_branch, + .mmx, + .movbe, + .mpx, + .nopl, + .pclmul, + .pku, + .popcnt, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .slow_3ops_lea, + .sse4_2, + .x87, + .xsave, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const core_avx_i = Cpu{ + .name = "core_avx_i", + .llvm_name = "core-avx-i", + .features = featureSet(&[_]Feature{ + .@"64bit", + .avx, + .cmov, + .cx16, + .cx8, + .f16c, + .false_deps_popcnt, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .macrofusion, + .merge_to_threeway_branch, + .mmx, + .nopl, + .pclmul, + .popcnt, + .rdrnd, + .sahf, + .slow_3ops_lea, + .slow_unaligned_mem_32, + .sse4_2, + .x87, + .xsave, + .xsaveopt, + }), + }; + pub const core_avx2 = Cpu{ + .name = "core_avx2", + .llvm_name = "core-avx2", + .features = featureSet(&[_]Feature{ + .@"64bit", + .avx, + .avx2, + .bmi, + .bmi2, + .cmov, + .cx16, + .cx8, + .ermsb, + .f16c, + .false_deps_lzcnt_tzcnt, + .false_deps_popcnt, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_shuffle, + .fma, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .merge_to_threeway_branch, + .mmx, + .movbe, + .nopl, + .pclmul, + .popcnt, + .rdrnd, + .sahf, + .slow_3ops_lea, + .sse4_2, + .x87, + .xsave, + .xsaveopt, + }), + }; + pub const core2 = Cpu{ + .name = "core2", + .llvm_name = "core2", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .cx16, + .cx8, + .fxsr, + .macrofusion, + .mmx, + .nopl, + .sahf, + .slow_unaligned_mem_16, + .ssse3, + .x87, + }), + }; + pub const corei7 = Cpu{ + .name = "corei7", + .llvm_name = "corei7", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .cx16, + .cx8, + .fxsr, + .macrofusion, + .mmx, + .nopl, + .popcnt, + .sahf, + .sse4_2, + .x87, + }), + }; + pub const corei7_avx = Cpu{ + .name = "corei7_avx", + .llvm_name = "corei7-avx", + .features = featureSet(&[_]Feature{ + .@"64bit", + .avx, + .cmov, + .cx16, + .cx8, + .false_deps_popcnt, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fxsr, + .idivq_to_divl, + .macrofusion, + .merge_to_threeway_branch, + .mmx, + .nopl, + .pclmul, + .popcnt, + .sahf, + .slow_3ops_lea, + .slow_unaligned_mem_32, + .sse4_2, + .x87, + .xsave, + .xsaveopt, + }), + }; + pub const generic = Cpu{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{ + .cx8, + .slow_unaligned_mem_16, + .x87, + }), + }; + pub const geode = Cpu{ + .name = "geode", + .llvm_name = "geode", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .cx8, + .slow_unaligned_mem_16, + .x87, + }), + }; + pub const goldmont = Cpu{ + .name = "goldmont", + .llvm_name = "goldmont", + .features = featureSet(&[_]Feature{ + .@"64bit", + .aes, + .clflushopt, + .cmov, + .cx16, + .cx8, + .false_deps_popcnt, + .fsgsbase, + .fxsr, + .mmx, + .movbe, + .mpx, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .sha, + .slow_incdec, + .slow_lea, + .slow_two_mem_ops, + .sse4_2, + .ssse3, + .x87, + .xsave, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const goldmont_plus = Cpu{ + .name = "goldmont_plus", + .llvm_name = "goldmont-plus", + .features = featureSet(&[_]Feature{ + .@"64bit", + .aes, + .clflushopt, + .cmov, + .cx16, + .cx8, + .fsgsbase, + .fxsr, + .mmx, + .movbe, + .mpx, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .ptwrite, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .sgx, + .sha, + .slow_incdec, + .slow_lea, + .slow_two_mem_ops, + .sse4_2, + .ssse3, + .x87, + .xsave, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const haswell = Cpu{ + .name = "haswell", + .llvm_name = "haswell", + .features = featureSet(&[_]Feature{ + .@"64bit", + .avx, + .avx2, + .bmi, + .bmi2, + .cmov, + .cx16, + .cx8, + .ermsb, + .f16c, + .false_deps_lzcnt_tzcnt, + .false_deps_popcnt, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_shuffle, + .fma, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .merge_to_threeway_branch, + .mmx, + .movbe, + .nopl, + .pclmul, + .popcnt, + .rdrnd, + .sahf, + .slow_3ops_lea, + .sse4_2, + .x87, + .xsave, + .xsaveopt, + }), + }; + pub const _i386 = Cpu{ + .name = "_i386", + .llvm_name = "i386", + .features = featureSet(&[_]Feature{ + .slow_unaligned_mem_16, + .x87, + }), + }; + pub const _i486 = Cpu{ + .name = "_i486", + .llvm_name = "i486", + .features = featureSet(&[_]Feature{ + .slow_unaligned_mem_16, + .x87, + }), + }; + pub const _i586 = Cpu{ + .name = "_i586", + .llvm_name = "i586", + .features = featureSet(&[_]Feature{ + .cx8, + .slow_unaligned_mem_16, + .x87, + }), + }; + pub const _i686 = Cpu{ + .name = "_i686", + .llvm_name = "i686", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .slow_unaligned_mem_16, + .x87, + }), + }; + pub const icelake_client = Cpu{ + .name = "icelake_client", + .llvm_name = "icelake-client", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .avx, + .avx2, + .avx512bitalg, + .avx512bw, + .avx512cd, + .avx512dq, + .avx512f, + .avx512ifma, + .avx512vbmi, + .avx512vbmi2, + .avx512vl, + .avx512vnni, + .avx512vpopcntdq, + .bmi, + .bmi2, + .clflushopt, + .clwb, + .cmov, + .cx16, + .cx8, + .ermsb, + .f16c, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_shuffle, + .fast_vector_fsqrt, + .fma, + .fsgsbase, + .fxsr, + .gfni, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .merge_to_threeway_branch, + .mmx, + .movbe, + .mpx, + .nopl, + .pclmul, + .pku, + .popcnt, + .prfchw, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .sgx, + .sha, + .slow_3ops_lea, + .sse4_2, + .vaes, + .vpclmulqdq, + .x87, + .xsave, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const icelake_server = Cpu{ + .name = "icelake_server", + .llvm_name = "icelake-server", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .avx, + .avx2, + .avx512bitalg, + .avx512bw, + .avx512cd, + .avx512dq, + .avx512f, + .avx512ifma, + .avx512vbmi, + .avx512vbmi2, + .avx512vl, + .avx512vnni, + .avx512vpopcntdq, + .bmi, + .bmi2, + .clflushopt, + .clwb, + .cmov, + .cx16, + .cx8, + .ermsb, + .f16c, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_shuffle, + .fast_vector_fsqrt, + .fma, + .fsgsbase, + .fxsr, + .gfni, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .merge_to_threeway_branch, + .mmx, + .movbe, + .mpx, + .nopl, + .pclmul, + .pconfig, + .pku, + .popcnt, + .prfchw, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .sgx, + .sha, + .slow_3ops_lea, + .sse4_2, + .vaes, + .vpclmulqdq, + .wbnoinvd, + .x87, + .xsave, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const ivybridge = Cpu{ + .name = "ivybridge", + .llvm_name = "ivybridge", + .features = featureSet(&[_]Feature{ + .@"64bit", + .avx, + .cmov, + .cx16, + .cx8, + .f16c, + .false_deps_popcnt, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .macrofusion, + .merge_to_threeway_branch, + .mmx, + .nopl, + .pclmul, + .popcnt, + .rdrnd, + .sahf, + .slow_3ops_lea, + .slow_unaligned_mem_32, + .sse4_2, + .x87, + .xsave, + .xsaveopt, + }), + }; + pub const k6 = Cpu{ + .name = "k6", + .llvm_name = "k6", + .features = featureSet(&[_]Feature{ + .cx8, + .mmx, + .slow_unaligned_mem_16, + .x87, + }), + }; + pub const k6_2 = Cpu{ + .name = "k6_2", + .llvm_name = "k6-2", + .features = featureSet(&[_]Feature{ + .@"3dnow", + .cx8, + .slow_unaligned_mem_16, + .x87, + }), + }; + pub const k6_3 = Cpu{ + .name = "k6_3", + .llvm_name = "k6-3", + .features = featureSet(&[_]Feature{ + .@"3dnow", + .cx8, + .slow_unaligned_mem_16, + .x87, + }), + }; + pub const k8 = Cpu{ + .name = "k8", + .llvm_name = "k8", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .@"64bit", + .cmov, + .cx8, + .fast_scalar_shift_masks, + .fxsr, + .nopl, + .slow_shld, + .slow_unaligned_mem_16, + .sse2, + .x87, + }), + }; + pub const k8_sse3 = Cpu{ + .name = "k8_sse3", + .llvm_name = "k8-sse3", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .@"64bit", + .cmov, + .cx16, + .cx8, + .fast_scalar_shift_masks, + .fxsr, + .nopl, + .slow_shld, + .slow_unaligned_mem_16, + .sse3, + .x87, + }), + }; + pub const knl = Cpu{ + .name = "knl", + .llvm_name = "knl", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .avx512cd, + .avx512er, + .avx512f, + .avx512pf, + .bmi, + .bmi2, + .cmov, + .cx16, + .cx8, + .f16c, + .fast_gather, + .fast_partial_ymm_or_zmm_write, + .fma, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .lzcnt, + .mmx, + .movbe, + .nopl, + .pclmul, + .popcnt, + .prefetchwt1, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .slow_3ops_lea, + .slow_incdec, + .slow_pmaddwd, + .slow_two_mem_ops, + .x87, + .xsave, + .xsaveopt, + }), + }; + pub const knm = Cpu{ + .name = "knm", + .llvm_name = "knm", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .avx512cd, + .avx512er, + .avx512f, + .avx512pf, + .avx512vpopcntdq, + .bmi, + .bmi2, + .cmov, + .cx16, + .cx8, + .f16c, + .fast_gather, + .fast_partial_ymm_or_zmm_write, + .fma, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .lzcnt, + .mmx, + .movbe, + .nopl, + .pclmul, + .popcnt, + .prefetchwt1, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .slow_3ops_lea, + .slow_incdec, + .slow_pmaddwd, + .slow_two_mem_ops, + .x87, + .xsave, + .xsaveopt, + }), + }; + pub const lakemont = Cpu{ + .name = "lakemont", + .llvm_name = "lakemont", + .features = featureSet(&[_]Feature{}), + }; + pub const nehalem = Cpu{ + .name = "nehalem", + .llvm_name = "nehalem", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .cx16, + .cx8, + .fxsr, + .macrofusion, + .mmx, + .nopl, + .popcnt, + .sahf, + .sse4_2, + .x87, + }), + }; + pub const nocona = Cpu{ + .name = "nocona", + .llvm_name = "nocona", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .cx16, + .cx8, + .fxsr, + .mmx, + .nopl, + .slow_unaligned_mem_16, + .sse3, + .x87, + }), + }; + pub const opteron = Cpu{ + .name = "opteron", + .llvm_name = "opteron", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .@"64bit", + .cmov, + .cx8, + .fast_scalar_shift_masks, + .fxsr, + .nopl, + .slow_shld, + .slow_unaligned_mem_16, + .sse2, + .x87, + }), + }; + pub const opteron_sse3 = Cpu{ + .name = "opteron_sse3", + .llvm_name = "opteron-sse3", + .features = featureSet(&[_]Feature{ + .@"3dnowa", + .@"64bit", + .cmov, + .cx16, + .cx8, + .fast_scalar_shift_masks, + .fxsr, + .nopl, + .slow_shld, + .slow_unaligned_mem_16, + .sse3, + .x87, + }), + }; + pub const penryn = Cpu{ + .name = "penryn", + .llvm_name = "penryn", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .cx16, + .cx8, + .fxsr, + .macrofusion, + .mmx, + .nopl, + .sahf, + .slow_unaligned_mem_16, + .sse4_1, + .x87, + }), + }; + pub const pentium = Cpu{ + .name = "pentium", + .llvm_name = "pentium", + .features = featureSet(&[_]Feature{ + .cx8, + .slow_unaligned_mem_16, + .x87, + }), + }; + pub const pentium_m = Cpu{ + .name = "pentium_m", + .llvm_name = "pentium-m", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .fxsr, + .mmx, + .nopl, + .slow_unaligned_mem_16, + .sse2, + .x87, + }), + }; + pub const pentium_mmx = Cpu{ + .name = "pentium_mmx", + .llvm_name = "pentium-mmx", + .features = featureSet(&[_]Feature{ + .cx8, + .mmx, + .slow_unaligned_mem_16, + .x87, + }), + }; + pub const pentium2 = Cpu{ + .name = "pentium2", + .llvm_name = "pentium2", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .fxsr, + .mmx, + .nopl, + .slow_unaligned_mem_16, + .x87, + }), + }; + pub const pentium3 = Cpu{ + .name = "pentium3", + .llvm_name = "pentium3", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .fxsr, + .mmx, + .nopl, + .slow_unaligned_mem_16, + .sse, + .x87, + }), + }; + pub const pentium3m = Cpu{ + .name = "pentium3m", + .llvm_name = "pentium3m", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .fxsr, + .mmx, + .nopl, + .slow_unaligned_mem_16, + .sse, + .x87, + }), + }; + pub const pentium4 = Cpu{ + .name = "pentium4", + .llvm_name = "pentium4", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .fxsr, + .mmx, + .nopl, + .slow_unaligned_mem_16, + .sse2, + .x87, + }), + }; + pub const pentium4m = Cpu{ + .name = "pentium4m", + .llvm_name = "pentium4m", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .fxsr, + .mmx, + .nopl, + .slow_unaligned_mem_16, + .sse2, + .x87, + }), + }; + pub const pentiumpro = Cpu{ + .name = "pentiumpro", + .llvm_name = "pentiumpro", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .nopl, + .slow_unaligned_mem_16, + .x87, + }), + }; + pub const prescott = Cpu{ + .name = "prescott", + .llvm_name = "prescott", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .fxsr, + .mmx, + .nopl, + .slow_unaligned_mem_16, + .sse3, + .x87, + }), + }; + pub const sandybridge = Cpu{ + .name = "sandybridge", + .llvm_name = "sandybridge", + .features = featureSet(&[_]Feature{ + .@"64bit", + .avx, + .cmov, + .cx16, + .cx8, + .false_deps_popcnt, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fxsr, + .idivq_to_divl, + .macrofusion, + .merge_to_threeway_branch, + .mmx, + .nopl, + .pclmul, + .popcnt, + .sahf, + .slow_3ops_lea, + .slow_unaligned_mem_32, + .sse4_2, + .x87, + .xsave, + .xsaveopt, + }), + }; + pub const silvermont = Cpu{ + .name = "silvermont", + .llvm_name = "silvermont", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .cx16, + .cx8, + .false_deps_popcnt, + .fxsr, + .idivq_to_divl, + .mmx, + .movbe, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .rdrnd, + .sahf, + .slow_incdec, + .slow_lea, + .slow_pmulld, + .slow_two_mem_ops, + .sse4_2, + .ssse3, + .x87, + }), + }; + pub const skx = Cpu{ + .name = "skx", + .llvm_name = "skx", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .avx, + .avx2, + .avx512bw, + .avx512cd, + .avx512dq, + .avx512f, + .avx512vl, + .bmi, + .bmi2, + .clflushopt, + .clwb, + .cmov, + .cx16, + .cx8, + .ermsb, + .f16c, + .false_deps_popcnt, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_shuffle, + .fast_vector_fsqrt, + .fma, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .merge_to_threeway_branch, + .mmx, + .movbe, + .mpx, + .nopl, + .pclmul, + .pku, + .popcnt, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .slow_3ops_lea, + .sse4_2, + .x87, + .xsave, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const skylake = Cpu{ + .name = "skylake", + .llvm_name = "skylake", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .avx, + .avx2, + .bmi, + .bmi2, + .clflushopt, + .cmov, + .cx16, + .cx8, + .ermsb, + .f16c, + .false_deps_popcnt, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_shuffle, + .fast_vector_fsqrt, + .fma, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .merge_to_threeway_branch, + .mmx, + .movbe, + .mpx, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .sgx, + .slow_3ops_lea, + .sse4_2, + .x87, + .xsave, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const skylake_avx512 = Cpu{ + .name = "skylake_avx512", + .llvm_name = "skylake-avx512", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .avx, + .avx2, + .avx512bw, + .avx512cd, + .avx512dq, + .avx512f, + .avx512vl, + .bmi, + .bmi2, + .clflushopt, + .clwb, + .cmov, + .cx16, + .cx8, + .ermsb, + .f16c, + .false_deps_popcnt, + .fast_gather, + .fast_scalar_fsqrt, + .fast_shld_rotate, + .fast_variable_shuffle, + .fast_vector_fsqrt, + .fma, + .fsgsbase, + .fxsr, + .idivq_to_divl, + .invpcid, + .lzcnt, + .macrofusion, + .merge_to_threeway_branch, + .mmx, + .movbe, + .mpx, + .nopl, + .pclmul, + .pku, + .popcnt, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .slow_3ops_lea, + .sse4_2, + .x87, + .xsave, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const slm = Cpu{ + .name = "slm", + .llvm_name = "slm", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .cx16, + .cx8, + .false_deps_popcnt, + .fxsr, + .idivq_to_divl, + .mmx, + .movbe, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .rdrnd, + .sahf, + .slow_incdec, + .slow_lea, + .slow_pmulld, + .slow_two_mem_ops, + .sse4_2, + .ssse3, + .x87, + }), + }; + pub const tremont = Cpu{ + .name = "tremont", + .llvm_name = "tremont", + .features = featureSet(&[_]Feature{ + .@"64bit", + .aes, + .cldemote, + .clflushopt, + .cmov, + .cx16, + .cx8, + .fsgsbase, + .fxsr, + .gfni, + .mmx, + .movbe, + .movdir64b, + .movdiri, + .mpx, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .ptwrite, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .sgx, + .sha, + .slow_incdec, + .slow_lea, + .slow_two_mem_ops, + .sse4_2, + .ssse3, + .waitpkg, + .x87, + .xsave, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const westmere = Cpu{ + .name = "westmere", + .llvm_name = "westmere", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .cx16, + .cx8, + .fxsr, + .macrofusion, + .mmx, + .nopl, + .pclmul, + .popcnt, + .sahf, + .sse4_2, + .x87, + }), + }; + pub const winchip_c6 = Cpu{ + .name = "winchip_c6", + .llvm_name = "winchip-c6", + .features = featureSet(&[_]Feature{ + .mmx, + .slow_unaligned_mem_16, + .x87, + }), + }; + pub const winchip2 = Cpu{ + .name = "winchip2", + .llvm_name = "winchip2", + .features = featureSet(&[_]Feature{ + .@"3dnow", + .slow_unaligned_mem_16, + .x87, + }), + }; + pub const x86_64 = Cpu{ + .name = "x86_64", + .llvm_name = "x86-64", + .features = featureSet(&[_]Feature{ + .@"64bit", + .cmov, + .cx8, + .fxsr, + .macrofusion, + .mmx, + .nopl, + .slow_3ops_lea, + .slow_incdec, + .sse2, + .x87, + }), + }; + pub const yonah = Cpu{ + .name = "yonah", + .llvm_name = "yonah", + .features = featureSet(&[_]Feature{ + .cmov, + .cx8, + .fxsr, + .mmx, + .nopl, + .slow_unaligned_mem_16, + .sse3, + .x87, + }), + }; + pub const znver1 = Cpu{ + .name = "znver1", + .llvm_name = "znver1", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .avx2, + .bmi, + .bmi2, + .branchfusion, + .clflushopt, + .clzero, + .cmov, + .cx16, + .f16c, + .fast_15bytenop, + .fast_bextr, + .fast_lzcnt, + .fast_scalar_shift_masks, + .fma, + .fsgsbase, + .fxsr, + .lzcnt, + .mmx, + .movbe, + .mwaitx, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .rdrnd, + .rdseed, + .sahf, + .sha, + .slow_shld, + .sse4a, + .x87, + .xsave, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; + pub const znver2 = Cpu{ + .name = "znver2", + .llvm_name = "znver2", + .features = featureSet(&[_]Feature{ + .@"64bit", + .adx, + .aes, + .avx2, + .bmi, + .bmi2, + .branchfusion, + .clflushopt, + .clwb, + .clzero, + .cmov, + .cx16, + .f16c, + .fast_15bytenop, + .fast_bextr, + .fast_lzcnt, + .fast_scalar_shift_masks, + .fma, + .fsgsbase, + .fxsr, + .lzcnt, + .mmx, + .movbe, + .mwaitx, + .nopl, + .pclmul, + .popcnt, + .prfchw, + .rdpid, + .rdrnd, + .rdseed, + .sahf, + .sha, + .slow_shld, + .sse4a, + .wbnoinvd, + .x87, + .xsave, + .xsavec, + .xsaveopt, + .xsaves, + }), + }; +}; + +/// All x86 CPUs, sorted alphabetically by name. +/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1 +/// compiler has inefficient memory and CPU usage, affecting build times. +pub const all_cpus = &[_]*const Cpu{ + &cpu.amdfam10, + &cpu.athlon, + &cpu.athlon_4, + &cpu.athlon_fx, + &cpu.athlon_mp, + &cpu.athlon_tbird, + &cpu.athlon_xp, + &cpu.athlon64, + &cpu.athlon64_sse3, + &cpu.atom, + &cpu.barcelona, + &cpu.bdver1, + &cpu.bdver2, + &cpu.bdver3, + &cpu.bdver4, + &cpu.bonnell, + &cpu.broadwell, + &cpu.btver1, + &cpu.btver2, + &cpu.c3, + &cpu.c3_2, + &cpu.cannonlake, + &cpu.cascadelake, + &cpu.cooperlake, + &cpu.core_avx_i, + &cpu.core_avx2, + &cpu.core2, + &cpu.corei7, + &cpu.corei7_avx, + &cpu.generic, + &cpu.geode, + &cpu.goldmont, + &cpu.goldmont_plus, + &cpu.haswell, + &cpu._i386, + &cpu._i486, + &cpu._i586, + &cpu._i686, + &cpu.icelake_client, + &cpu.icelake_server, + &cpu.ivybridge, + &cpu.k6, + &cpu.k6_2, + &cpu.k6_3, + &cpu.k8, + &cpu.k8_sse3, + &cpu.knl, + &cpu.knm, + &cpu.lakemont, + &cpu.nehalem, + &cpu.nocona, + &cpu.opteron, + &cpu.opteron_sse3, + &cpu.penryn, + &cpu.pentium, + &cpu.pentium_m, + &cpu.pentium_mmx, + &cpu.pentium2, + &cpu.pentium3, + &cpu.pentium3m, + &cpu.pentium4, + &cpu.pentium4m, + &cpu.pentiumpro, + &cpu.prescott, + &cpu.sandybridge, + &cpu.silvermont, + &cpu.skx, + &cpu.skylake, + &cpu.skylake_avx512, + &cpu.slm, + &cpu.tremont, + &cpu.westmere, + &cpu.winchip_c6, + &cpu.winchip2, + &cpu.x86_64, + &cpu.yonah, + &cpu.znver1, + &cpu.znver2, +}; diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index 37f1eebe27..d2db306be8 100644 --- a/src-self-hosted/clang.zig +++ b/src-self-hosted/clang.zig @@ -768,6 +768,7 @@ pub extern fn ZigClangFieldDecl_getCanonicalDecl(field_decl: ?*const struct_ZigC pub extern fn ZigClangEnumDecl_getCanonicalDecl(self: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangTagDecl; pub extern fn ZigClangTypedefNameDecl_getCanonicalDecl(self: ?*const struct_ZigClangTypedefNameDecl) ?*const struct_ZigClangTypedefNameDecl; pub extern fn ZigClangFunctionDecl_getCanonicalDecl(self: ?*const struct_ZigClangFunctionDecl) ?*const struct_ZigClangFunctionDecl; +pub extern fn ZigClangParmVarDecl_getOriginalType(self: ?*const struct_ZigClangParmVarDecl) struct_ZigClangQualType; pub extern fn ZigClangVarDecl_getCanonicalDecl(self: ?*const struct_ZigClangVarDecl) ?*const struct_ZigClangVarDecl; pub extern fn ZigClangVarDecl_getSectionAttribute(self: *const ZigClangVarDecl, len: *usize) ?[*]const u8; pub extern fn ZigClangFunctionDecl_getAlignedAttribute(self: *const ZigClangFunctionDecl, *const ZigClangASTContext) c_uint; @@ -809,6 +810,7 @@ pub extern fn ZigClangQualType_isRestrictQualified(self: struct_ZigClangQualType pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass; pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) struct_ZigClangQualType; pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool; +pub extern fn ZigClangType_isConstantArrayType(self: ?*const struct_ZigClangType) bool; pub extern fn ZigClangType_isRecordType(self: ?*const struct_ZigClangType) bool; pub extern fn ZigClangType_isArrayType(self: ?*const struct_ZigClangType) bool; pub extern fn ZigClangType_isBooleanType(self: ?*const struct_ZigClangType) bool; diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index af3fd3a015..fc0825f3db 100644 --- a/src-self-hosted/main.zig +++ b/src-self-hosted/main.zig @@ -79,7 +79,9 @@ pub fn main() !void { } else if (mem.eql(u8, cmd, "libc")) { return cmdLibC(allocator, cmd_args); } else if (mem.eql(u8, cmd, "targets")) { - return cmdTargets(allocator, cmd_args); + // TODO figure out the current target rather than using the target that was specified when + // compiling the compiler + return @import("print_targets.zig").cmdTargets(allocator, cmd_args, stdout, Target.current); } else if (mem.eql(u8, cmd, "version")) { return cmdVersion(allocator, cmd_args); } else if (mem.eql(u8, cmd, "zen")) { @@ -789,48 +791,6 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro } } -// cmd:targets ///////////////////////////////////////////////////////////////////////////////////// - -fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void { - try stdout.write("Architectures:\n"); - { - comptime var i: usize = 0; - inline while (i < @memberCount(builtin.Arch)) : (i += 1) { - comptime const arch_tag = @memberName(builtin.Arch, i); - // NOTE: Cannot use empty string, see #918. - comptime const native_str = if (comptime mem.eql(u8, arch_tag, @tagName(builtin.arch))) " (native)\n" else "\n"; - - try stdout.print(" {}{}", .{ arch_tag, native_str }); - } - } - try stdout.write("\n"); - - try stdout.write("Operating Systems:\n"); - { - comptime var i: usize = 0; - inline while (i < @memberCount(Target.Os)) : (i += 1) { - comptime const os_tag = @memberName(Target.Os, i); - // NOTE: Cannot use empty string, see #918. - comptime const native_str = if (comptime mem.eql(u8, os_tag, @tagName(builtin.os))) " (native)\n" else "\n"; - - try stdout.print(" {}{}", .{ os_tag, native_str }); - } - } - try stdout.write("\n"); - - try stdout.write("C ABIs:\n"); - { - comptime var i: usize = 0; - inline while (i < @memberCount(Target.Abi)) : (i += 1) { - comptime const abi_tag = @memberName(Target.Abi, i); - // NOTE: Cannot use empty string, see #918. - comptime const native_str = if (comptime mem.eql(u8, abi_tag, @tagName(builtin.abi))) " (native)\n" else "\n"; - - try stdout.print(" {}{}", .{ abi_tag, native_str }); - } - } -} - fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void { try stdout.print("{}\n", .{std.mem.toSliceConst(u8, c.ZIG_VERSION_STRING)}); } diff --git a/src-self-hosted/print_targets.zig b/src-self-hosted/print_targets.zig new file mode 100644 index 0000000000..79041da431 --- /dev/null +++ b/src-self-hosted/print_targets.zig @@ -0,0 +1,251 @@ +const std = @import("std"); +const fs = std.fs; +const io = std.io; +const mem = std.mem; +const Allocator = mem.Allocator; +const Target = std.Target; + +// TODO this is hard-coded until self-hosted gains this information canonically +const available_libcs = [_][]const u8{ + "aarch64_be-linux-gnu", + "aarch64_be-linux-musl", + "aarch64_be-windows-gnu", + "aarch64-linux-gnu", + "aarch64-linux-musl", + "aarch64-windows-gnu", + "armeb-linux-gnueabi", + "armeb-linux-gnueabihf", + "armeb-linux-musleabi", + "armeb-linux-musleabihf", + "armeb-windows-gnu", + "arm-linux-gnueabi", + "arm-linux-gnueabihf", + "arm-linux-musleabi", + "arm-linux-musleabihf", + "arm-windows-gnu", + "i386-linux-gnu", + "i386-linux-musl", + "i386-windows-gnu", + "mips64el-linux-gnuabi64", + "mips64el-linux-gnuabin32", + "mips64el-linux-musl", + "mips64-linux-gnuabi64", + "mips64-linux-gnuabin32", + "mips64-linux-musl", + "mipsel-linux-gnu", + "mipsel-linux-musl", + "mips-linux-gnu", + "mips-linux-musl", + "powerpc64le-linux-gnu", + "powerpc64le-linux-musl", + "powerpc64-linux-gnu", + "powerpc64-linux-musl", + "powerpc-linux-gnu", + "powerpc-linux-musl", + "riscv64-linux-gnu", + "riscv64-linux-musl", + "s390x-linux-gnu", + "s390x-linux-musl", + "sparc-linux-gnu", + "sparcv9-linux-gnu", + "wasm32-freestanding-musl", + "x86_64-linux-gnu (native)", + "x86_64-linux-gnux32", + "x86_64-linux-musl", + "x86_64-windows-gnu", +}; + +// TODO this is hard-coded until self-hosted gains this information canonically +const available_glibcs = [_][]const u8{ + "2.0", + "2.1", + "2.1.1", + "2.1.2", + "2.1.3", + "2.2", + "2.2.1", + "2.2.2", + "2.2.3", + "2.2.4", + "2.2.5", + "2.2.6", + "2.3", + "2.3.2", + "2.3.3", + "2.3.4", + "2.4", + "2.5", + "2.6", + "2.7", + "2.8", + "2.9", + "2.10", + "2.11", + "2.12", + "2.13", + "2.14", + "2.15", + "2.16", + "2.17", + "2.18", + "2.19", + "2.22", + "2.23", + "2.24", + "2.25", + "2.26", + "2.27", + "2.28", + "2.29", + "2.30", +}; + +pub fn cmdTargets( + allocator: *Allocator, + args: []const []const u8, + stdout: *io.OutStream(fs.File.WriteError), + native_target: Target, +) !void { + const BOS = io.BufferedOutStream(fs.File.WriteError); + var bos = BOS.init(stdout); + var jws = std.json.WriteStream(BOS.Stream, 6).init(&bos.stream); + + try jws.beginObject(); + + try jws.objectField("arch"); + try jws.beginObject(); + { + inline for (@typeInfo(Target.Arch).Union.fields) |field| { + try jws.objectField(field.name); + if (field.field_type == void) { + try jws.emitNull(); + } else { + try jws.emitString(@typeName(field.field_type)); + } + } + } + try jws.endObject(); + + try jws.objectField("subArch"); + try jws.beginObject(); + const sub_arch_list = [_]type{ + Target.Arch.Arm32, + Target.Arch.Arm64, + Target.Arch.Kalimba, + Target.Arch.Mips, + }; + inline for (sub_arch_list) |SubArch| { + try jws.objectField(@typeName(SubArch)); + try jws.beginArray(); + inline for (@typeInfo(SubArch).Enum.fields) |field| { + try jws.arrayElem(); + try jws.emitString(field.name); + } + try jws.endArray(); + } + try jws.endObject(); + + try jws.objectField("os"); + try jws.beginArray(); + inline for (@typeInfo(Target.Os).Enum.fields) |field| { + try jws.arrayElem(); + try jws.emitString(field.name); + } + try jws.endArray(); + + try jws.objectField("abi"); + try jws.beginArray(); + inline for (@typeInfo(Target.Abi).Enum.fields) |field| { + try jws.arrayElem(); + try jws.emitString(field.name); + } + try jws.endArray(); + + try jws.objectField("libc"); + try jws.beginArray(); + for (available_libcs) |libc| { + try jws.arrayElem(); + try jws.emitString(libc); + } + try jws.endArray(); + + try jws.objectField("glibc"); + try jws.beginArray(); + for (available_glibcs) |glibc| { + try jws.arrayElem(); + try jws.emitString(glibc); + } + try jws.endArray(); + + try jws.objectField("cpus"); + try jws.beginObject(); + inline for (@typeInfo(Target.Arch).Union.fields) |field| { + try jws.objectField(field.name); + try jws.beginObject(); + const arch = @unionInit(Target.Arch, field.name, undefined); + for (arch.allCpus()) |cpu| { + try jws.objectField(cpu.name); + try jws.beginArray(); + for (arch.allFeaturesList()) |feature, i| { + if (cpu.features.isEnabled(@intCast(u8, i))) { + try jws.arrayElem(); + try jws.emitString(feature.name); + } + } + try jws.endArray(); + } + try jws.endObject(); + } + try jws.endObject(); + + try jws.objectField("cpuFeatures"); + try jws.beginObject(); + inline for (@typeInfo(Target.Arch).Union.fields) |field| { + try jws.objectField(field.name); + try jws.beginArray(); + const arch = @unionInit(Target.Arch, field.name, undefined); + for (arch.allFeaturesList()) |feature| { + try jws.arrayElem(); + try jws.emitString(feature.name); + } + try jws.endArray(); + } + try jws.endObject(); + + try jws.objectField("native"); + try jws.beginObject(); + { + const triple = try native_target.zigTriple(allocator); + defer allocator.free(triple); + try jws.objectField("triple"); + try jws.emitString(triple); + } + try jws.objectField("arch"); + try jws.emitString(@tagName(native_target.getArch())); + try jws.objectField("os"); + try jws.emitString(@tagName(native_target.getOs())); + try jws.objectField("abi"); + try jws.emitString(@tagName(native_target.getAbi())); + try jws.objectField("cpuName"); + const cpu_features = native_target.getCpuFeatures(); + try jws.emitString(cpu_features.cpu.name); + { + try jws.objectField("cpuFeatures"); + try jws.beginArray(); + for (native_target.getArch().allFeaturesList()) |feature, i_usize| { + const index = @intCast(Target.Cpu.Feature.Set.Index, i_usize); + if (cpu_features.features.isEnabled(index)) { + try jws.arrayElem(); + try jws.emitString(feature.name); + } + } + try jws.endArray(); + } + // TODO implement native glibc version detection in self-hosted + try jws.endObject(); + + try jws.endObject(); + + try bos.stream.writeByte('\n'); + return bos.flush(); +} diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage1.zig index ec683e4ba8..961b95d481 100644 --- a/src-self-hosted/stage1.zig +++ b/src-self-hosted/stage1.zig @@ -9,9 +9,11 @@ const process = std.process; const Allocator = mem.Allocator; const ArrayList = std.ArrayList; const Buffer = std.Buffer; +const Target = std.Target; const self_hosted_main = @import("main.zig"); const errmsg = @import("errmsg.zig"); const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer; +const assert = std.debug.assert; var stderr_file: fs.File = undefined; var stderr: *io.OutStream(fs.File.WriteError) = undefined; @@ -63,6 +65,7 @@ const Error = extern enum { CacheUnavailable, PathTooLong, CCompilerCannotFindFile, + NoCCompilerInstalled, ReadingDepFile, InvalidDepFile, MissingArchitecture, @@ -80,6 +83,15 @@ const Error = extern enum { OperationAborted, BrokenPipe, NoSpaceLeft, + NotLazy, + IsAsync, + ImportOutsidePkgPath, + UnknownCpu, + UnknownSubArchitecture, + UnknownCpuFeature, + InvalidCpuFeatures, + InvalidLlvmCpuFeaturesFormat, + UnknownApplicationBinaryInterface, }; const FILE = std.c.FILE; @@ -149,7 +161,7 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void { const argc_usize = @intCast(usize, argc); var arg_i: usize = 0; while (arg_i < argc_usize) : (arg_i += 1) { - try args_list.append(std.mem.toSliceConst(u8, argv[arg_i])); + try args_list.append(mem.toSliceConst(u8, argv[arg_i])); } stdout = &std.io.getStdOut().outStream().stream; @@ -527,3 +539,294 @@ export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usiz node.activate(); node.context.maybeRefresh(); } + +fn cpuFeaturesFromLLVM( + arch: Target.Arch, + llvm_cpu_name_z: ?[*:0]const u8, + llvm_cpu_features_opt: ?[*:0]const u8, +) !Target.CpuFeatures { + var result = arch.getBaselineCpuFeatures(); + + if (llvm_cpu_name_z) |cpu_name_z| { + const llvm_cpu_name = mem.toSliceConst(u8, cpu_name_z); + + for (arch.allCpus()) |cpu| { + const this_llvm_name = cpu.llvm_name orelse continue; + if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) { + // Here we use the non-dependencies-populated set, + // so that subtracting features later in this function + // affect the prepopulated set. + result = Target.CpuFeatures{ + .cpu = cpu, + .features = cpu.features, + }; + break; + } + } + } + + const all_features = arch.allFeaturesList(); + + if (llvm_cpu_features_opt) |llvm_cpu_features| { + var it = mem.tokenize(mem.toSliceConst(u8, llvm_cpu_features), ","); + while (it.next()) |decorated_llvm_feat| { + var op: enum { + add, + sub, + } = undefined; + var llvm_feat: []const u8 = undefined; + if (mem.startsWith(u8, decorated_llvm_feat, "+")) { + op = .add; + llvm_feat = decorated_llvm_feat[1..]; + } else if (mem.startsWith(u8, decorated_llvm_feat, "-")) { + op = .sub; + llvm_feat = decorated_llvm_feat[1..]; + } else { + return error.InvalidLlvmCpuFeaturesFormat; + } + for (all_features) |feature, index_usize| { + const this_llvm_name = feature.llvm_name orelse continue; + if (mem.eql(u8, llvm_feat, this_llvm_name)) { + const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); + switch (op) { + .add => result.features.addFeature(index), + .sub => result.features.removeFeature(index), + } + break; + } + } + } + } + + result.features.populateDependencies(all_features); + return result; +} + +// ABI warning +export fn stage2_cmd_targets(zig_triple: [*:0]const u8) c_int { + cmdTargets(zig_triple) catch |err| { + std.debug.warn("unable to list targets: {}\n", .{@errorName(err)}); + return -1; + }; + return 0; +} + +fn cmdTargets(zig_triple: [*:0]const u8) !void { + var target = try Target.parse(mem.toSliceConst(u8, zig_triple)); + target.Cross.cpu_features = blk: { + const llvm = @import("llvm.zig"); + const llvm_cpu_name = llvm.GetHostCPUName(); + const llvm_cpu_features = llvm.GetNativeFeatures(); + break :blk try cpuFeaturesFromLLVM(target.Cross.arch, llvm_cpu_name, llvm_cpu_features); + }; + return @import("print_targets.zig").cmdTargets( + std.heap.c_allocator, + &[0][]u8{}, + &std.io.getStdOut().outStream().stream, + target, + ); +} + +const Stage2CpuFeatures = struct { + allocator: *mem.Allocator, + cpu_features: Target.CpuFeatures, + + llvm_features_str: ?[*:0]const u8, + + builtin_str: [:0]const u8, + cache_hash: [:0]const u8, + + const Self = @This(); + + fn createFromNative(allocator: *mem.Allocator) !*Self { + const arch = Target.current.getArch(); + const llvm = @import("llvm.zig"); + const llvm_cpu_name = llvm.GetHostCPUName(); + const llvm_cpu_features = llvm.GetNativeFeatures(); + const cpu_features = try cpuFeaturesFromLLVM(arch, llvm_cpu_name, llvm_cpu_features); + return createFromCpuFeatures(allocator, arch, cpu_features); + } + + fn createFromCpuFeatures( + allocator: *mem.Allocator, + arch: Target.Arch, + cpu_features: Target.CpuFeatures, + ) !*Self { + const self = try allocator.create(Self); + errdefer allocator.destroy(self); + + const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{}", .{ + cpu_features.cpu.name, + cpu_features.features.asBytes(), + }); + errdefer allocator.free(cache_hash); + + const generic_arch_name = arch.genericName(); + var builtin_str_buffer = try std.Buffer.allocPrint(allocator, + \\CpuFeatures{{ + \\ .cpu = &Target.{}.cpu.{}, + \\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{ + \\ + , .{ + generic_arch_name, + cpu_features.cpu.name, + generic_arch_name, + generic_arch_name, + }); + defer builtin_str_buffer.deinit(); + + var llvm_features_buffer = try std.Buffer.initSize(allocator, 0); + defer llvm_features_buffer.deinit(); + + for (arch.allFeaturesList()) |feature, index_usize| { + const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); + const is_enabled = cpu_features.features.isEnabled(index); + + if (feature.llvm_name) |llvm_name| { + const plus_or_minus = "-+"[@boolToInt(is_enabled)]; + try llvm_features_buffer.appendByte(plus_or_minus); + try llvm_features_buffer.append(llvm_name); + try llvm_features_buffer.append(","); + } + + if (is_enabled) { + // TODO some kind of "zig identifier escape" function rather than + // unconditionally using @"" syntax + try builtin_str_buffer.append(" .@\""); + try builtin_str_buffer.append(feature.name); + try builtin_str_buffer.append("\",\n"); + } + } + + try builtin_str_buffer.append( + \\ }), + \\}; + \\ + ); + + assert(mem.endsWith(u8, llvm_features_buffer.toSliceConst(), ",")); + llvm_features_buffer.shrink(llvm_features_buffer.len() - 1); + + self.* = Self{ + .allocator = allocator, + .cpu_features = cpu_features, + .llvm_features_str = llvm_features_buffer.toOwnedSlice().ptr, + .builtin_str = builtin_str_buffer.toOwnedSlice(), + .cache_hash = cache_hash, + }; + return self; + } + + fn destroy(self: *Self) void { + self.allocator.free(self.cache_hash); + self.allocator.free(self.builtin_str); + // TODO if (self.llvm_features_str) |llvm_features_str| self.allocator.free(llvm_features_str); + self.allocator.destroy(self); + } +}; + +// ABI warning +export fn stage2_cpu_features_parse( + result: **Stage2CpuFeatures, + zig_triple: ?[*:0]const u8, + cpu_name: ?[*:0]const u8, + cpu_features: ?[*:0]const u8, +) Error { + result.* = stage2ParseCpuFeatures(zig_triple, cpu_name, cpu_features) catch |err| switch (err) { + error.OutOfMemory => return .OutOfMemory, + error.UnknownArchitecture => return .UnknownArchitecture, + error.UnknownSubArchitecture => return .UnknownSubArchitecture, + error.UnknownOperatingSystem => return .UnknownOperatingSystem, + error.UnknownApplicationBinaryInterface => return .UnknownApplicationBinaryInterface, + error.MissingOperatingSystem => return .MissingOperatingSystem, + error.MissingArchitecture => return .MissingArchitecture, + error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat, + error.InvalidCpuFeatures => return .InvalidCpuFeatures, + }; + return .None; +} + +fn stage2ParseCpuFeatures( + zig_triple_oz: ?[*:0]const u8, + cpu_name_oz: ?[*:0]const u8, + cpu_features_oz: ?[*:0]const u8, +) !*Stage2CpuFeatures { + const zig_triple_z = zig_triple_oz orelse return Stage2CpuFeatures.createFromNative(std.heap.c_allocator); + const target = try Target.parse(mem.toSliceConst(u8, zig_triple_z)); + const arch = target.Cross.arch; + + const cpu = if (cpu_name_oz) |cpu_name_z| blk: { + const cpu_name = mem.toSliceConst(u8, cpu_name_z); + break :blk arch.parseCpu(cpu_name) catch |err| switch (err) { + error.UnknownCpu => { + std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{ + cpu_name, + @tagName(arch), + }); + for (arch.allCpus()) |cpu| { + std.debug.warn(" {}\n", .{cpu.name}); + } + process.exit(1); + }, + else => |e| return e, + }; + } else target.Cross.cpu_features.cpu; + + var set = if (cpu_features_oz) |cpu_features_z| blk: { + const cpu_features = mem.toSliceConst(u8, cpu_features_z); + break :blk arch.parseCpuFeatureSet(cpu, cpu_features) catch |err| switch (err) { + error.UnknownCpuFeature => { + std.debug.warn( + \\Unknown CPU features specified. + \\Available CPU features for architecture '{}': + \\ + , .{@tagName(arch)}); + for (arch.allFeaturesList()) |feature| { + std.debug.warn(" {}\n", .{feature.name}); + } + process.exit(1); + }, + else => |e| return e, + }; + } else cpu.features; + + if (arch.subArchFeature()) |index| { + set.addFeature(index); + } + set.populateDependencies(arch.allFeaturesList()); + + return Stage2CpuFeatures.createFromCpuFeatures(std.heap.c_allocator, arch, .{ + .cpu = cpu, + .features = set, + }); +} + +// ABI warning +export fn stage2_cpu_features_get_cache_hash( + cpu_features: *const Stage2CpuFeatures, + ptr: *[*:0]const u8, + len: *usize, +) void { + ptr.* = cpu_features.cache_hash.ptr; + len.* = cpu_features.cache_hash.len; +} + +// ABI warning +export fn stage2_cpu_features_get_builtin_str( + cpu_features: *const Stage2CpuFeatures, + ptr: *[*:0]const u8, + len: *usize, +) void { + ptr.* = cpu_features.builtin_str.ptr; + len.* = cpu_features.builtin_str.len; +} + +// ABI warning +export fn stage2_cpu_features_get_llvm_cpu(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 { + return if (cpu_features.cpu_features.cpu.llvm_name) |s| s.ptr else null; +} + +// ABI warning +export fn stage2_cpu_features_get_llvm_features(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 { + return cpu_features.llvm_features_str; +} diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index b45d0f61f0..18c4cafbe3 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -289,8 +289,7 @@ pub fn translate( tree.errors = ast.Tree.ErrorList.init(arena); tree.root_node = try arena.create(ast.Node.Root); - tree.root_node.* = ast.Node.Root{ - .base = ast.Node{ .id = ast.Node.Id.Root }, + tree.root_node.* = .{ .decls = ast.Node.Root.DeclList.init(arena), // initialized with the eof token at the end .eof_token = undefined, @@ -440,7 +439,6 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { .PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern", .{}), .Auto => unreachable, // Not legal on functions .Register => unreachable, // Not legal on functions - else => unreachable, }, }; @@ -487,6 +485,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { block_scope.block_node = block_node; var it = proto_node.params.iterator(0); + var param_id: c_uint = 0; while (it.next()) |p| { const param = @fieldParentPtr(ast.Node.ParamDecl, "base", p.*); const param_name = if (param.name_token) |name_tok| @@ -500,18 +499,27 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { const mangled_param_name = try block_scope.makeMangledName(c, param_name); + const c_param = ZigClangFunctionDecl_getParamDecl(fn_decl, param_id); + const qual_type = ZigClangParmVarDecl_getOriginalType(c_param); + const is_const = ZigClangQualType_isConstQualified(qual_type); + const arg_name = blk: { - const bare_arg_name = try std.fmt.allocPrint(c.a(), "arg_{}", .{mangled_param_name}); + const param_prefix = if (is_const) "" else "arg_"; + const bare_arg_name = try std.fmt.allocPrint(c.a(), "{}{}", .{param_prefix, mangled_param_name}); break :blk try block_scope.makeMangledName(c, bare_arg_name); }; - const node = try transCreateNodeVarDecl(c, false, false, mangled_param_name); - node.eq_token = try appendToken(c, .Equal, "="); - node.init_node = try transCreateNodeIdentifier(c, arg_name); - node.semicolon_token = try appendToken(c, .Semicolon, ";"); - try block_node.statements.push(&node.base); - param.name_token = try appendIdentifier(c, arg_name); - _ = try appendToken(c, .Colon, ":"); + if (!is_const) { + const node = try transCreateNodeVarDecl(c, false, false, mangled_param_name); + node.eq_token = try appendToken(c, .Equal, "="); + node.init_node = try transCreateNodeIdentifier(c, arg_name); + node.semicolon_token = try appendToken(c, .Semicolon, ";"); + try block_node.statements.push(&node.base); + param.name_token = try appendIdentifier(c, arg_name); + _ = try appendToken(c, .Colon, ":"); + } + + param_id += 1; } transCompoundStmtInline(rp, &block_scope.base, @ptrCast(*const ZigClangCompoundStmt, body_stmt), block_node) catch |err| switch (err) { @@ -877,25 +885,23 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No // types, while that's not ISO-C compliant many compilers allow this and // default to the usual integer type used for all the enums. - // TODO only emit this tag type if the enum tag type is not the default. - // I don't know what the default is, need to figure out how clang is deciding. - // it appears to at least be different across gcc/msvc - if (int_type.ptr != null and - !isCBuiltinType(int_type, .UInt) and - !isCBuiltinType(int_type, .Int)) - { - _ = try appendToken(c, .LParen, "("); - container_node.init_arg_expr = .{ - .Type = transQualType(rp, int_type, enum_loc) catch |err| switch (err) { + // default to c_int since msvc and gcc default to different types + _ = try appendToken(c, .LParen, "("); + container_node.init_arg_expr = .{ + .Type = if (int_type.ptr != null and + !isCBuiltinType(int_type, .UInt) and + !isCBuiltinType(int_type, .Int)) + transQualType(rp, int_type, enum_loc) catch |err| switch (err) { error.UnsupportedType => { try failDecl(c, enum_loc, name, "unable to translate enum tag type", .{}); return null; }, else => |e| return e, - }, - }; - _ = try appendToken(c, .RParen, ")"); - } + } + else + try transCreateNodeIdentifier(c, "c_int"), + }; + _ = try appendToken(c, .RParen, ")"); container_node.lbrace_token = try appendToken(c, .LBrace, "{"); @@ -953,6 +959,19 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No tld_node.semicolon_token = try appendToken(c, .Semicolon, ";"); try addTopLevelDecl(c, field_name, &tld_node.base); } + // make non exhaustive + const field_node = try c.a().create(ast.Node.ContainerField); + field_node.* = .{ + .doc_comments = null, + .comptime_token = null, + .name_token = try appendIdentifier(c, "_"), + .type_expr = null, + .value_expr = null, + .align_expr = null, + }; + + try container_node.fields_and_decls.push(&field_node.base); + _ = try appendToken(c, .Comma, ","); container_node.rbrace_token = try appendToken(c, .RBrace, "}"); break :blk &container_node.base; @@ -1231,18 +1250,6 @@ fn transBinaryOperator( op_id = .BitOr; op_token = try appendToken(rp.c, .Pipe, "|"); }, - .Assign, - .MulAssign, - .DivAssign, - .RemAssign, - .AddAssign, - .SubAssign, - .ShlAssign, - .ShrAssign, - .AndAssign, - .XorAssign, - .OrAssign, - => unreachable, else => unreachable, } @@ -1678,7 +1685,6 @@ fn transStringLiteral( "TODO: support string literal kind {}", .{kind}, ), - else => unreachable, } } @@ -1986,7 +1992,8 @@ fn transInitListExprArray( const arr_type = ZigClangType_getAsArrayTypeUnsafe(ty); const child_qt = ZigClangArrayType_getElementType(arr_type); const init_count = ZigClangInitListExpr_getNumInits(expr); - const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, ty); + assert(ZigClangType_isConstantArrayType(@ptrCast(*const ZigClangType, arr_type))); + const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, arr_type); const size_ap_int = ZigClangConstantArrayType_getSize(const_arr_ty); const all_count = ZigClangAPInt_getLimitedValue(size_ap_int, math.maxInt(usize)); const leftover_count = all_count - init_count; @@ -2206,6 +2213,19 @@ fn transDoWhileLoop( .id = .Loop, }; + // if (!cond) break; + const if_node = try transCreateNodeIf(rp.c); + var cond_scope = Scope{ + .parent = scope, + .id = .Condition, + }; + const prefix_op = try transCreateNodePrefixOp(rp.c, .BoolNot, .Bang, "!"); + prefix_op.rhs = try transBoolExpr(rp, &cond_scope, @ptrCast(*const ZigClangExpr, ZigClangDoStmt_getCond(stmt)), .used, .r_value, true); + _ = try appendToken(rp.c, .RParen, ")"); + if_node.condition = &prefix_op.base; + if_node.body = &(try transCreateNodeBreak(rp.c, null)).base; + _ = try appendToken(rp.c, .Semicolon, ";"); + const body_node = if (ZigClangStmt_getStmtClass(ZigClangDoStmt_getBody(stmt)) == .CompoundStmtClass) blk: { // there's already a block in C, so we'll append our condition to it. // c: do { @@ -2217,10 +2237,7 @@ fn transDoWhileLoop( // zig: b; // zig: if (!cond) break; // zig: } - const body = (try transStmt(rp, &loop_scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)).cast(ast.Node.Block).?; - // if this is used as an expression in Zig it needs to be immediately followed by a semicolon - _ = try appendToken(rp.c, .Semicolon, ";"); - break :blk body; + break :blk (try transStmt(rp, &loop_scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)).cast(ast.Node.Block).?; } else blk: { // the C statement is without a block, so we need to create a block to contain it. // c: do @@ -2236,19 +2253,6 @@ fn transDoWhileLoop( break :blk block; }; - // if (!cond) break; - const if_node = try transCreateNodeIf(rp.c); - var cond_scope = Scope{ - .parent = scope, - .id = .Condition, - }; - const prefix_op = try transCreateNodePrefixOp(rp.c, .BoolNot, .Bang, "!"); - prefix_op.rhs = try transBoolExpr(rp, &cond_scope, @ptrCast(*const ZigClangExpr, ZigClangDoStmt_getCond(stmt)), .used, .r_value, true); - _ = try appendToken(rp.c, .RParen, ")"); - if_node.condition = &prefix_op.base; - if_node.body = &(try transCreateNodeBreak(rp.c, null)).base; - _ = try appendToken(rp.c, .Semicolon, ";"); - try body_node.statements.push(&if_node.base); if (new) body_node.rbrace = try appendToken(rp.c, .RBrace, "}"); @@ -4783,8 +4787,7 @@ fn appendIdentifier(c: *Context, name: []const u8) !ast.TokenIndex { fn transCreateNodeIdentifier(c: *Context, name: []const u8) !*ast.Node { const token_index = try appendIdentifier(c, name); const identifier = try c.a().create(ast.Node.Identifier); - identifier.* = ast.Node.Identifier{ - .base = ast.Node{ .id = ast.Node.Id.Identifier }, + identifier.* = .{ .token = token_index, }; return &identifier.base; @@ -4923,8 +4926,7 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u const token_index = try appendToken(c, .Keyword_var, "var"); const identifier = try c.a().create(ast.Node.Identifier); - identifier.* = ast.Node.Identifier{ - .base = ast.Node{ .id = ast.Node.Id.Identifier }, + identifier.* = .{ .token = token_index, }; diff --git a/src/all_types.hpp b/src/all_types.hpp index 49cbf38d03..993a693d88 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -33,12 +33,15 @@ struct BuiltinFnEntry; struct TypeStructField; struct CodeGen; struct ZigValue; -struct IrInstruction; -struct IrInstructionCast; -struct IrInstructionAllocaGen; -struct IrInstructionCallGen; -struct IrInstructionAwaitGen; -struct IrBasicBlock; +struct IrInst; +struct IrInstSrc; +struct IrInstGen; +struct IrInstGenCast; +struct IrInstGenAlloca; +struct IrInstGenCall; +struct IrInstGenAwait; +struct IrBasicBlockSrc; +struct IrBasicBlockGen; struct ScopeDecls; struct ZigWindowsSDK; struct Tld; @@ -50,6 +53,7 @@ struct ResultLocPeerParent; struct ResultLocBitCast; struct ResultLocCast; struct ResultLocReturn; +struct IrExecutableGen; enum PtrLen { PtrLenUnknown, @@ -97,8 +101,8 @@ enum X64CABIClass { X64CABIClass_SSE, }; -struct IrExecutable { - ZigList basic_block_list; +struct IrExecutableSrc { + ZigList basic_block_list; Buf *name; ZigFn *name_fn; size_t mem_slot_count; @@ -108,8 +112,7 @@ struct IrExecutable { ZigFn *fn_entry; Buf *c_import_buf; AstNode *source_node; - IrExecutable *parent_exec; - IrExecutable *source_exec; + IrExecutableGen *parent_exec; IrAnalyze *analysis; Scope *begin_scope; ErrorMsg *first_err_trace_msg; @@ -124,6 +127,32 @@ struct IrExecutable { void src(); }; +struct IrExecutableGen { + ZigList basic_block_list; + Buf *name; + ZigFn *name_fn; + size_t mem_slot_count; + size_t next_debug_id; + size_t *backward_branch_count; + size_t *backward_branch_quota; + ZigFn *fn_entry; + Buf *c_import_buf; + AstNode *source_node; + IrExecutableGen *parent_exec; + IrExecutableSrc *source_exec; + Scope *begin_scope; + ErrorMsg *first_err_trace_msg; + ZigList tld_list; + + bool is_inline; + bool is_generic_instantiation; + bool need_err_code_spill; + + // This is a function for use in the debugger to print + // the source location. + void src(); +}; + enum OutType { OutTypeUnknown, OutTypeExe, @@ -287,7 +316,7 @@ struct ConstErrValue { struct ConstBoundFnValue { ZigFn *fn; - IrInstruction *first_arg; + IrInstGen *first_arg; }; struct ConstArgTuple { @@ -350,14 +379,14 @@ struct LazyValueAlignOf { LazyValue base; IrAnalyze *ira; - IrInstruction *target_type; + IrInstGen *target_type; }; struct LazyValueSizeOf { LazyValue base; IrAnalyze *ira; - IrInstruction *target_type; + IrInstGen *target_type; bool bit_size; }; @@ -366,9 +395,9 @@ struct LazyValueSliceType { LazyValue base; IrAnalyze *ira; - IrInstruction *sentinel; // can be null - IrInstruction *elem_type; - IrInstruction *align_inst; // can be null + IrInstGen *sentinel; // can be null + IrInstGen *elem_type; + IrInstGen *align_inst; // can be null bool is_const; bool is_volatile; @@ -379,8 +408,8 @@ struct LazyValueArrayType { LazyValue base; IrAnalyze *ira; - IrInstruction *sentinel; // can be null - IrInstruction *elem_type; + IrInstGen *sentinel; // can be null + IrInstGen *elem_type; uint64_t length; }; @@ -388,9 +417,9 @@ struct LazyValuePtrType { LazyValue base; IrAnalyze *ira; - IrInstruction *sentinel; // can be null - IrInstruction *elem_type; - IrInstruction *align_inst; // can be null + IrInstGen *sentinel; // can be null + IrInstGen *elem_type; + IrInstGen *align_inst; // can be null PtrLen ptr_len; uint32_t bit_offset_in_host; @@ -405,7 +434,7 @@ struct LazyValueOptType { LazyValue base; IrAnalyze *ira; - IrInstruction *payload_type; + IrInstGen *payload_type; }; struct LazyValueFnType { @@ -413,9 +442,9 @@ struct LazyValueFnType { IrAnalyze *ira; AstNode *proto_node; - IrInstruction **param_types; - IrInstruction *align_inst; // can be null - IrInstruction *return_type; + IrInstGen **param_types; + IrInstGen *align_inst; // can be null + IrInstGen *return_type; CallingConvention cc; bool is_generic; @@ -425,8 +454,8 @@ struct LazyValueErrUnionType { LazyValue base; IrAnalyze *ira; - IrInstruction *err_set_type; - IrInstruction *payload_type; + IrInstGen *err_set_type; + IrInstGen *payload_type; Buf *type_name; }; @@ -1389,6 +1418,7 @@ struct ZigTypeEnum { ContainerLayout layout; ResolveStatus resolve_status; + bool non_exhaustive; bool resolve_loop_flag; }; @@ -1605,19 +1635,19 @@ struct ZigFn { // in the case of async functions this is the implicit return type according to the // zig source code, not according to zig ir ZigType *src_implicit_return_type; - IrExecutable *ir_executable; - IrExecutable analyzed_executable; + IrExecutableSrc *ir_executable; + IrExecutableGen analyzed_executable; size_t prealloc_bbc; size_t prealloc_backward_branch_quota; AstNode **param_source_nodes; Buf **param_names; - IrInstruction *err_code_spill; + IrInstGen *err_code_spill; AstNode *assumed_non_async; AstNode *fn_no_inline_set_node; AstNode *fn_static_eval_set_node; - ZigList alloca_gen_list; + ZigList alloca_gen_list; ZigList variable_list; Buf *section_name; @@ -1629,8 +1659,8 @@ struct ZigFn { AstNode *non_async_node; ZigList export_list; - ZigList call_list; - ZigList await_list; + ZigList call_list; + ZigList await_list; LLVMValueRef valgrind_client_request_array; @@ -2101,8 +2131,9 @@ struct CodeGen { Buf *zig_c_headers_dir; // Cannot be overridden; derived from zig_lib_dir. Buf *zig_std_special_dir; // Cannot be overridden; derived from zig_lib_dir. - IrInstruction *invalid_instruction; - IrInstruction *unreach_instruction; + IrInstSrc *invalid_inst_src; + IrInstGen *invalid_inst_gen; + IrInstGen *unreach_instruction; ZigValue panic_msg_vals[PanicMsgIdCount]; @@ -2147,6 +2178,7 @@ struct CodeGen { bool verbose_llvm_ir; bool verbose_cimport; bool verbose_cc; + bool verbose_llvm_cpu_features; bool error_during_imports; bool generate_error_name_table; bool enable_cache; // mutually exclusive with output_dir @@ -2225,8 +2257,8 @@ struct ZigVar { ZigValue *const_value; ZigType *var_type; LLVMValueRef value_ref; - IrInstruction *is_comptime; - IrInstruction *ptr_instruction; + IrInstSrc *is_comptime; + IrInstGen *ptr_instruction; // which node is the declaration of the variable AstNode *decl_node; ZigLLVMDILocalVariable *di_loc_var; @@ -2234,7 +2266,7 @@ struct ZigVar { Scope *parent_scope; Scope *child_scope; LLVMValueRef param_value_ref; - IrExecutable *owner_exec; + IrExecutableSrc *owner_exec; Buf *section_name; @@ -2325,11 +2357,11 @@ struct ScopeBlock { Scope base; Buf *name; - IrBasicBlock *end_block; - IrInstruction *is_comptime; + IrBasicBlockSrc *end_block; + IrInstSrc *is_comptime; ResultLocPeerParent *peer_parent; - ZigList *incoming_values; - ZigList *incoming_blocks; + ZigList *incoming_values; + ZigList *incoming_blocks; AstNode *safety_set_node; AstNode *fast_math_set_node; @@ -2380,11 +2412,11 @@ struct ScopeLoop { LVal lval; Buf *name; - IrBasicBlock *break_block; - IrBasicBlock *continue_block; - IrInstruction *is_comptime; - ZigList *incoming_values; - ZigList *incoming_blocks; + IrBasicBlockSrc *break_block; + IrBasicBlockSrc *continue_block; + IrInstSrc *is_comptime; + ZigList *incoming_values; + ZigList *incoming_blocks; ResultLocPeerParent *peer_parent; ScopeExpr *spill_scope; }; @@ -2395,7 +2427,7 @@ struct ScopeLoop { struct ScopeRuntime { Scope base; - IrInstruction *is_comptime; + IrInstSrc *is_comptime; }; // This scope is created for a suspend block in order to have labeled @@ -2474,319 +2506,450 @@ enum AtomicRmwOp { // to another basic block. // Phi instructions must be first in a basic block. // The last instruction in a basic block must be of type unreachable. -struct IrBasicBlock { - ZigList instruction_list; - IrBasicBlock *other; +struct IrBasicBlockSrc { + ZigList instruction_list; + IrBasicBlockGen *child; Scope *scope; const char *name_hint; - size_t debug_id; - size_t ref_count; - // index into the basic block list - size_t index; + IrInst *suspend_instruction_ref; + + uint32_t ref_count; + uint32_t index; // index into the basic block list + + uint32_t debug_id; + bool suspended; + bool in_resume_stack; +}; + +struct IrBasicBlockGen { + ZigList instruction_list; + IrBasicBlockSrc *parent; + Scope *scope; + const char *name_hint; + uint32_t index; // index into the basic block list + uint32_t ref_count; LLVMBasicBlockRef llvm_block; LLVMBasicBlockRef llvm_exit_block; // The instruction that referenced this basic block and caused us to // analyze the basic block. If the same instruction wants us to emit // the same basic block, then we re-generate it instead of saving it. - IrInstruction *ref_instruction; + IrInst *ref_instruction; // When this is non-null, a branch to this basic block is only allowed // if the branch is comptime. The instruction points to the reason // the basic block must be comptime. - IrInstruction *must_be_comptime_source_instr; - IrInstruction *suspend_instruction_ref; + IrInst *must_be_comptime_source_instr; + + uint32_t debug_id; bool already_appended; - bool suspended; - bool in_resume_stack; }; -// These instructions are in transition to having "pass 1" instructions -// and "pass 2" instructions. The pass 1 instructions are suffixed with Src -// and pass 2 are suffixed with Gen. -// Once all instructions are separated in this way, they'll have different -// base types for better type safety. // Src instructions are generated by ir_gen_* functions in ir.cpp from AST. // ir_analyze_* functions consume Src instructions and produce Gen instructions. -// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR. // Src instructions do not have type information; Gen instructions do. -enum IrInstructionId { - IrInstructionIdInvalid, - IrInstructionIdDeclVarSrc, - IrInstructionIdDeclVarGen, - IrInstructionIdBr, - IrInstructionIdCondBr, - IrInstructionIdSwitchBr, - IrInstructionIdSwitchVar, - IrInstructionIdSwitchElseVar, - IrInstructionIdSwitchTarget, - IrInstructionIdPhi, - IrInstructionIdUnOp, - IrInstructionIdBinOp, - IrInstructionIdMergeErrSets, - IrInstructionIdLoadPtr, - IrInstructionIdLoadPtrGen, - IrInstructionIdStorePtr, - IrInstructionIdVectorStoreElem, - IrInstructionIdFieldPtr, - IrInstructionIdStructFieldPtr, - IrInstructionIdUnionFieldPtr, - IrInstructionIdElemPtr, - IrInstructionIdVarPtr, - IrInstructionIdReturnPtr, - IrInstructionIdCallSrc, - IrInstructionIdCallSrcArgs, - IrInstructionIdCallExtra, - IrInstructionIdCallGen, - IrInstructionIdConst, - IrInstructionIdReturn, - IrInstructionIdCast, - IrInstructionIdResizeSlice, - IrInstructionIdContainerInitList, - IrInstructionIdContainerInitFields, - IrInstructionIdUnreachable, - IrInstructionIdTypeOf, - IrInstructionIdSetCold, - IrInstructionIdSetRuntimeSafety, - IrInstructionIdSetFloatMode, - IrInstructionIdArrayType, - IrInstructionIdAnyFrameType, - IrInstructionIdSliceType, - IrInstructionIdAsmSrc, - IrInstructionIdAsmGen, - IrInstructionIdSizeOf, - IrInstructionIdTestNonNull, - IrInstructionIdOptionalUnwrapPtr, - IrInstructionIdOptionalWrap, - IrInstructionIdUnionTag, - IrInstructionIdClz, - IrInstructionIdCtz, - IrInstructionIdPopCount, - IrInstructionIdBswap, - IrInstructionIdBitReverse, - IrInstructionIdImport, - IrInstructionIdCImport, - IrInstructionIdCInclude, - IrInstructionIdCDefine, - IrInstructionIdCUndef, - IrInstructionIdRef, - IrInstructionIdRefGen, - IrInstructionIdCompileErr, - IrInstructionIdCompileLog, - IrInstructionIdErrName, - IrInstructionIdEmbedFile, - IrInstructionIdCmpxchgSrc, - IrInstructionIdCmpxchgGen, - IrInstructionIdFence, - IrInstructionIdTruncate, - IrInstructionIdIntCast, - IrInstructionIdFloatCast, - IrInstructionIdIntToFloat, - IrInstructionIdFloatToInt, - IrInstructionIdBoolToInt, - IrInstructionIdIntType, - IrInstructionIdVectorType, - IrInstructionIdShuffleVector, - IrInstructionIdSplatSrc, - IrInstructionIdSplatGen, - IrInstructionIdBoolNot, - IrInstructionIdMemset, - IrInstructionIdMemcpy, - IrInstructionIdSliceSrc, - IrInstructionIdSliceGen, - IrInstructionIdMemberCount, - IrInstructionIdMemberType, - IrInstructionIdMemberName, - IrInstructionIdBreakpoint, - IrInstructionIdReturnAddress, - IrInstructionIdFrameAddress, - IrInstructionIdFrameHandle, - IrInstructionIdFrameType, - IrInstructionIdFrameSizeSrc, - IrInstructionIdFrameSizeGen, - IrInstructionIdAlignOf, - IrInstructionIdOverflowOp, - IrInstructionIdTestErrSrc, - IrInstructionIdTestErrGen, - IrInstructionIdMulAdd, - IrInstructionIdFloatOp, - IrInstructionIdUnwrapErrCode, - IrInstructionIdUnwrapErrPayload, - IrInstructionIdErrWrapCode, - IrInstructionIdErrWrapPayload, - IrInstructionIdFnProto, - IrInstructionIdTestComptime, - IrInstructionIdPtrCastSrc, - IrInstructionIdPtrCastGen, - IrInstructionIdBitCastSrc, - IrInstructionIdBitCastGen, - IrInstructionIdWidenOrShorten, - IrInstructionIdIntToPtr, - IrInstructionIdPtrToInt, - IrInstructionIdIntToEnum, - IrInstructionIdEnumToInt, - IrInstructionIdIntToErr, - IrInstructionIdErrToInt, - IrInstructionIdCheckSwitchProngs, - IrInstructionIdCheckStatementIsVoid, - IrInstructionIdTypeName, - IrInstructionIdDeclRef, - IrInstructionIdPanic, - IrInstructionIdTagName, - IrInstructionIdTagType, - IrInstructionIdFieldParentPtr, - IrInstructionIdByteOffsetOf, - IrInstructionIdBitOffsetOf, - IrInstructionIdTypeInfo, - IrInstructionIdType, - IrInstructionIdHasField, - IrInstructionIdTypeId, - IrInstructionIdSetEvalBranchQuota, - IrInstructionIdPtrType, - IrInstructionIdAlignCast, - IrInstructionIdImplicitCast, - IrInstructionIdResolveResult, - IrInstructionIdResetResult, - IrInstructionIdOpaqueType, - IrInstructionIdSetAlignStack, - IrInstructionIdArgType, - IrInstructionIdExport, - IrInstructionIdErrorReturnTrace, - IrInstructionIdErrorUnion, - IrInstructionIdAtomicRmw, - IrInstructionIdAtomicLoad, - IrInstructionIdAtomicStore, - IrInstructionIdSaveErrRetAddr, - IrInstructionIdAddImplicitReturnType, - IrInstructionIdErrSetCast, - IrInstructionIdToBytes, - IrInstructionIdFromBytes, - IrInstructionIdCheckRuntimeScope, - IrInstructionIdVectorToArray, - IrInstructionIdArrayToVector, - IrInstructionIdAssertZero, - IrInstructionIdAssertNonNull, - IrInstructionIdHasDecl, - IrInstructionIdUndeclaredIdent, - IrInstructionIdAllocaSrc, - IrInstructionIdAllocaGen, - IrInstructionIdEndExpr, - IrInstructionIdPtrOfArrayToSlice, - IrInstructionIdUnionInitNamedField, - IrInstructionIdSuspendBegin, - IrInstructionIdSuspendFinish, - IrInstructionIdAwaitSrc, - IrInstructionIdAwaitGen, - IrInstructionIdResume, - IrInstructionIdSpillBegin, - IrInstructionIdSpillEnd, - IrInstructionIdVectorExtractElem, +enum IrInstSrcId { + IrInstSrcIdInvalid, + IrInstSrcIdDeclVar, + IrInstSrcIdBr, + IrInstSrcIdCondBr, + IrInstSrcIdSwitchBr, + IrInstSrcIdSwitchVar, + IrInstSrcIdSwitchElseVar, + IrInstSrcIdSwitchTarget, + IrInstSrcIdPhi, + IrInstSrcIdUnOp, + IrInstSrcIdBinOp, + IrInstSrcIdMergeErrSets, + IrInstSrcIdLoadPtr, + IrInstSrcIdStorePtr, + IrInstSrcIdFieldPtr, + IrInstSrcIdElemPtr, + IrInstSrcIdVarPtr, + IrInstSrcIdCall, + IrInstSrcIdCallArgs, + IrInstSrcIdCallExtra, + IrInstSrcIdConst, + IrInstSrcIdReturn, + IrInstSrcIdContainerInitList, + IrInstSrcIdContainerInitFields, + IrInstSrcIdUnreachable, + IrInstSrcIdTypeOf, + IrInstSrcIdSetCold, + IrInstSrcIdSetRuntimeSafety, + IrInstSrcIdSetFloatMode, + IrInstSrcIdArrayType, + IrInstSrcIdAnyFrameType, + IrInstSrcIdSliceType, + IrInstSrcIdAsm, + IrInstSrcIdSizeOf, + IrInstSrcIdTestNonNull, + IrInstSrcIdOptionalUnwrapPtr, + IrInstSrcIdClz, + IrInstSrcIdCtz, + IrInstSrcIdPopCount, + IrInstSrcIdBswap, + IrInstSrcIdBitReverse, + IrInstSrcIdImport, + IrInstSrcIdCImport, + IrInstSrcIdCInclude, + IrInstSrcIdCDefine, + IrInstSrcIdCUndef, + IrInstSrcIdRef, + IrInstSrcIdCompileErr, + IrInstSrcIdCompileLog, + IrInstSrcIdErrName, + IrInstSrcIdEmbedFile, + IrInstSrcIdCmpxchg, + IrInstSrcIdFence, + IrInstSrcIdTruncate, + IrInstSrcIdIntCast, + IrInstSrcIdFloatCast, + IrInstSrcIdIntToFloat, + IrInstSrcIdFloatToInt, + IrInstSrcIdBoolToInt, + IrInstSrcIdIntType, + IrInstSrcIdVectorType, + IrInstSrcIdShuffleVector, + IrInstSrcIdSplat, + IrInstSrcIdBoolNot, + IrInstSrcIdMemset, + IrInstSrcIdMemcpy, + IrInstSrcIdSlice, + IrInstSrcIdMemberCount, + IrInstSrcIdMemberType, + IrInstSrcIdMemberName, + IrInstSrcIdBreakpoint, + IrInstSrcIdReturnAddress, + IrInstSrcIdFrameAddress, + IrInstSrcIdFrameHandle, + IrInstSrcIdFrameType, + IrInstSrcIdFrameSize, + IrInstSrcIdAlignOf, + IrInstSrcIdOverflowOp, + IrInstSrcIdTestErr, + IrInstSrcIdMulAdd, + IrInstSrcIdFloatOp, + IrInstSrcIdUnwrapErrCode, + IrInstSrcIdUnwrapErrPayload, + IrInstSrcIdFnProto, + IrInstSrcIdTestComptime, + IrInstSrcIdPtrCast, + IrInstSrcIdBitCast, + IrInstSrcIdIntToPtr, + IrInstSrcIdPtrToInt, + IrInstSrcIdIntToEnum, + IrInstSrcIdEnumToInt, + IrInstSrcIdIntToErr, + IrInstSrcIdErrToInt, + IrInstSrcIdCheckSwitchProngs, + IrInstSrcIdCheckStatementIsVoid, + IrInstSrcIdTypeName, + IrInstSrcIdDeclRef, + IrInstSrcIdPanic, + IrInstSrcIdTagName, + IrInstSrcIdTagType, + IrInstSrcIdFieldParentPtr, + IrInstSrcIdByteOffsetOf, + IrInstSrcIdBitOffsetOf, + IrInstSrcIdTypeInfo, + IrInstSrcIdType, + IrInstSrcIdHasField, + IrInstSrcIdTypeId, + IrInstSrcIdSetEvalBranchQuota, + IrInstSrcIdPtrType, + IrInstSrcIdAlignCast, + IrInstSrcIdImplicitCast, + IrInstSrcIdResolveResult, + IrInstSrcIdResetResult, + IrInstSrcIdOpaqueType, + IrInstSrcIdSetAlignStack, + IrInstSrcIdArgType, + IrInstSrcIdExport, + IrInstSrcIdErrorReturnTrace, + IrInstSrcIdErrorUnion, + IrInstSrcIdAtomicRmw, + IrInstSrcIdAtomicLoad, + IrInstSrcIdAtomicStore, + IrInstSrcIdSaveErrRetAddr, + IrInstSrcIdAddImplicitReturnType, + IrInstSrcIdErrSetCast, + IrInstSrcIdToBytes, + IrInstSrcIdFromBytes, + IrInstSrcIdCheckRuntimeScope, + IrInstSrcIdHasDecl, + IrInstSrcIdUndeclaredIdent, + IrInstSrcIdAlloca, + IrInstSrcIdEndExpr, + IrInstSrcIdUnionInitNamedField, + IrInstSrcIdSuspendBegin, + IrInstSrcIdSuspendFinish, + IrInstSrcIdAwait, + IrInstSrcIdResume, + IrInstSrcIdSpillBegin, + IrInstSrcIdSpillEnd, }; -struct IrInstruction { - Scope *scope; - AstNode *source_node; - LLVMValueRef llvm_value; - ZigValue *value; - uint32_t debug_id; +// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR. +// Src instructions do not have type information; Gen instructions do. +enum IrInstGenId { + IrInstGenIdInvalid, + IrInstGenIdDeclVar, + IrInstGenIdBr, + IrInstGenIdCondBr, + IrInstGenIdSwitchBr, + IrInstGenIdPhi, + IrInstGenIdBinaryNot, + IrInstGenIdNegation, + IrInstGenIdNegationWrapping, + IrInstGenIdBinOp, + IrInstGenIdLoadPtr, + IrInstGenIdStorePtr, + IrInstGenIdVectorStoreElem, + IrInstGenIdStructFieldPtr, + IrInstGenIdUnionFieldPtr, + IrInstGenIdElemPtr, + IrInstGenIdVarPtr, + IrInstGenIdReturnPtr, + IrInstGenIdCall, + IrInstGenIdReturn, + IrInstGenIdCast, + IrInstGenIdResizeSlice, + IrInstGenIdUnreachable, + IrInstGenIdAsm, + IrInstGenIdTestNonNull, + IrInstGenIdOptionalUnwrapPtr, + IrInstGenIdOptionalWrap, + IrInstGenIdUnionTag, + IrInstGenIdClz, + IrInstGenIdCtz, + IrInstGenIdPopCount, + IrInstGenIdBswap, + IrInstGenIdBitReverse, + IrInstGenIdRef, + IrInstGenIdErrName, + IrInstGenIdCmpxchg, + IrInstGenIdFence, + IrInstGenIdTruncate, + IrInstGenIdShuffleVector, + IrInstGenIdSplat, + IrInstGenIdBoolNot, + IrInstGenIdMemset, + IrInstGenIdMemcpy, + IrInstGenIdSlice, + IrInstGenIdBreakpoint, + IrInstGenIdReturnAddress, + IrInstGenIdFrameAddress, + IrInstGenIdFrameHandle, + IrInstGenIdFrameSize, + IrInstGenIdOverflowOp, + IrInstGenIdTestErr, + IrInstGenIdMulAdd, + IrInstGenIdFloatOp, + IrInstGenIdUnwrapErrCode, + IrInstGenIdUnwrapErrPayload, + IrInstGenIdErrWrapCode, + IrInstGenIdErrWrapPayload, + IrInstGenIdPtrCast, + IrInstGenIdBitCast, + IrInstGenIdWidenOrShorten, + IrInstGenIdIntToPtr, + IrInstGenIdPtrToInt, + IrInstGenIdIntToEnum, + IrInstGenIdIntToErr, + IrInstGenIdErrToInt, + IrInstGenIdPanic, + IrInstGenIdTagName, + IrInstGenIdFieldParentPtr, + IrInstGenIdAlignCast, + IrInstGenIdErrorReturnTrace, + IrInstGenIdAtomicRmw, + IrInstGenIdAtomicLoad, + IrInstGenIdAtomicStore, + IrInstGenIdSaveErrRetAddr, + IrInstGenIdVectorToArray, + IrInstGenIdArrayToVector, + IrInstGenIdAssertZero, + IrInstGenIdAssertNonNull, + IrInstGenIdPtrOfArrayToSlice, + IrInstGenIdSuspendBegin, + IrInstGenIdSuspendFinish, + IrInstGenIdAwait, + IrInstGenIdResume, + IrInstGenIdSpillBegin, + IrInstGenIdSpillEnd, + IrInstGenIdVectorExtractElem, + IrInstGenIdAlloca, + IrInstGenIdConst, +}; + +// Common fields between IrInstSrc and IrInstGen. This allows future passes +// after pass2 to be added to zig. +struct IrInst { // if ref_count is zero and the instruction has no side effects, // the instruction can be omitted in codegen uint32_t ref_count; - // When analyzing IR, instructions that point to this instruction in the "old ir" - // can find the instruction that corresponds to this value in the "new ir" - // with this child field. - IrInstruction *child; - IrBasicBlock *owner_bb; - // Nearly any instruction can have to be stored as a local variable before suspending - // and then loaded after resuming, in case there is an expression with a suspend point - // in it, such as: x + await y - IrInstruction *spill; - IrInstructionId id; - // true if this instruction was generated by zig and not from user code - bool is_gen; + uint32_t debug_id; + + Scope *scope; + AstNode *source_node; // for debugging purposes, these are useful to call to inspect the instruction void dump(); void src(); }; -struct IrInstructionDeclVarSrc { - IrInstruction base; +struct IrInstSrc { + IrInst base; - ZigVar *var; - IrInstruction *var_type; - IrInstruction *align_value; - IrInstruction *ptr; + IrInstSrcId id; + // true if this instruction was generated by zig and not from user code + // this matters for the "unreachable code" compile error + bool is_gen; + bool is_noreturn; + + // When analyzing IR, instructions that point to this instruction in the "old ir" + // can find the instruction that corresponds to this value in the "new ir" + // with this child field. + IrInstGen *child; + IrBasicBlockSrc *owner_bb; + + // for debugging purposes, these are useful to call to inspect the instruction + void dump(); + void src(); }; -struct IrInstructionDeclVarGen { - IrInstruction base; +struct IrInstGen { + IrInst base; - ZigVar *var; - IrInstruction *var_ptr; + IrInstGenId id; + + LLVMValueRef llvm_value; + ZigValue *value; + IrBasicBlockGen *owner_bb; + // Nearly any instruction can have to be stored as a local variable before suspending + // and then loaded after resuming, in case there is an expression with a suspend point + // in it, such as: x + await y + IrInstGen *spill; + + // for debugging purposes, these are useful to call to inspect the instruction + void dump(); + void src(); }; -struct IrInstructionCondBr { - IrInstruction base; +struct IrInstSrcDeclVar { + IrInstSrc base; - IrInstruction *condition; - IrBasicBlock *then_block; - IrBasicBlock *else_block; - IrInstruction *is_comptime; + ZigVar *var; + IrInstSrc *var_type; + IrInstSrc *align_value; + IrInstSrc *ptr; +}; + +struct IrInstGenDeclVar { + IrInstGen base; + + ZigVar *var; + IrInstGen *var_ptr; +}; + +struct IrInstSrcCondBr { + IrInstSrc base; + + IrInstSrc *condition; + IrBasicBlockSrc *then_block; + IrBasicBlockSrc *else_block; + IrInstSrc *is_comptime; ResultLoc *result_loc; }; -struct IrInstructionBr { - IrInstruction base; +struct IrInstGenCondBr { + IrInstGen base; - IrBasicBlock *dest_block; - IrInstruction *is_comptime; + IrInstGen *condition; + IrBasicBlockGen *then_block; + IrBasicBlockGen *else_block; }; -struct IrInstructionSwitchBrCase { - IrInstruction *value; - IrBasicBlock *block; +struct IrInstSrcBr { + IrInstSrc base; + + IrBasicBlockSrc *dest_block; + IrInstSrc *is_comptime; }; -struct IrInstructionSwitchBr { - IrInstruction base; +struct IrInstGenBr { + IrInstGen base; - IrInstruction *target_value; - IrBasicBlock *else_block; + IrBasicBlockGen *dest_block; +}; + +struct IrInstSrcSwitchBrCase { + IrInstSrc *value; + IrBasicBlockSrc *block; +}; + +struct IrInstSrcSwitchBr { + IrInstSrc base; + + IrInstSrc *target_value; + IrBasicBlockSrc *else_block; size_t case_count; - IrInstructionSwitchBrCase *cases; - IrInstruction *is_comptime; - IrInstruction *switch_prongs_void; + IrInstSrcSwitchBrCase *cases; + IrInstSrc *is_comptime; + IrInstSrc *switch_prongs_void; }; -struct IrInstructionSwitchVar { - IrInstruction base; +struct IrInstGenSwitchBrCase { + IrInstGen *value; + IrBasicBlockGen *block; +}; - IrInstruction *target_value_ptr; - IrInstruction **prongs_ptr; +struct IrInstGenSwitchBr { + IrInstGen base; + + IrInstGen *target_value; + IrBasicBlockGen *else_block; + size_t case_count; + IrInstGenSwitchBrCase *cases; +}; + +struct IrInstSrcSwitchVar { + IrInstSrc base; + + IrInstSrc *target_value_ptr; + IrInstSrc **prongs_ptr; size_t prongs_len; }; -struct IrInstructionSwitchElseVar { - IrInstruction base; +struct IrInstSrcSwitchElseVar { + IrInstSrc base; - IrInstruction *target_value_ptr; - IrInstructionSwitchBr *switch_br; + IrInstSrc *target_value_ptr; + IrInstSrcSwitchBr *switch_br; }; -struct IrInstructionSwitchTarget { - IrInstruction base; +struct IrInstSrcSwitchTarget { + IrInstSrc base; - IrInstruction *target_value_ptr; + IrInstSrc *target_value_ptr; }; -struct IrInstructionPhi { - IrInstruction base; +struct IrInstSrcPhi { + IrInstSrc base; size_t incoming_count; - IrBasicBlock **incoming_blocks; - IrInstruction **incoming_values; + IrBasicBlockSrc **incoming_blocks; + IrInstSrc **incoming_values; ResultLocPeerParent *peer_parent; }; +struct IrInstGenPhi { + IrInstGen base; + + size_t incoming_count; + IrBasicBlockGen **incoming_blocks; + IrInstGen **incoming_values; +}; + enum IrUnOp { IrUnOpInvalid, IrUnOpBinNot, @@ -2796,15 +2959,30 @@ enum IrUnOp { IrUnOpOptional, }; -struct IrInstructionUnOp { - IrInstruction base; +struct IrInstSrcUnOp { + IrInstSrc base; IrUnOp op_id; LVal lval; - IrInstruction *value; + IrInstSrc *value; ResultLoc *result_loc; }; +struct IrInstGenBinaryNot { + IrInstGen base; + IrInstGen *operand; +}; + +struct IrInstGenNegation { + IrInstGen base; + IrInstGen *operand; +}; + +struct IrInstGenNegationWrapping { + IrInstGen base; + IrInstGen *operand; +}; + enum IrBinOp { IrBinOpInvalid, IrBinOpBoolOr, @@ -2839,113 +3017,144 @@ enum IrBinOp { IrBinOpArrayMult, }; -struct IrInstructionBinOp { - IrInstruction base; +struct IrInstSrcBinOp { + IrInstSrc base; - IrInstruction *op1; - IrInstruction *op2; + IrInstSrc *op1; + IrInstSrc *op2; IrBinOp op_id; bool safety_check_on; }; -struct IrInstructionMergeErrSets { - IrInstruction base; +struct IrInstGenBinOp { + IrInstGen base; - IrInstruction *op1; - IrInstruction *op2; + IrInstGen *op1; + IrInstGen *op2; + IrBinOp op_id; + bool safety_check_on; +}; + +struct IrInstSrcMergeErrSets { + IrInstSrc base; + + IrInstSrc *op1; + IrInstSrc *op2; Buf *type_name; }; -struct IrInstructionLoadPtr { - IrInstruction base; +struct IrInstSrcLoadPtr { + IrInstSrc base; - IrInstruction *ptr; + IrInstSrc *ptr; }; -struct IrInstructionLoadPtrGen { - IrInstruction base; +struct IrInstGenLoadPtr { + IrInstGen base; - IrInstruction *ptr; - IrInstruction *result_loc; + IrInstGen *ptr; + IrInstGen *result_loc; }; -struct IrInstructionStorePtr { - IrInstruction base; +struct IrInstSrcStorePtr { + IrInstSrc base; + + IrInstSrc *ptr; + IrInstSrc *value; bool allow_write_through_const; - IrInstruction *ptr; - IrInstruction *value; }; -struct IrInstructionVectorStoreElem { - IrInstruction base; +struct IrInstGenStorePtr { + IrInstGen base; - IrInstruction *vector_ptr; - IrInstruction *index; - IrInstruction *value; + IrInstGen *ptr; + IrInstGen *value; }; -struct IrInstructionFieldPtr { - IrInstruction base; +struct IrInstGenVectorStoreElem { + IrInstGen base; - bool initializing; - IrInstruction *container_ptr; + IrInstGen *vector_ptr; + IrInstGen *index; + IrInstGen *value; +}; + +struct IrInstSrcFieldPtr { + IrInstSrc base; + + IrInstSrc *container_ptr; Buf *field_name_buffer; - IrInstruction *field_name_expr; + IrInstSrc *field_name_expr; + bool initializing; }; -struct IrInstructionStructFieldPtr { - IrInstruction base; +struct IrInstGenStructFieldPtr { + IrInstGen base; - IrInstruction *struct_ptr; + IrInstGen *struct_ptr; TypeStructField *field; bool is_const; }; -struct IrInstructionUnionFieldPtr { - IrInstruction base; +struct IrInstGenUnionFieldPtr { + IrInstGen base; + IrInstGen *union_ptr; + TypeUnionField *field; bool safety_check_on; bool initializing; - IrInstruction *union_ptr; - TypeUnionField *field; }; -struct IrInstructionElemPtr { - IrInstruction base; +struct IrInstSrcElemPtr { + IrInstSrc base; - IrInstruction *array_ptr; - IrInstruction *elem_index; + IrInstSrc *array_ptr; + IrInstSrc *elem_index; AstNode *init_array_type_source_node; PtrLen ptr_len; bool safety_check_on; }; -struct IrInstructionVarPtr { - IrInstruction base; +struct IrInstGenElemPtr { + IrInstGen base; + + IrInstGen *array_ptr; + IrInstGen *elem_index; + bool safety_check_on; +}; + +struct IrInstSrcVarPtr { + IrInstSrc base; ZigVar *var; ScopeFnDef *crossed_fndef_scope; }; +struct IrInstGenVarPtr { + IrInstGen base; + + ZigVar *var; +}; + // For functions that have a return type for which handle_is_ptr is true, a // result location pointer is the secret first parameter ("sret"). This // instruction returns that pointer. -struct IrInstructionReturnPtr { - IrInstruction base; +struct IrInstGenReturnPtr { + IrInstGen base; }; -struct IrInstructionCallSrc { - IrInstruction base; +struct IrInstSrcCall { + IrInstSrc base; - IrInstruction *fn_ref; + IrInstSrc *fn_ref; ZigFn *fn_entry; size_t arg_count; - IrInstruction **args; - IrInstruction *ret_ptr; + IrInstSrc **args; + IrInstSrc *ret_ptr; ResultLoc *result_loc; - IrInstruction *new_stack; + IrInstSrc *new_stack; CallModifier modifier; bool is_async_call_builtin; @@ -2953,12 +3162,12 @@ struct IrInstructionCallSrc { // This is a pass1 instruction, used by @call when the args node is // a tuple or struct literal. -struct IrInstructionCallSrcArgs { - IrInstruction base; +struct IrInstSrcCallArgs { + IrInstSrc base; - IrInstruction *options; - IrInstruction *fn_ref; - IrInstruction **args_ptr; + IrInstSrc *options; + IrInstSrc *fn_ref; + IrInstSrc **args_ptr; size_t args_len; ResultLoc *result_loc; }; @@ -2966,42 +3175,54 @@ struct IrInstructionCallSrcArgs { // This is a pass1 instruction, used by @call, when the args node // is not a literal. // `args` is expected to be either a struct or a tuple. -struct IrInstructionCallExtra { - IrInstruction base; +struct IrInstSrcCallExtra { + IrInstSrc base; - IrInstruction *options; - IrInstruction *fn_ref; - IrInstruction *args; + IrInstSrc *options; + IrInstSrc *fn_ref; + IrInstSrc *args; ResultLoc *result_loc; }; -struct IrInstructionCallGen { - IrInstruction base; +struct IrInstGenCall { + IrInstGen base; - IrInstruction *fn_ref; + IrInstGen *fn_ref; ZigFn *fn_entry; size_t arg_count; - IrInstruction **args; - IrInstruction *result_loc; - IrInstruction *frame_result_loc; - IrInstruction *new_stack; + IrInstGen **args; + IrInstGen *result_loc; + IrInstGen *frame_result_loc; + IrInstGen *new_stack; CallModifier modifier; bool is_async_call_builtin; }; -struct IrInstructionConst { - IrInstruction base; +struct IrInstSrcConst { + IrInstSrc base; + + ZigValue *value; +}; + +struct IrInstGenConst { + IrInstGen base; +}; + +struct IrInstSrcReturn { + IrInstSrc base; + + IrInstSrc *operand; }; // When an IrExecutable is not in a function, a return instruction means that // the expression returns with that value, even though a return statement from // an AST perspective is invalid. -struct IrInstructionReturn { - IrInstruction base; +struct IrInstGenReturn { + IrInstGen base; - IrInstruction *operand; + IrInstGen *operand; }; enum CastOp { @@ -3016,89 +3237,92 @@ enum CastOp { }; // TODO get rid of this instruction, replace with instructions for each op code -struct IrInstructionCast { - IrInstruction base; +struct IrInstGenCast { + IrInstGen base; - IrInstruction *value; - ZigType *dest_type; + IrInstGen *value; CastOp cast_op; }; -struct IrInstructionResizeSlice { - IrInstruction base; +struct IrInstGenResizeSlice { + IrInstGen base; - IrInstruction *operand; - IrInstruction *result_loc; + IrInstGen *operand; + IrInstGen *result_loc; }; -struct IrInstructionContainerInitList { - IrInstruction base; +struct IrInstSrcContainerInitList { + IrInstSrc base; - IrInstruction *elem_type; + IrInstSrc *elem_type; size_t item_count; - IrInstruction **elem_result_loc_list; - IrInstruction *result_loc; + IrInstSrc **elem_result_loc_list; + IrInstSrc *result_loc; AstNode *init_array_type_source_node; }; -struct IrInstructionContainerInitFieldsField { +struct IrInstSrcContainerInitFieldsField { Buf *name; AstNode *source_node; TypeStructField *type_struct_field; - IrInstruction *result_loc; + IrInstSrc *result_loc; }; -struct IrInstructionContainerInitFields { - IrInstruction base; +struct IrInstSrcContainerInitFields { + IrInstSrc base; size_t field_count; - IrInstructionContainerInitFieldsField *fields; - IrInstruction *result_loc; + IrInstSrcContainerInitFieldsField *fields; + IrInstSrc *result_loc; }; -struct IrInstructionUnreachable { - IrInstruction base; +struct IrInstSrcUnreachable { + IrInstSrc base; }; -struct IrInstructionTypeOf { - IrInstruction base; - - IrInstruction *value; +struct IrInstGenUnreachable { + IrInstGen base; }; -struct IrInstructionSetCold { - IrInstruction base; +struct IrInstSrcTypeOf { + IrInstSrc base; - IrInstruction *is_cold; + IrInstSrc *value; }; -struct IrInstructionSetRuntimeSafety { - IrInstruction base; +struct IrInstSrcSetCold { + IrInstSrc base; - IrInstruction *safety_on; + IrInstSrc *is_cold; }; -struct IrInstructionSetFloatMode { - IrInstruction base; +struct IrInstSrcSetRuntimeSafety { + IrInstSrc base; - IrInstruction *scope_value; - IrInstruction *mode_value; + IrInstSrc *safety_on; }; -struct IrInstructionArrayType { - IrInstruction base; +struct IrInstSrcSetFloatMode { + IrInstSrc base; - IrInstruction *size; - IrInstruction *sentinel; - IrInstruction *child_type; + IrInstSrc *scope_value; + IrInstSrc *mode_value; }; -struct IrInstructionPtrType { - IrInstruction base; +struct IrInstSrcArrayType { + IrInstSrc base; - IrInstruction *sentinel; - IrInstruction *align_value; - IrInstruction *child_type; + IrInstSrc *size; + IrInstSrc *sentinel; + IrInstSrc *child_type; +}; + +struct IrInstSrcPtrType { + IrInstSrc base; + + IrInstSrc *sentinel; + IrInstSrc *align_value; + IrInstSrc *child_type; uint32_t bit_offset_start; uint32_t host_int_bytes; PtrLen ptr_len; @@ -3107,375 +3331,459 @@ struct IrInstructionPtrType { bool is_allow_zero; }; -struct IrInstructionAnyFrameType { - IrInstruction base; +struct IrInstSrcAnyFrameType { + IrInstSrc base; - IrInstruction *payload_type; + IrInstSrc *payload_type; }; -struct IrInstructionSliceType { - IrInstruction base; +struct IrInstSrcSliceType { + IrInstSrc base; - IrInstruction *sentinel; - IrInstruction *align_value; - IrInstruction *child_type; + IrInstSrc *sentinel; + IrInstSrc *align_value; + IrInstSrc *child_type; bool is_const; bool is_volatile; bool is_allow_zero; }; -struct IrInstructionAsmSrc { - IrInstruction base; +struct IrInstSrcAsm { + IrInstSrc base; - IrInstruction *asm_template; - IrInstruction **input_list; - IrInstruction **output_types; + IrInstSrc *asm_template; + IrInstSrc **input_list; + IrInstSrc **output_types; ZigVar **output_vars; size_t return_count; bool has_side_effects; bool is_global; }; -struct IrInstructionAsmGen { - IrInstruction base; +struct IrInstGenAsm { + IrInstGen base; Buf *asm_template; AsmToken *token_list; size_t token_list_len; - IrInstruction **input_list; - IrInstruction **output_types; + IrInstGen **input_list; + IrInstGen **output_types; ZigVar **output_vars; size_t return_count; bool has_side_effects; }; -struct IrInstructionSizeOf { - IrInstruction base; +struct IrInstSrcSizeOf { + IrInstSrc base; + IrInstSrc *type_value; bool bit_size; - IrInstruction *type_value; }; // returns true if nonnull, returns false if null -// this is so that `zeroes` sets maybe values to null -struct IrInstructionTestNonNull { - IrInstruction base; +struct IrInstSrcTestNonNull { + IrInstSrc base; - IrInstruction *value; + IrInstSrc *value; +}; + +struct IrInstGenTestNonNull { + IrInstGen base; + + IrInstGen *value; }; // Takes a pointer to an optional value, returns a pointer // to the payload. -struct IrInstructionOptionalUnwrapPtr { - IrInstruction base; +struct IrInstSrcOptionalUnwrapPtr { + IrInstSrc base; + IrInstSrc *base_ptr; bool safety_check_on; bool initializing; - IrInstruction *base_ptr; }; -struct IrInstructionCtz { - IrInstruction base; +struct IrInstGenOptionalUnwrapPtr { + IrInstGen base; - IrInstruction *type; - IrInstruction *op; + IrInstGen *base_ptr; + bool safety_check_on; + bool initializing; }; -struct IrInstructionClz { - IrInstruction base; +struct IrInstSrcCtz { + IrInstSrc base; - IrInstruction *type; - IrInstruction *op; + IrInstSrc *type; + IrInstSrc *op; }; -struct IrInstructionPopCount { - IrInstruction base; +struct IrInstGenCtz { + IrInstGen base; - IrInstruction *type; - IrInstruction *op; + IrInstGen *op; }; -struct IrInstructionUnionTag { - IrInstruction base; +struct IrInstSrcClz { + IrInstSrc base; - IrInstruction *value; + IrInstSrc *type; + IrInstSrc *op; }; -struct IrInstructionImport { - IrInstruction base; +struct IrInstGenClz { + IrInstGen base; - IrInstruction *name; + IrInstGen *op; }; -struct IrInstructionRef { - IrInstruction base; +struct IrInstSrcPopCount { + IrInstSrc base; - IrInstruction *value; + IrInstSrc *type; + IrInstSrc *op; +}; + +struct IrInstGenPopCount { + IrInstGen base; + + IrInstGen *op; +}; + +struct IrInstGenUnionTag { + IrInstGen base; + + IrInstGen *value; +}; + +struct IrInstSrcImport { + IrInstSrc base; + + IrInstSrc *name; +}; + +struct IrInstSrcRef { + IrInstSrc base; + + IrInstSrc *value; bool is_const; bool is_volatile; }; -struct IrInstructionRefGen { - IrInstruction base; +struct IrInstGenRef { + IrInstGen base; - IrInstruction *operand; - IrInstruction *result_loc; + IrInstGen *operand; + IrInstGen *result_loc; }; -struct IrInstructionCompileErr { - IrInstruction base; +struct IrInstSrcCompileErr { + IrInstSrc base; - IrInstruction *msg; + IrInstSrc *msg; }; -struct IrInstructionCompileLog { - IrInstruction base; +struct IrInstSrcCompileLog { + IrInstSrc base; size_t msg_count; - IrInstruction **msg_list; + IrInstSrc **msg_list; }; -struct IrInstructionErrName { - IrInstruction base; +struct IrInstSrcErrName { + IrInstSrc base; - IrInstruction *value; + IrInstSrc *value; }; -struct IrInstructionCImport { - IrInstruction base; +struct IrInstGenErrName { + IrInstGen base; + + IrInstGen *value; }; -struct IrInstructionCInclude { - IrInstruction base; - - IrInstruction *name; +struct IrInstSrcCImport { + IrInstSrc base; }; -struct IrInstructionCDefine { - IrInstruction base; +struct IrInstSrcCInclude { + IrInstSrc base; - IrInstruction *name; - IrInstruction *value; + IrInstSrc *name; }; -struct IrInstructionCUndef { - IrInstruction base; +struct IrInstSrcCDefine { + IrInstSrc base; - IrInstruction *name; + IrInstSrc *name; + IrInstSrc *value; }; -struct IrInstructionEmbedFile { - IrInstruction base; +struct IrInstSrcCUndef { + IrInstSrc base; - IrInstruction *name; + IrInstSrc *name; }; -struct IrInstructionCmpxchgSrc { - IrInstruction base; +struct IrInstSrcEmbedFile { + IrInstSrc base; + + IrInstSrc *name; +}; + +struct IrInstSrcCmpxchg { + IrInstSrc base; bool is_weak; - IrInstruction *type_value; - IrInstruction *ptr; - IrInstruction *cmp_value; - IrInstruction *new_value; - IrInstruction *success_order_value; - IrInstruction *failure_order_value; + IrInstSrc *type_value; + IrInstSrc *ptr; + IrInstSrc *cmp_value; + IrInstSrc *new_value; + IrInstSrc *success_order_value; + IrInstSrc *failure_order_value; ResultLoc *result_loc; }; -struct IrInstructionCmpxchgGen { - IrInstruction base; +struct IrInstGenCmpxchg { + IrInstGen base; - bool is_weak; AtomicOrder success_order; AtomicOrder failure_order; - IrInstruction *ptr; - IrInstruction *cmp_value; - IrInstruction *new_value; - IrInstruction *result_loc; + IrInstGen *ptr; + IrInstGen *cmp_value; + IrInstGen *new_value; + IrInstGen *result_loc; + bool is_weak; }; -struct IrInstructionFence { - IrInstruction base; +struct IrInstSrcFence { + IrInstSrc base; - IrInstruction *order_value; + IrInstSrc *order; +}; + +struct IrInstGenFence { + IrInstGen base; - // if this instruction gets to runtime then we know these values: AtomicOrder order; }; -struct IrInstructionTruncate { - IrInstruction base; +struct IrInstSrcTruncate { + IrInstSrc base; - IrInstruction *dest_type; - IrInstruction *target; + IrInstSrc *dest_type; + IrInstSrc *target; }; -struct IrInstructionIntCast { - IrInstruction base; +struct IrInstGenTruncate { + IrInstGen base; - IrInstruction *dest_type; - IrInstruction *target; + IrInstGen *target; }; -struct IrInstructionFloatCast { - IrInstruction base; +struct IrInstSrcIntCast { + IrInstSrc base; - IrInstruction *dest_type; - IrInstruction *target; + IrInstSrc *dest_type; + IrInstSrc *target; }; -struct IrInstructionErrSetCast { - IrInstruction base; +struct IrInstSrcFloatCast { + IrInstSrc base; - IrInstruction *dest_type; - IrInstruction *target; + IrInstSrc *dest_type; + IrInstSrc *target; }; -struct IrInstructionToBytes { - IrInstruction base; +struct IrInstSrcErrSetCast { + IrInstSrc base; - IrInstruction *target; + IrInstSrc *dest_type; + IrInstSrc *target; +}; + +struct IrInstSrcToBytes { + IrInstSrc base; + + IrInstSrc *target; ResultLoc *result_loc; }; -struct IrInstructionFromBytes { - IrInstruction base; +struct IrInstSrcFromBytes { + IrInstSrc base; - IrInstruction *dest_child_type; - IrInstruction *target; + IrInstSrc *dest_child_type; + IrInstSrc *target; ResultLoc *result_loc; }; -struct IrInstructionIntToFloat { - IrInstruction base; +struct IrInstSrcIntToFloat { + IrInstSrc base; - IrInstruction *dest_type; - IrInstruction *target; + IrInstSrc *dest_type; + IrInstSrc *target; }; -struct IrInstructionFloatToInt { - IrInstruction base; +struct IrInstSrcFloatToInt { + IrInstSrc base; - IrInstruction *dest_type; - IrInstruction *target; + IrInstSrc *dest_type; + IrInstSrc *target; }; -struct IrInstructionBoolToInt { - IrInstruction base; +struct IrInstSrcBoolToInt { + IrInstSrc base; - IrInstruction *target; + IrInstSrc *target; }; -struct IrInstructionIntType { - IrInstruction base; +struct IrInstSrcIntType { + IrInstSrc base; - IrInstruction *is_signed; - IrInstruction *bit_count; + IrInstSrc *is_signed; + IrInstSrc *bit_count; }; -struct IrInstructionVectorType { - IrInstruction base; +struct IrInstSrcVectorType { + IrInstSrc base; - IrInstruction *len; - IrInstruction *elem_type; + IrInstSrc *len; + IrInstSrc *elem_type; }; -struct IrInstructionBoolNot { - IrInstruction base; +struct IrInstSrcBoolNot { + IrInstSrc base; - IrInstruction *value; + IrInstSrc *value; }; -struct IrInstructionMemset { - IrInstruction base; +struct IrInstGenBoolNot { + IrInstGen base; - IrInstruction *dest_ptr; - IrInstruction *byte; - IrInstruction *count; + IrInstGen *value; }; -struct IrInstructionMemcpy { - IrInstruction base; +struct IrInstSrcMemset { + IrInstSrc base; - IrInstruction *dest_ptr; - IrInstruction *src_ptr; - IrInstruction *count; + IrInstSrc *dest_ptr; + IrInstSrc *byte; + IrInstSrc *count; }; -struct IrInstructionSliceSrc { - IrInstruction base; +struct IrInstGenMemset { + IrInstGen base; + IrInstGen *dest_ptr; + IrInstGen *byte; + IrInstGen *count; +}; + +struct IrInstSrcMemcpy { + IrInstSrc base; + + IrInstSrc *dest_ptr; + IrInstSrc *src_ptr; + IrInstSrc *count; +}; + +struct IrInstGenMemcpy { + IrInstGen base; + + IrInstGen *dest_ptr; + IrInstGen *src_ptr; + IrInstGen *count; +}; + +struct IrInstSrcSlice { + IrInstSrc base; + + IrInstSrc *ptr; + IrInstSrc *start; + IrInstSrc *end; + IrInstSrc *sentinel; + ResultLoc *result_loc; bool safety_check_on; - IrInstruction *ptr; - IrInstruction *start; - IrInstruction *end; - IrInstruction *sentinel; - ResultLoc *result_loc; }; -struct IrInstructionSliceGen { - IrInstruction base; +struct IrInstGenSlice { + IrInstGen base; + IrInstGen *ptr; + IrInstGen *start; + IrInstGen *end; + IrInstGen *result_loc; bool safety_check_on; - IrInstruction *ptr; - IrInstruction *start; - IrInstruction *end; - IrInstruction *result_loc; }; -struct IrInstructionMemberCount { - IrInstruction base; +struct IrInstSrcMemberCount { + IrInstSrc base; - IrInstruction *container; + IrInstSrc *container; }; -struct IrInstructionMemberType { - IrInstruction base; +struct IrInstSrcMemberType { + IrInstSrc base; - IrInstruction *container_type; - IrInstruction *member_index; + IrInstSrc *container_type; + IrInstSrc *member_index; }; -struct IrInstructionMemberName { - IrInstruction base; +struct IrInstSrcMemberName { + IrInstSrc base; - IrInstruction *container_type; - IrInstruction *member_index; + IrInstSrc *container_type; + IrInstSrc *member_index; }; -struct IrInstructionBreakpoint { - IrInstruction base; +struct IrInstSrcBreakpoint { + IrInstSrc base; }; -struct IrInstructionReturnAddress { - IrInstruction base; +struct IrInstGenBreakpoint { + IrInstGen base; }; -struct IrInstructionFrameAddress { - IrInstruction base; +struct IrInstSrcReturnAddress { + IrInstSrc base; }; -struct IrInstructionFrameHandle { - IrInstruction base; +struct IrInstGenReturnAddress { + IrInstGen base; }; -struct IrInstructionFrameType { - IrInstruction base; - - IrInstruction *fn; +struct IrInstSrcFrameAddress { + IrInstSrc base; }; -struct IrInstructionFrameSizeSrc { - IrInstruction base; - - IrInstruction *fn; +struct IrInstGenFrameAddress { + IrInstGen base; }; -struct IrInstructionFrameSizeGen { - IrInstruction base; +struct IrInstSrcFrameHandle { + IrInstSrc base; +}; - IrInstruction *fn; +struct IrInstGenFrameHandle { + IrInstGen base; +}; + +struct IrInstSrcFrameType { + IrInstSrc base; + + IrInstSrc *fn; +}; + +struct IrInstSrcFrameSize { + IrInstSrc base; + + IrInstSrc *fn; +}; + +struct IrInstGenFrameSize { + IrInstGen base; + + IrInstGen *fn; }; enum IrOverflowOp { @@ -3485,559 +3793,713 @@ enum IrOverflowOp { IrOverflowOpShl, }; -struct IrInstructionOverflowOp { - IrInstruction base; +struct IrInstSrcOverflowOp { + IrInstSrc base; IrOverflowOp op; - IrInstruction *type_value; - IrInstruction *op1; - IrInstruction *op2; - IrInstruction *result_ptr; + IrInstSrc *type_value; + IrInstSrc *op1; + IrInstSrc *op2; + IrInstSrc *result_ptr; +}; +struct IrInstGenOverflowOp { + IrInstGen base; + + IrOverflowOp op; + IrInstGen *op1; + IrInstGen *op2; + IrInstGen *result_ptr; + + // TODO can this field be removed? ZigType *result_ptr_type; }; -struct IrInstructionMulAdd { - IrInstruction base; +struct IrInstSrcMulAdd { + IrInstSrc base; - IrInstruction *type_value; - IrInstruction *op1; - IrInstruction *op2; - IrInstruction *op3; + IrInstSrc *type_value; + IrInstSrc *op1; + IrInstSrc *op2; + IrInstSrc *op3; }; -struct IrInstructionAlignOf { - IrInstruction base; +struct IrInstGenMulAdd { + IrInstGen base; - IrInstruction *type_value; + IrInstGen *op1; + IrInstGen *op2; + IrInstGen *op3; +}; + +struct IrInstSrcAlignOf { + IrInstSrc base; + + IrInstSrc *type_value; }; // returns true if error, returns false if not error -struct IrInstructionTestErrSrc { - IrInstruction base; +struct IrInstSrcTestErr { + IrInstSrc base; + IrInstSrc *base_ptr; bool resolve_err_set; bool base_ptr_is_payload; - IrInstruction *base_ptr; }; -struct IrInstructionTestErrGen { - IrInstruction base; +struct IrInstGenTestErr { + IrInstGen base; - IrInstruction *err_union; + IrInstGen *err_union; }; // Takes an error union pointer, returns a pointer to the error code. -struct IrInstructionUnwrapErrCode { - IrInstruction base; +struct IrInstSrcUnwrapErrCode { + IrInstSrc base; + IrInstSrc *err_union_ptr; bool initializing; - IrInstruction *err_union_ptr; }; -struct IrInstructionUnwrapErrPayload { - IrInstruction base; +struct IrInstGenUnwrapErrCode { + IrInstGen base; + IrInstGen *err_union_ptr; + bool initializing; +}; + +struct IrInstSrcUnwrapErrPayload { + IrInstSrc base; + + IrInstSrc *value; bool safety_check_on; bool initializing; - IrInstruction *value; }; -struct IrInstructionOptionalWrap { - IrInstruction base; +struct IrInstGenUnwrapErrPayload { + IrInstGen base; - IrInstruction *operand; - IrInstruction *result_loc; + IrInstGen *value; + bool safety_check_on; + bool initializing; }; -struct IrInstructionErrWrapPayload { - IrInstruction base; +struct IrInstGenOptionalWrap { + IrInstGen base; - IrInstruction *operand; - IrInstruction *result_loc; + IrInstGen *operand; + IrInstGen *result_loc; }; -struct IrInstructionErrWrapCode { - IrInstruction base; +struct IrInstGenErrWrapPayload { + IrInstGen base; - IrInstruction *operand; - IrInstruction *result_loc; + IrInstGen *operand; + IrInstGen *result_loc; }; -struct IrInstructionFnProto { - IrInstruction base; +struct IrInstGenErrWrapCode { + IrInstGen base; - IrInstruction **param_types; - IrInstruction *align_value; - IrInstruction *callconv_value; - IrInstruction *return_type; + IrInstGen *operand; + IrInstGen *result_loc; +}; + +struct IrInstSrcFnProto { + IrInstSrc base; + + IrInstSrc **param_types; + IrInstSrc *align_value; + IrInstSrc *callconv_value; + IrInstSrc *return_type; bool is_var_args; }; // true if the target value is compile time known, false otherwise -struct IrInstructionTestComptime { - IrInstruction base; +struct IrInstSrcTestComptime { + IrInstSrc base; - IrInstruction *value; + IrInstSrc *value; }; -struct IrInstructionPtrCastSrc { - IrInstruction base; +struct IrInstSrcPtrCast { + IrInstSrc base; - IrInstruction *dest_type; - IrInstruction *ptr; + IrInstSrc *dest_type; + IrInstSrc *ptr; bool safety_check_on; }; -struct IrInstructionPtrCastGen { - IrInstruction base; +struct IrInstGenPtrCast { + IrInstGen base; - IrInstruction *ptr; + IrInstGen *ptr; bool safety_check_on; }; -struct IrInstructionImplicitCast { - IrInstruction base; +struct IrInstSrcImplicitCast { + IrInstSrc base; - IrInstruction *operand; + IrInstSrc *operand; ResultLocCast *result_loc_cast; }; -struct IrInstructionBitCastSrc { - IrInstruction base; +struct IrInstSrcBitCast { + IrInstSrc base; - IrInstruction *operand; + IrInstSrc *operand; ResultLocBitCast *result_loc_bit_cast; }; -struct IrInstructionBitCastGen { - IrInstruction base; +struct IrInstGenBitCast { + IrInstGen base; - IrInstruction *operand; + IrInstGen *operand; }; -struct IrInstructionWidenOrShorten { - IrInstruction base; +struct IrInstGenWidenOrShorten { + IrInstGen base; - IrInstruction *target; + IrInstGen *target; }; -struct IrInstructionPtrToInt { - IrInstruction base; +struct IrInstSrcPtrToInt { + IrInstSrc base; - IrInstruction *target; + IrInstSrc *target; }; -struct IrInstructionIntToPtr { - IrInstruction base; +struct IrInstGenPtrToInt { + IrInstGen base; - IrInstruction *dest_type; - IrInstruction *target; + IrInstGen *target; }; -struct IrInstructionIntToEnum { - IrInstruction base; +struct IrInstSrcIntToPtr { + IrInstSrc base; - IrInstruction *dest_type; - IrInstruction *target; + IrInstSrc *dest_type; + IrInstSrc *target; }; -struct IrInstructionEnumToInt { - IrInstruction base; +struct IrInstGenIntToPtr { + IrInstGen base; - IrInstruction *target; + IrInstGen *target; }; -struct IrInstructionIntToErr { - IrInstruction base; +struct IrInstSrcIntToEnum { + IrInstSrc base; - IrInstruction *target; + IrInstSrc *dest_type; + IrInstSrc *target; }; -struct IrInstructionErrToInt { - IrInstruction base; +struct IrInstGenIntToEnum { + IrInstGen base; - IrInstruction *target; + IrInstGen *target; }; -struct IrInstructionCheckSwitchProngsRange { - IrInstruction *start; - IrInstruction *end; +struct IrInstSrcEnumToInt { + IrInstSrc base; + + IrInstSrc *target; }; -struct IrInstructionCheckSwitchProngs { - IrInstruction base; +struct IrInstSrcIntToErr { + IrInstSrc base; - IrInstruction *target_value; - IrInstructionCheckSwitchProngsRange *ranges; + IrInstSrc *target; +}; + +struct IrInstGenIntToErr { + IrInstGen base; + + IrInstGen *target; +}; + +struct IrInstSrcErrToInt { + IrInstSrc base; + + IrInstSrc *target; +}; + +struct IrInstGenErrToInt { + IrInstGen base; + + IrInstGen *target; +}; + +struct IrInstSrcCheckSwitchProngsRange { + IrInstSrc *start; + IrInstSrc *end; +}; + +struct IrInstSrcCheckSwitchProngs { + IrInstSrc base; + + IrInstSrc *target_value; + IrInstSrcCheckSwitchProngsRange *ranges; size_t range_count; bool have_else_prong; + bool have_underscore_prong; }; -struct IrInstructionCheckStatementIsVoid { - IrInstruction base; +struct IrInstSrcCheckStatementIsVoid { + IrInstSrc base; - IrInstruction *statement_value; + IrInstSrc *statement_value; }; -struct IrInstructionTypeName { - IrInstruction base; +struct IrInstSrcTypeName { + IrInstSrc base; - IrInstruction *type_value; + IrInstSrc *type_value; }; -struct IrInstructionDeclRef { - IrInstruction base; +struct IrInstSrcDeclRef { + IrInstSrc base; LVal lval; Tld *tld; }; -struct IrInstructionPanic { - IrInstruction base; +struct IrInstSrcPanic { + IrInstSrc base; - IrInstruction *msg; + IrInstSrc *msg; }; -struct IrInstructionTagName { - IrInstruction base; +struct IrInstGenPanic { + IrInstGen base; - IrInstruction *target; + IrInstGen *msg; }; -struct IrInstructionTagType { - IrInstruction base; +struct IrInstSrcTagName { + IrInstSrc base; - IrInstruction *target; + IrInstSrc *target; }; -struct IrInstructionFieldParentPtr { - IrInstruction base; +struct IrInstGenTagName { + IrInstGen base; - IrInstruction *type_value; - IrInstruction *field_name; - IrInstruction *field_ptr; + IrInstGen *target; +}; + +struct IrInstSrcTagType { + IrInstSrc base; + + IrInstSrc *target; +}; + +struct IrInstSrcFieldParentPtr { + IrInstSrc base; + + IrInstSrc *type_value; + IrInstSrc *field_name; + IrInstSrc *field_ptr; +}; + +struct IrInstGenFieldParentPtr { + IrInstGen base; + + IrInstGen *field_ptr; TypeStructField *field; }; -struct IrInstructionByteOffsetOf { - IrInstruction base; +struct IrInstSrcByteOffsetOf { + IrInstSrc base; - IrInstruction *type_value; - IrInstruction *field_name; + IrInstSrc *type_value; + IrInstSrc *field_name; }; -struct IrInstructionBitOffsetOf { - IrInstruction base; +struct IrInstSrcBitOffsetOf { + IrInstSrc base; - IrInstruction *type_value; - IrInstruction *field_name; + IrInstSrc *type_value; + IrInstSrc *field_name; }; -struct IrInstructionTypeInfo { - IrInstruction base; +struct IrInstSrcTypeInfo { + IrInstSrc base; - IrInstruction *type_value; + IrInstSrc *type_value; }; -struct IrInstructionType { - IrInstruction base; +struct IrInstSrcType { + IrInstSrc base; - IrInstruction *type_info; + IrInstSrc *type_info; }; -struct IrInstructionHasField { - IrInstruction base; +struct IrInstSrcHasField { + IrInstSrc base; - IrInstruction *container_type; - IrInstruction *field_name; + IrInstSrc *container_type; + IrInstSrc *field_name; }; -struct IrInstructionTypeId { - IrInstruction base; +struct IrInstSrcTypeId { + IrInstSrc base; - IrInstruction *type_value; + IrInstSrc *type_value; }; -struct IrInstructionSetEvalBranchQuota { - IrInstruction base; +struct IrInstSrcSetEvalBranchQuota { + IrInstSrc base; - IrInstruction *new_quota; + IrInstSrc *new_quota; }; -struct IrInstructionAlignCast { - IrInstruction base; +struct IrInstSrcAlignCast { + IrInstSrc base; - IrInstruction *align_bytes; - IrInstruction *target; + IrInstSrc *align_bytes; + IrInstSrc *target; }; -struct IrInstructionOpaqueType { - IrInstruction base; +struct IrInstGenAlignCast { + IrInstGen base; + + IrInstGen *target; }; -struct IrInstructionSetAlignStack { - IrInstruction base; - - IrInstruction *align_bytes; +struct IrInstSrcOpaqueType { + IrInstSrc base; }; -struct IrInstructionArgType { - IrInstruction base; +struct IrInstSrcSetAlignStack { + IrInstSrc base; - IrInstruction *fn_type; - IrInstruction *arg_index; + IrInstSrc *align_bytes; +}; + +struct IrInstSrcArgType { + IrInstSrc base; + + IrInstSrc *fn_type; + IrInstSrc *arg_index; bool allow_var; }; -struct IrInstructionExport { - IrInstruction base; +struct IrInstSrcExport { + IrInstSrc base; - IrInstruction *target; - IrInstruction *options; + IrInstSrc *target; + IrInstSrc *options; }; -struct IrInstructionErrorReturnTrace { - IrInstruction base; - - enum Optional { - Null, - NonNull, - } optional; +enum IrInstErrorReturnTraceOptional { + IrInstErrorReturnTraceNull, + IrInstErrorReturnTraceNonNull, }; -struct IrInstructionErrorUnion { - IrInstruction base; +struct IrInstSrcErrorReturnTrace { + IrInstSrc base; - IrInstruction *err_set; - IrInstruction *payload; + IrInstErrorReturnTraceOptional optional; +}; + +struct IrInstGenErrorReturnTrace { + IrInstGen base; + + IrInstErrorReturnTraceOptional optional; +}; + +struct IrInstSrcErrorUnion { + IrInstSrc base; + + IrInstSrc *err_set; + IrInstSrc *payload; Buf *type_name; }; -struct IrInstructionAtomicRmw { - IrInstruction base; +struct IrInstSrcAtomicRmw { + IrInstSrc base; - IrInstruction *operand_type; - IrInstruction *ptr; - IrInstruction *op; - AtomicRmwOp resolved_op; - IrInstruction *operand; - IrInstruction *ordering; - AtomicOrder resolved_ordering; + IrInstSrc *operand_type; + IrInstSrc *ptr; + IrInstSrc *op; + IrInstSrc *operand; + IrInstSrc *ordering; }; -struct IrInstructionAtomicLoad { - IrInstruction base; +struct IrInstGenAtomicRmw { + IrInstGen base; - IrInstruction *operand_type; - IrInstruction *ptr; - IrInstruction *ordering; - AtomicOrder resolved_ordering; + IrInstGen *ptr; + IrInstGen *operand; + AtomicRmwOp op; + AtomicOrder ordering; }; -struct IrInstructionAtomicStore { - IrInstruction base; +struct IrInstSrcAtomicLoad { + IrInstSrc base; - IrInstruction *operand_type; - IrInstruction *ptr; - IrInstruction *value; - IrInstruction *ordering; - AtomicOrder resolved_ordering; + IrInstSrc *operand_type; + IrInstSrc *ptr; + IrInstSrc *ordering; }; -struct IrInstructionSaveErrRetAddr { - IrInstruction base; +struct IrInstGenAtomicLoad { + IrInstGen base; + + IrInstGen *ptr; + AtomicOrder ordering; }; -struct IrInstructionAddImplicitReturnType { - IrInstruction base; +struct IrInstSrcAtomicStore { + IrInstSrc base; - IrInstruction *value; + IrInstSrc *operand_type; + IrInstSrc *ptr; + IrInstSrc *value; + IrInstSrc *ordering; +}; + +struct IrInstGenAtomicStore { + IrInstGen base; + + IrInstGen *ptr; + IrInstGen *value; + AtomicOrder ordering; +}; + +struct IrInstSrcSaveErrRetAddr { + IrInstSrc base; +}; + +struct IrInstGenSaveErrRetAddr { + IrInstGen base; +}; + +struct IrInstSrcAddImplicitReturnType { + IrInstSrc base; + + IrInstSrc *value; ResultLocReturn *result_loc_ret; }; -// For float ops which take a single argument -struct IrInstructionFloatOp { - IrInstruction base; +// For float ops that take a single argument +struct IrInstSrcFloatOp { + IrInstSrc base; + IrInstSrc *operand; BuiltinFnId fn_id; - IrInstruction *operand; }; -struct IrInstructionCheckRuntimeScope { - IrInstruction base; +struct IrInstGenFloatOp { + IrInstGen base; - IrInstruction *scope_is_comptime; - IrInstruction *is_comptime; + IrInstGen *operand; + BuiltinFnId fn_id; }; -struct IrInstructionBswap { - IrInstruction base; +struct IrInstSrcCheckRuntimeScope { + IrInstSrc base; - IrInstruction *type; - IrInstruction *op; + IrInstSrc *scope_is_comptime; + IrInstSrc *is_comptime; }; -struct IrInstructionBitReverse { - IrInstruction base; +struct IrInstSrcBswap { + IrInstSrc base; - IrInstruction *type; - IrInstruction *op; + IrInstSrc *type; + IrInstSrc *op; }; -struct IrInstructionArrayToVector { - IrInstruction base; +struct IrInstGenBswap { + IrInstGen base; - IrInstruction *array; + IrInstGen *op; }; -struct IrInstructionVectorToArray { - IrInstruction base; +struct IrInstSrcBitReverse { + IrInstSrc base; - IrInstruction *vector; - IrInstruction *result_loc; + IrInstSrc *type; + IrInstSrc *op; }; -struct IrInstructionShuffleVector { - IrInstruction base; +struct IrInstGenBitReverse { + IrInstGen base; - IrInstruction *scalar_type; - IrInstruction *a; - IrInstruction *b; - IrInstruction *mask; // This is in zig-format, not llvm format + IrInstGen *op; }; -struct IrInstructionSplatSrc { - IrInstruction base; +struct IrInstGenArrayToVector { + IrInstGen base; - IrInstruction *len; - IrInstruction *scalar; + IrInstGen *array; }; -struct IrInstructionSplatGen { - IrInstruction base; +struct IrInstGenVectorToArray { + IrInstGen base; - IrInstruction *scalar; + IrInstGen *vector; + IrInstGen *result_loc; }; -struct IrInstructionAssertZero { - IrInstruction base; +struct IrInstSrcShuffleVector { + IrInstSrc base; - IrInstruction *target; + IrInstSrc *scalar_type; + IrInstSrc *a; + IrInstSrc *b; + IrInstSrc *mask; // This is in zig-format, not llvm format }; -struct IrInstructionAssertNonNull { - IrInstruction base; +struct IrInstGenShuffleVector { + IrInstGen base; - IrInstruction *target; + IrInstGen *a; + IrInstGen *b; + IrInstGen *mask; // This is in zig-format, not llvm format }; -struct IrInstructionUnionInitNamedField { - IrInstruction base; +struct IrInstSrcSplat { + IrInstSrc base; - IrInstruction *union_type; - IrInstruction *field_name; - IrInstruction *field_result_loc; - IrInstruction *result_loc; + IrInstSrc *len; + IrInstSrc *scalar; }; -struct IrInstructionHasDecl { - IrInstruction base; +struct IrInstGenSplat { + IrInstGen base; - IrInstruction *container; - IrInstruction *name; + IrInstGen *scalar; }; -struct IrInstructionUndeclaredIdent { - IrInstruction base; +struct IrInstGenAssertZero { + IrInstGen base; + + IrInstGen *target; +}; + +struct IrInstGenAssertNonNull { + IrInstGen base; + + IrInstGen *target; +}; + +struct IrInstSrcUnionInitNamedField { + IrInstSrc base; + + IrInstSrc *union_type; + IrInstSrc *field_name; + IrInstSrc *field_result_loc; + IrInstSrc *result_loc; +}; + +struct IrInstSrcHasDecl { + IrInstSrc base; + + IrInstSrc *container; + IrInstSrc *name; +}; + +struct IrInstSrcUndeclaredIdent { + IrInstSrc base; Buf *name; }; -struct IrInstructionAllocaSrc { - IrInstruction base; +struct IrInstSrcAlloca { + IrInstSrc base; - IrInstruction *align; - IrInstruction *is_comptime; + IrInstSrc *align; + IrInstSrc *is_comptime; const char *name_hint; }; -struct IrInstructionAllocaGen { - IrInstruction base; +struct IrInstGenAlloca { + IrInstGen base; uint32_t align; const char *name_hint; size_t field_index; }; -struct IrInstructionEndExpr { - IrInstruction base; +struct IrInstSrcEndExpr { + IrInstSrc base; - IrInstruction *value; + IrInstSrc *value; ResultLoc *result_loc; }; // This one is for writing through the result pointer. -struct IrInstructionResolveResult { - IrInstruction base; +struct IrInstSrcResolveResult { + IrInstSrc base; ResultLoc *result_loc; - IrInstruction *ty; + IrInstSrc *ty; }; -// This one is when you want to read the value of the result. -// You have to give the value in case it is comptime. -struct IrInstructionResultPtr { - IrInstruction base; - - ResultLoc *result_loc; - IrInstruction *result; -}; - -struct IrInstructionResetResult { - IrInstruction base; +struct IrInstSrcResetResult { + IrInstSrc base; ResultLoc *result_loc; }; -struct IrInstructionPtrOfArrayToSlice { - IrInstruction base; +struct IrInstGenPtrOfArrayToSlice { + IrInstGen base; - IrInstruction *operand; - IrInstruction *result_loc; + IrInstGen *operand; + IrInstGen *result_loc; }; -struct IrInstructionSuspendBegin { - IrInstruction base; +struct IrInstSrcSuspendBegin { + IrInstSrc base; +}; + +struct IrInstGenSuspendBegin { + IrInstGen base; LLVMBasicBlockRef resume_bb; }; -struct IrInstructionSuspendFinish { - IrInstruction base; +struct IrInstSrcSuspendFinish { + IrInstSrc base; - IrInstructionSuspendBegin *begin; + IrInstSrcSuspendBegin *begin; }; -struct IrInstructionAwaitSrc { - IrInstruction base; +struct IrInstGenSuspendFinish { + IrInstGen base; - IrInstruction *frame; + IrInstGenSuspendBegin *begin; +}; + +struct IrInstSrcAwait { + IrInstSrc base; + + IrInstSrc *frame; ResultLoc *result_loc; }; -struct IrInstructionAwaitGen { - IrInstruction base; +struct IrInstGenAwait { + IrInstGen base; - IrInstruction *frame; - IrInstruction *result_loc; + IrInstGen *frame; + IrInstGen *result_loc; ZigFn *target_fn; }; -struct IrInstructionResume { - IrInstruction base; +struct IrInstSrcResume { + IrInstSrc base; - IrInstruction *frame; + IrInstSrc *frame; +}; + +struct IrInstGenResume { + IrInstGen base; + + IrInstGen *frame; }; enum SpillId { @@ -4045,24 +4507,37 @@ enum SpillId { SpillIdRetErrCode, }; -struct IrInstructionSpillBegin { - IrInstruction base; +struct IrInstSrcSpillBegin { + IrInstSrc base; + + IrInstSrc *operand; + SpillId spill_id; +}; + +struct IrInstGenSpillBegin { + IrInstGen base; SpillId spill_id; - IrInstruction *operand; + IrInstGen *operand; }; -struct IrInstructionSpillEnd { - IrInstruction base; +struct IrInstSrcSpillEnd { + IrInstSrc base; - IrInstructionSpillBegin *begin; + IrInstSrcSpillBegin *begin; }; -struct IrInstructionVectorExtractElem { - IrInstruction base; +struct IrInstGenSpillEnd { + IrInstGen base; - IrInstruction *vector; - IrInstruction *index; + IrInstGenSpillBegin *begin; +}; + +struct IrInstGenVectorExtractElem { + IrInstGen base; + + IrInstGen *vector; + IrInstGen *index; }; enum ResultLocId { @@ -4083,9 +4558,9 @@ struct ResultLoc { ResultLocId id; bool written; bool allow_write_through_const; - IrInstruction *resolved_loc; // result ptr - IrInstruction *source_instruction; - IrInstruction *gen_instruction; // value to store to the result loc + IrInstGen *resolved_loc; // result ptr + IrInstSrc *source_instruction; + IrInstGen *gen_instruction; // value to store to the result loc ZigType *implicit_elem_type; }; @@ -4115,18 +4590,18 @@ struct ResultLocPeerParent { bool skipped; bool done_resuming; - IrBasicBlock *end_bb; + IrBasicBlockSrc *end_bb; ResultLoc *parent; ZigList peers; ZigType *resolved_type; - IrInstruction *is_comptime; + IrInstSrc *is_comptime; }; struct ResultLocPeer { ResultLoc base; ResultLocPeerParent *parent; - IrBasicBlock *next_bb; + IrBasicBlockSrc *next_bb; IrSuspendPosition suspend_pos; }; @@ -4197,7 +4672,7 @@ struct FnWalkAttrs { struct FnWalkCall { ZigList *gen_param_values; ZigList *gen_param_types; - IrInstructionCallGen *inst; + IrInstGenCall *inst; bool is_var_args; }; diff --git a/src/analyze.cpp b/src/analyze.cpp index 4b3b024b53..fe274195ef 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -199,7 +199,7 @@ ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent) { return scope; } -Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime) { +Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstSrc *is_comptime) { ScopeRuntime *scope = allocate(1); scope->is_comptime = is_comptime; init_scope(g, &scope->base, ScopeIdRuntime, node, parent); @@ -1120,7 +1120,7 @@ ZigValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType * &backward_branch_count, &backward_branch_quota, nullptr, nullptr, node, type_name, nullptr, nullptr, undef))) { - return g->invalid_instruction->value; + return g->invalid_inst_gen->value; } destroy(result_ptr, "ZigValue"); return result; @@ -2586,15 +2586,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { return ErrorSemanticAnalyzeFail; } - enum_type->data.enumeration.src_field_count = field_count; - enum_type->data.enumeration.fields = allocate(field_count); - enum_type->data.enumeration.fields_by_name.init(field_count); - Scope *scope = &enum_type->data.enumeration.decls_scope->base; - HashMap occupied_tag_values = {}; - occupied_tag_values.init(field_count); - ZigType *tag_int_type; if (enum_type->data.enumeration.layout == ContainerLayoutExtern) { tag_int_type = get_c_int_type(g, CIntTypeInt); @@ -2629,13 +2622,14 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { buf_ptr(&wanted_tag_int_type->name))); add_error_note(g, msg, decl_node->data.container_decl.init_arg_expr, buf_sprintf("any integral type of size 8, 16, 32, 64 or 128 bit is valid")); - return ErrorNone; + return ErrorSemanticAnalyzeFail; } } tag_int_type = wanted_tag_int_type; } } + enum_type->data.enumeration.non_exhaustive = false; enum_type->data.enumeration.tag_int_type = tag_int_type; enum_type->size_in_bits = tag_int_type->size_in_bits; enum_type->abi_size = tag_int_type->abi_size; @@ -2644,6 +2638,31 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { BigInt bi_one; bigint_init_unsigned(&bi_one, 1); + AstNode *last_field_node = decl_node->data.container_decl.fields.at(field_count - 1); + if (buf_eql_str(last_field_node->data.struct_field.name, "_")) { + field_count -= 1; + if (field_count > 1 && log2_u64(field_count) == enum_type->size_in_bits) { + add_node_error(g, last_field_node, buf_sprintf("non-exhaustive enum specifies every value")); + enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; + } + if (decl_node->data.container_decl.init_arg_expr == nullptr) { + add_node_error(g, last_field_node, buf_sprintf("non-exhaustive enum must specify size")); + enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; + } + if (last_field_node->data.struct_field.value != nullptr) { + add_node_error(g, last_field_node, buf_sprintf("value assigned to '_' field of non-exhaustive enum")); + enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; + } + enum_type->data.enumeration.non_exhaustive = true; + } + + enum_type->data.enumeration.src_field_count = field_count; + enum_type->data.enumeration.fields = allocate(field_count); + enum_type->data.enumeration.fields_by_name.init(field_count); + + HashMap occupied_tag_values = {}; + occupied_tag_values.init(field_count); + TypeEnumField *last_enum_field = nullptr; for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { @@ -2665,6 +2684,11 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { buf_sprintf("consider 'union(enum)' here")); } + if (buf_eql_str(type_enum_field->name, "_")) { + add_node_error(g, field_node, buf_sprintf("'_' field of non-exhaustive enum must be last")); + enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; + } + auto field_entry = enum_type->data.enumeration.fields_by_name.put_unique(type_enum_field->name, type_enum_field); if (field_entry != nullptr) { ErrorMsg *msg = add_node_error(g, field_node, @@ -3343,7 +3367,7 @@ static void get_fully_qualified_decl_name(CodeGen *g, Buf *buf, Tld *tld, bool i ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value) { ZigFn *fn_entry = allocate(1, "ZigFn"); - fn_entry->ir_executable = allocate(1, "IrExecutablePass1"); + fn_entry->ir_executable = allocate(1, "IrExecutableSrc"); fn_entry->prealloc_backward_branch_quota = default_backward_branch_quota; @@ -4089,7 +4113,7 @@ static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, Sco if (type_is_invalid(result->type)) { dest_decls_scope->any_imports_failed = true; using_namespace->base.resolution = TldResolutionInvalid; - using_namespace->using_namespace_value = g->invalid_instruction->value; + using_namespace->using_namespace_value = g->invalid_inst_gen->value; return; } @@ -4098,7 +4122,7 @@ static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, Sco buf_sprintf("expected struct, enum, or union; found '%s'", buf_ptr(&result->data.x_type->name))); dest_decls_scope->any_imports_failed = true; using_namespace->base.resolution = TldResolutionInvalid; - using_namespace->using_namespace_value = g->invalid_instruction->value; + using_namespace->using_namespace_value = g->invalid_inst_gen->value; return; } } @@ -4659,12 +4683,12 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) { } for (size_t i = 0; i < fn->call_list.length; i += 1) { - IrInstructionCallGen *call = fn->call_list.at(i); + IrInstGenCall *call = fn->call_list.at(i); if (call->fn_entry == nullptr) { // TODO function pointer call here, could be anything continue; } - switch (analyze_callee_async(g, fn, call->fn_entry, call->base.source_node, must_not_be_async, + switch (analyze_callee_async(g, fn, call->fn_entry, call->base.base.source_node, must_not_be_async, call->modifier)) { case ErrorSemanticAnalyzeFail: @@ -4682,10 +4706,10 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) { } } for (size_t i = 0; i < fn->await_list.length; i += 1) { - IrInstructionAwaitGen *await = fn->await_list.at(i); + IrInstGenAwait *await = fn->await_list.at(i); // TODO If this is a noasync await, it doesn't count // https://github.com/ziglang/zig/issues/3157 - switch (analyze_callee_async(g, fn, await->target_fn, await->base.source_node, must_not_be_async, + switch (analyze_callee_async(g, fn, await->target_fn, await->base.base.source_node, must_not_be_async, CallModifierNone)) { case ErrorSemanticAnalyzeFail: @@ -4782,7 +4806,7 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) { if (g->verbose_ir) { fprintf(stderr, "fn %s() { // (analyzed)\n", buf_ptr(&fn->symbol_name)); - ir_print(g, stderr, &fn->analyzed_executable, 4, IrPassGen); + ir_print_gen(g, stderr, &fn->analyzed_executable, 4); fprintf(stderr, "}\n"); } fn->anal_state = FnAnalStateComplete; @@ -4825,7 +4849,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { fprintf(stderr, "\n"); ast_render(stderr, fn_table_entry->body_node, 4); fprintf(stderr, "\nfn %s() { // (IR)\n", buf_ptr(&fn_table_entry->symbol_name)); - ir_print(g, stderr, fn_table_entry->ir_executable, 4, IrPassSrc); + ir_print_src(g, stderr, fn_table_entry->ir_executable, 4); fprintf(stderr, "}\n"); } @@ -6189,13 +6213,13 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { ZigType *fn_type = get_async_fn_type(g, fn->type_entry); if (fn->analyzed_executable.need_err_code_spill) { - IrInstructionAllocaGen *alloca_gen = allocate(1); - alloca_gen->base.id = IrInstructionIdAllocaGen; - alloca_gen->base.source_node = fn->proto_node; - alloca_gen->base.scope = fn->child_scope; + IrInstGenAlloca *alloca_gen = allocate(1); + alloca_gen->base.id = IrInstGenIdAlloca; + alloca_gen->base.base.source_node = fn->proto_node; + alloca_gen->base.base.scope = fn->child_scope; alloca_gen->base.value = allocate(1, "ZigValue"); alloca_gen->base.value->type = get_pointer_to_type(g, g->builtin_types.entry_global_error_set, false); - alloca_gen->base.ref_count = 1; + alloca_gen->base.base.ref_count = 1; alloca_gen->name_hint = ""; fn->alloca_gen_list.append(alloca_gen); fn->err_code_spill = &alloca_gen->base; @@ -6203,18 +6227,18 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { ZigType *largest_call_frame_type = nullptr; // Later we'll change this to be largest_call_frame_type instead of void. - IrInstruction *all_calls_alloca = ir_create_alloca(g, &fn->fndef_scope->base, fn->body_node, + IrInstGen *all_calls_alloca = ir_create_alloca(g, &fn->fndef_scope->base, fn->body_node, fn, g->builtin_types.entry_void, "@async_call_frame"); for (size_t i = 0; i < fn->call_list.length; i += 1) { - IrInstructionCallGen *call = fn->call_list.at(i); + IrInstGenCall *call = fn->call_list.at(i); if (call->new_stack != nullptr) { // don't need to allocate a frame for this continue; } ZigFn *callee = call->fn_entry; if (callee == nullptr) { - add_node_error(g, call->base.source_node, + add_node_error(g, call->base.base.source_node, buf_sprintf("function is not comptime-known; @asyncCall required")); return ErrorSemanticAnalyzeFail; } @@ -6224,14 +6248,14 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { if (callee->anal_state == FnAnalStateProbing) { ErrorMsg *msg = add_node_error(g, fn->proto_node, buf_sprintf("unable to determine async function frame of '%s'", buf_ptr(&fn->symbol_name))); - g->trace_err = add_error_note(g, msg, call->base.source_node, + g->trace_err = add_error_note(g, msg, call->base.base.source_node, buf_sprintf("analysis of function '%s' depends on the frame", buf_ptr(&callee->symbol_name))); return ErrorSemanticAnalyzeFail; } ZigType *callee_frame_type = get_fn_frame_type(g, callee); frame_type->data.frame.resolve_loop_type = callee_frame_type; - frame_type->data.frame.resolve_loop_src_node = call->base.source_node; + frame_type->data.frame.resolve_loop_src_node = call->base.base.source_node; analyze_fn_body(g, callee); if (callee->anal_state == FnAnalStateInvalid) { @@ -6247,7 +6271,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { if (!fn_is_async(callee)) continue; - mark_suspension_point(call->base.scope); + mark_suspension_point(call->base.base.scope); if ((err = type_resolve(g, callee_frame_type, ResolveStatusSizeKnown))) { return err; @@ -6269,7 +6293,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { // For example: foo() + await z // The funtion call result of foo() must be spilled. for (size_t i = 0; i < fn->await_list.length; i += 1) { - IrInstructionAwaitGen *await = fn->await_list.at(i); + IrInstGenAwait *await = fn->await_list.at(i); // TODO If this is a noasync await, it doesn't suspend // https://github.com/ziglang/zig/issues/3157 if (await->base.value->special != ConstValSpecialRuntime) { @@ -6291,52 +6315,51 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { } // This await is a suspend point, but it might not need a spill. // We do need to mark the ExprScope as having a suspend point in it. - mark_suspension_point(await->base.scope); + mark_suspension_point(await->base.base.scope); if (await->result_loc != nullptr) { // If there's a result location, that is the spill continue; } - if (await->base.ref_count == 0) + if (await->base.base.ref_count == 0) continue; if (!type_has_bits(await->base.value->type)) continue; - await->result_loc = ir_create_alloca(g, await->base.scope, await->base.source_node, fn, + await->result_loc = ir_create_alloca(g, await->base.base.scope, await->base.base.source_node, fn, await->base.value->type, ""); } for (size_t block_i = 0; block_i < fn->analyzed_executable.basic_block_list.length; block_i += 1) { - IrBasicBlock *block = fn->analyzed_executable.basic_block_list.at(block_i); + IrBasicBlockGen *block = fn->analyzed_executable.basic_block_list.at(block_i); for (size_t instr_i = 0; instr_i < block->instruction_list.length; instr_i += 1) { - IrInstruction *instruction = block->instruction_list.at(instr_i); - if (instruction->id == IrInstructionIdSuspendFinish) { - mark_suspension_point(instruction->scope); + IrInstGen *instruction = block->instruction_list.at(instr_i); + if (instruction->id == IrInstGenIdSuspendFinish) { + mark_suspension_point(instruction->base.scope); } } } // Now that we've marked all the expr scopes that have to spill, we go over the instructions // and spill the relevant ones. for (size_t block_i = 0; block_i < fn->analyzed_executable.basic_block_list.length; block_i += 1) { - IrBasicBlock *block = fn->analyzed_executable.basic_block_list.at(block_i); + IrBasicBlockGen *block = fn->analyzed_executable.basic_block_list.at(block_i); for (size_t instr_i = 0; instr_i < block->instruction_list.length; instr_i += 1) { - IrInstruction *instruction = block->instruction_list.at(instr_i); - if (instruction->id == IrInstructionIdAwaitGen || - instruction->id == IrInstructionIdVarPtr || - instruction->id == IrInstructionIdDeclRef || - instruction->id == IrInstructionIdAllocaGen) + IrInstGen *instruction = block->instruction_list.at(instr_i); + if (instruction->id == IrInstGenIdAwait || + instruction->id == IrInstGenIdVarPtr || + instruction->id == IrInstGenIdAlloca) { // This instruction does its own spilling specially, or otherwise doesn't need it. continue; } if (instruction->value->special != ConstValSpecialRuntime) continue; - if (instruction->ref_count == 0) + if (instruction->base.ref_count == 0) continue; if ((err = type_resolve(g, instruction->value->type, ResolveStatusZeroBitsKnown))) return ErrorSemanticAnalyzeFail; if (!type_has_bits(instruction->value->type)) continue; - if (scope_needs_spill(instruction->scope)) { - instruction->spill = ir_create_alloca(g, instruction->scope, instruction->source_node, + if (scope_needs_spill(instruction->base.scope)) { + instruction->spill = ir_create_alloca(g, instruction->base.scope, instruction->base.source_node, fn, instruction->value->type, ""); } } @@ -6387,14 +6410,14 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { } for (size_t alloca_i = 0; alloca_i < fn->alloca_gen_list.length; alloca_i += 1) { - IrInstructionAllocaGen *instruction = fn->alloca_gen_list.at(alloca_i); + IrInstGenAlloca *instruction = fn->alloca_gen_list.at(alloca_i); instruction->field_index = SIZE_MAX; ZigType *ptr_type = instruction->base.value->type; assert(ptr_type->id == ZigTypeIdPointer); ZigType *child_type = ptr_type->data.pointer.child_type; if (!type_has_bits(child_type)) continue; - if (instruction->base.ref_count == 0) + if (instruction->base.base.ref_count == 0) continue; if (instruction->base.value->special != ConstValSpecialRuntime) { if (const_ptr_pointee(nullptr, g, instruction->base.value, nullptr)->special != @@ -6405,7 +6428,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { } frame_type->data.frame.resolve_loop_type = child_type; - frame_type->data.frame.resolve_loop_src_node = instruction->base.source_node; + frame_type->data.frame.resolve_loop_src_node = instruction->base.base.source_node; if ((err = type_resolve(g, child_type, ResolveStatusSizeKnown))) { return err; } @@ -6419,7 +6442,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { instruction->field_index = fields.length; src_assert(child_type->id != ZigTypeIdPointer || child_type->data.pointer.inferred_struct_field == nullptr, - instruction->base.source_node); + instruction->base.base.source_node); fields.append({name, child_type, instruction->align}); } @@ -6552,8 +6575,10 @@ bool ir_get_var_is_comptime(ZigVar *var) { // As an optimization, is_comptime values which are constant are allowed // to be omitted from analysis. In this case, there is no child instruction // and we simply look at the unanalyzed const parent instruction. - assert(var->is_comptime->value->type->id == ZigTypeIdBool); - var->is_comptime_memoized_value = var->is_comptime->value->data.x_bool; + assert(var->is_comptime->id == IrInstSrcIdConst); + IrInstSrcConst *const_inst = reinterpret_cast(var->is_comptime); + assert(const_inst->value->type->id == ZigTypeIdBool); + var->is_comptime_memoized_value = const_inst->value->data.x_bool; var->is_comptime = nullptr; return var->is_comptime_memoized_value; } @@ -8315,7 +8340,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatu uint32_t field_count = enum_type->data.enumeration.src_field_count; - assert(enum_type->data.enumeration.fields); + assert(field_count == 0 || enum_type->data.enumeration.fields != nullptr); ZigLLVMDIEnumerator **di_enumerators = allocate(field_count); for (uint32_t i = 0; i < field_count; i += 1) { @@ -9196,21 +9221,6 @@ void src_assert(bool ok, AstNode *source_node) { stage2_panic(msg, strlen(msg)); } -IrInstruction *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn, - ZigType *var_type, const char *name_hint) -{ - IrInstructionAllocaGen *alloca_gen = allocate(1); - alloca_gen->base.id = IrInstructionIdAllocaGen; - alloca_gen->base.source_node = source_node; - alloca_gen->base.scope = scope; - alloca_gen->base.value = allocate(1, "ZigValue"); - alloca_gen->base.value->type = get_pointer_to_type(g, var_type, false); - alloca_gen->base.ref_count = 1; - alloca_gen->name_hint = name_hint; - fn->alloca_gen_list.append(alloca_gen); - return &alloca_gen->base; -} - Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str, ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path) { @@ -9271,8 +9281,17 @@ Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str, } -void IrExecutable::src() { - IrExecutable *it; +void IrExecutableSrc::src() { + if (this->source_node != nullptr) { + this->source_node->src(); + } + if (this->parent_exec != nullptr) { + this->parent_exec->src(); + } +} + +void IrExecutableGen::src() { + IrExecutableGen *it; for (it = this; it != nullptr && it->source_node != nullptr; it = it->parent_exec) { it->source_node->src(); } @@ -9523,3 +9542,41 @@ static void dump_value_indent(ZigValue *val, int indent) { void ZigValue::dump() { dump_value_indent(this, 0); } + +// float ops that take a single argument +//TODO Powi, Pow, minnum, maxnum, maximum, minimum, copysign, lround, llround, lrint, llrint +const char *float_op_to_name(BuiltinFnId op) { + switch (op) { + case BuiltinFnIdSqrt: + return "sqrt"; + case BuiltinFnIdSin: + return "sin"; + case BuiltinFnIdCos: + return "cos"; + case BuiltinFnIdExp: + return "exp"; + case BuiltinFnIdExp2: + return "exp2"; + case BuiltinFnIdLog: + return "log"; + case BuiltinFnIdLog10: + return "log10"; + case BuiltinFnIdLog2: + return "log2"; + case BuiltinFnIdFabs: + return "fabs"; + case BuiltinFnIdFloor: + return "floor"; + case BuiltinFnIdCeil: + return "ceil"; + case BuiltinFnIdTrunc: + return "trunc"; + case BuiltinFnIdNearbyInt: + return "nearbyint"; + case BuiltinFnIdRound: + return "round"; + default: + zig_unreachable(); + } +} + diff --git a/src/analyze.hpp b/src/analyze.hpp index f79dbbda44..c0026945e2 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -120,7 +120,7 @@ ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent); ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent); ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *fn_entry); Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent); -Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime); +Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstSrc *is_comptime); Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent); ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent); @@ -271,8 +271,6 @@ ZigType *resolve_struct_field_type(CodeGen *g, TypeStructField *struct_field); void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn); -IrInstruction *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn, - ZigType *var_type, const char *name_hint); Error analyze_import(CodeGen *codegen, ZigType *source_import, Buf *import_target_str, ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path); ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry); @@ -281,4 +279,5 @@ void copy_const_val(ZigValue *dest, ZigValue *src); bool type_has_optional_repr(ZigType *ty); bool is_opt_err_set(ZigType *ty); bool type_is_numeric(ZigType *ty); +const char *float_op_to_name(BuiltinFnId op); #endif diff --git a/src/codegen.cpp b/src/codegen.cpp index 6b2b95d246..9a58a8c980 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -31,11 +31,6 @@ enum ResumeId { ResumeIdCall, }; -// TODO https://github.com/ziglang/zig/issues/2883 -// Until then we have this same default as Clang. -// This avoids https://github.com/ziglang/zig/issues/3275 -static const char *riscv_default_features = "+a,+c,+d,+f,+m,+relax"; - static void init_darwin_native(CodeGen *g) { char *osx_target = getenv("MACOSX_DEPLOYMENT_TARGET"); char *ios_target = getenv("IPHONEOS_DEPLOYMENT_TARGET"); @@ -192,7 +187,7 @@ static void generate_error_name_table(CodeGen *g); static bool value_is_all_undef(CodeGen *g, ZigValue *const_val); static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr); static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment); -static LLVMValueRef gen_await_early_return(CodeGen *g, IrInstruction *source_instr, +static LLVMValueRef gen_await_early_return(CodeGen *g, IrInstGen *source_instr, LLVMValueRef target_frame_ptr, ZigType *result_type, ZigType *ptr_result_type, LLVMValueRef result_loc, bool non_async); static Error get_tmp_filename(CodeGen *g, Buf *out, Buf *suffix); @@ -878,14 +873,14 @@ static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, ZigType *type } } -static void ir_assert(bool ok, IrInstruction *source_instruction) { +static void ir_assert(bool ok, IrInstGen *source_instruction) { if (ok) return; - src_assert(ok, source_instruction->source_node); + src_assert(ok, source_instruction->base.source_node); } -static bool ir_want_fast_math(CodeGen *g, IrInstruction *instruction) { +static bool ir_want_fast_math(CodeGen *g, IrInstGen *instruction) { // TODO memoize - Scope *scope = instruction->scope; + Scope *scope = instruction->base.scope; while (scope) { if (scope->id == ScopeIdBlock) { ScopeBlock *block_scope = (ScopeBlock *)scope; @@ -920,8 +915,8 @@ static bool ir_want_runtime_safety_scope(CodeGen *g, Scope *scope) { g->build_mode != BuildModeSmallRelease); } -static bool ir_want_runtime_safety(CodeGen *g, IrInstruction *instruction) { - return ir_want_runtime_safety_scope(g, instruction->scope); +static bool ir_want_runtime_safety(CodeGen *g, IrInstGen *instruction) { + return ir_want_runtime_safety_scope(g, instruction->base.scope); } static Buf *panic_msg_buf(PanicMsgId msg_id) { @@ -1047,8 +1042,8 @@ static void gen_assertion_scope(CodeGen *g, PanicMsgId msg_id, Scope *source_sco } } -static void gen_assertion(CodeGen *g, PanicMsgId msg_id, IrInstruction *source_instruction) { - return gen_assertion_scope(g, msg_id, source_instruction->scope); +static void gen_assertion(CodeGen *g, PanicMsgId msg_id, IrInstGen *source_instruction) { + return gen_assertion_scope(g, msg_id, source_instruction->base.scope); } static LLVMValueRef get_stacksave_fn_val(CodeGen *g) { @@ -1762,7 +1757,7 @@ static void gen_var_debug_decl(CodeGen *g, ZigVar *var) { LLVMGetInsertBlock(g->builder)); } -static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) { +static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstGen *instruction) { Error err; bool value_has_bits; @@ -1773,8 +1768,8 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) { return nullptr; if (!instruction->llvm_value) { - if (instruction->id == IrInstructionIdAwaitGen) { - IrInstructionAwaitGen *await = reinterpret_cast(instruction); + if (instruction->id == IrInstGenIdAwait) { + IrInstGenAwait *await = reinterpret_cast(instruction); if (await->result_loc != nullptr) { return get_handle_value(g, ir_llvm_value(g, await->result_loc), await->result_loc->value->type->data.pointer.child_type, await->result_loc->value->type); @@ -1857,9 +1852,9 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ case FnWalkIdCall: { if (src_i >= fn_walk->data.call.inst->arg_count) return false; - IrInstruction *arg = fn_walk->data.call.inst->args[src_i]; + IrInstGen *arg = fn_walk->data.call.inst->args[src_i]; ty = arg->value->type; - source_node = arg->source_node; + source_node = arg->base.source_node; val = ir_llvm_value(g, arg); break; } @@ -2092,10 +2087,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) { return; } if (fn_walk->id == FnWalkIdCall) { - IrInstructionCallGen *instruction = fn_walk->data.call.inst; + IrInstGenCall *instruction = fn_walk->data.call.inst; bool is_var_args = fn_walk->data.call.is_var_args; for (size_t call_i = 0; call_i < instruction->arg_count; call_i += 1) { - IrInstruction *param_instruction = instruction->args[call_i]; + IrInstGen *param_instruction = instruction->args[call_i]; ZigType *param_type = param_instruction->value->type; if (is_var_args || type_has_bits(param_type)) { LLVMValueRef param_value = ir_llvm_value(g, param_instruction); @@ -2310,14 +2305,14 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { return fn_val; } -static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *executable, - IrInstructionSaveErrRetAddr *save_err_ret_addr_instruction) +static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutableGen *executable, + IrInstGenSaveErrRetAddr *save_err_ret_addr_instruction) { assert(g->have_err_ret_tracing); LLVMValueRef return_err_fn = get_return_err_fn(g); bool is_llvm_alloca; - LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, save_err_ret_addr_instruction->base.scope, + LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, save_err_ret_addr_instruction->base.base.scope, &is_llvm_alloca); ZigLLVMBuildCall(g->builder, return_err_fn, &my_err_trace_val, 1, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); @@ -2332,7 +2327,7 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut return nullptr; } -static void gen_assert_resume_id(CodeGen *g, IrInstruction *source_instr, ResumeId resume_id, PanicMsgId msg_id, +static void gen_assert_resume_id(CodeGen *g, IrInstGen *source_instr, ResumeId resume_id, PanicMsgId msg_id, LLVMBasicBlockRef end_bb) { LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; @@ -2409,7 +2404,7 @@ static LLVMValueRef gen_maybe_atomic_op(CodeGen *g, LLVMAtomicRMWBinOp op, LLVMV } } -static void gen_async_return(CodeGen *g, IrInstructionReturn *instruction) { +static void gen_async_return(CodeGen *g, IrInstGenReturn *instruction) { LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; ZigType *operand_type = (instruction->operand != nullptr) ? instruction->operand->value->type : nullptr; @@ -2488,7 +2483,7 @@ static void gen_async_return(CodeGen *g, IrInstructionReturn *instruction) { frame_index_trace_arg(g, ret_type) + 1, ""); LLVMValueRef dest_trace_ptr = LLVMBuildLoad(g->builder, awaiter_trace_ptr_ptr, ""); bool is_llvm_alloca; - LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca); + LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, instruction->base.base.scope, &is_llvm_alloca); LLVMValueRef args[] = { dest_trace_ptr, my_err_trace_val }; ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); @@ -2503,7 +2498,7 @@ static void gen_async_return(CodeGen *g, IrInstructionReturn *instruction) { LLVMBuildRetVoid(g->builder); } -static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *instruction) { +static LLVMValueRef ir_render_return(CodeGen *g, IrExecutableGen *executable, IrInstGenReturn *instruction) { if (fn_is_async(g->cur_fn)) { gen_async_return(g, instruction); return nullptr; @@ -2844,12 +2839,12 @@ static LLVMValueRef gen_rem(CodeGen *g, bool want_runtime_safety, bool want_fast } -static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, - IrInstructionBinOp *bin_op_instruction) +static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutableGen *executable, + IrInstGenBinOp *bin_op_instruction) { IrBinOp op_id = bin_op_instruction->op_id; - IrInstruction *op1 = bin_op_instruction->op1; - IrInstruction *op2 = bin_op_instruction->op2; + IrInstGen *op1 = bin_op_instruction->op1; + IrInstGen *op2 = bin_op_instruction->op2; ZigType *operand_type = op1->value->type; ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type; @@ -3054,8 +3049,8 @@ static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *in } } -static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable, - IrInstructionResizeSlice *instruction) +static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutableGen *executable, + IrInstGenResizeSlice *instruction) { ZigType *actual_type = instruction->operand->value->type; ZigType *wanted_type = instruction->base.value->type; @@ -3122,8 +3117,8 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable, return result_loc; } -static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, - IrInstructionCast *cast_instruction) +static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutableGen *executable, + IrInstGenCast *cast_instruction) { ZigType *actual_type = cast_instruction->value->value->type; ZigType *wanted_type = cast_instruction->base.value->type; @@ -3200,8 +3195,8 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, zig_unreachable(); } -static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutable *executable, - IrInstructionPtrOfArrayToSlice *instruction) +static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutableGen *executable, + IrInstGenPtrOfArrayToSlice *instruction) { ZigType *actual_type = instruction->operand->value->type; ZigType *slice_type = instruction->base.value->type; @@ -3237,8 +3232,8 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutable *ex return result_loc; } -static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable, - IrInstructionPtrCastGen *instruction) +static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutableGen *executable, + IrInstGenPtrCast *instruction) { ZigType *wanted_type = instruction->base.value->type; if (!type_has_bits(wanted_type)) { @@ -3263,8 +3258,8 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable, return result_ptr; } -static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable, - IrInstructionBitCastGen *instruction) +static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutableGen *executable, + IrInstGenBitCast *instruction) { ZigType *wanted_type = instruction->base.value->type; ZigType *actual_type = instruction->operand->value->type; @@ -3287,8 +3282,8 @@ static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable, } } -static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executable, - IrInstructionWidenOrShorten *instruction) +static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutableGen *executable, + IrInstGenWidenOrShorten *instruction) { ZigType *actual_type = instruction->target->value->type; // TODO instead of this logic, use the Noop instruction to change the type from @@ -3304,7 +3299,7 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executa instruction->base.value->type, target_val); } -static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, IrExecutable *executable, IrInstructionIntToPtr *instruction) { +static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, IrExecutableGen *executable, IrInstGenIntToPtr *instruction) { ZigType *wanted_type = instruction->base.value->type; LLVMValueRef target_val = ir_llvm_value(g, instruction->target); @@ -3342,13 +3337,13 @@ static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, IrExecutable *executable, I return LLVMBuildIntToPtr(g->builder, target_val, get_llvm_type(g, wanted_type), ""); } -static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, IrExecutable *executable, IrInstructionPtrToInt *instruction) { +static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, IrExecutableGen *executable, IrInstGenPtrToInt *instruction) { ZigType *wanted_type = instruction->base.value->type; LLVMValueRef target_val = ir_llvm_value(g, instruction->target); return LLVMBuildPtrToInt(g->builder, target_val, get_llvm_type(g, wanted_type), ""); } -static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, IrInstructionIntToEnum *instruction) { +static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutableGen *executable, IrInstGenIntToEnum *instruction) { ZigType *wanted_type = instruction->base.value->type; assert(wanted_type->id == ZigTypeIdEnum); ZigType *tag_int_type = wanted_type->data.enumeration.tag_int_type; @@ -3357,7 +3352,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, LLVMValueRef tag_int_value = gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base), instruction->target->value->type, tag_int_type, target_val); - if (ir_want_runtime_safety(g, &instruction->base) && wanted_type->data.enumeration.layout != ContainerLayoutExtern) { + if (ir_want_runtime_safety(g, &instruction->base) && !wanted_type->data.enumeration.non_exhaustive) { LLVMBasicBlockRef bad_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadValue"); LLVMBasicBlockRef ok_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "OkValue"); size_t field_count = wanted_type->data.enumeration.src_field_count; @@ -3375,7 +3370,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, return tag_int_value; } -static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, IrInstructionIntToErr *instruction) { +static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutableGen *executable, IrInstGenIntToErr *instruction) { ZigType *wanted_type = instruction->base.value->type; assert(wanted_type->id == ZigTypeIdErrorSet); @@ -3392,7 +3387,7 @@ static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, I return gen_widen_or_shorten(g, false, actual_type, g->err_tag_type, target_val); } -static LLVMValueRef ir_render_err_to_int(CodeGen *g, IrExecutable *executable, IrInstructionErrToInt *instruction) { +static LLVMValueRef ir_render_err_to_int(CodeGen *g, IrExecutableGen *executable, IrInstGenErrToInt *instruction) { ZigType *wanted_type = instruction->base.value->type; assert(wanted_type->id == ZigTypeIdInt); assert(!wanted_type->data.integral.is_signed); @@ -3418,8 +3413,8 @@ static LLVMValueRef ir_render_err_to_int(CodeGen *g, IrExecutable *executable, I } } -static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutable *executable, - IrInstructionUnreachable *unreachable_instruction) +static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutableGen *executable, + IrInstGenUnreachable *unreachable_instruction) { if (ir_want_runtime_safety(g, &unreachable_instruction->base)) { gen_safety_crash(g, PanicMsgIdUnreachable); @@ -3429,8 +3424,8 @@ static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutable *executable, return nullptr; } -static LLVMValueRef ir_render_cond_br(CodeGen *g, IrExecutable *executable, - IrInstructionCondBr *cond_br_instruction) +static LLVMValueRef ir_render_cond_br(CodeGen *g, IrExecutableGen *executable, + IrInstGenCondBr *cond_br_instruction) { LLVMBuildCondBr(g->builder, ir_llvm_value(g, cond_br_instruction->condition), @@ -3439,51 +3434,56 @@ static LLVMValueRef ir_render_cond_br(CodeGen *g, IrExecutable *executable, return nullptr; } -static LLVMValueRef ir_render_br(CodeGen *g, IrExecutable *executable, IrInstructionBr *br_instruction) { +static LLVMValueRef ir_render_br(CodeGen *g, IrExecutableGen *executable, IrInstGenBr *br_instruction) { LLVMBuildBr(g->builder, br_instruction->dest_block->llvm_block); return nullptr; } -static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInstructionUnOp *un_op_instruction) { - IrUnOp op_id = un_op_instruction->op_id; - LLVMValueRef expr = ir_llvm_value(g, un_op_instruction->value); - ZigType *operand_type = un_op_instruction->value->value->type; - ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type; - - switch (op_id) { - case IrUnOpInvalid: - case IrUnOpOptional: - case IrUnOpDereference: - zig_unreachable(); - case IrUnOpNegation: - case IrUnOpNegationWrap: - { - if (scalar_type->id == ZigTypeIdFloat) { - ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &un_op_instruction->base)); - return LLVMBuildFNeg(g->builder, expr, ""); - } else if (scalar_type->id == ZigTypeIdInt) { - if (op_id == IrUnOpNegationWrap) { - return LLVMBuildNeg(g->builder, expr, ""); - } else if (ir_want_runtime_safety(g, &un_op_instruction->base)) { - LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr)); - return gen_overflow_op(g, operand_type, AddSubMulSub, zero, expr); - } else if (scalar_type->data.integral.is_signed) { - return LLVMBuildNSWNeg(g->builder, expr, ""); - } else { - return LLVMBuildNUWNeg(g->builder, expr, ""); - } - } else { - zig_unreachable(); - } - } - case IrUnOpBinNot: - return LLVMBuildNot(g->builder, expr, ""); - } - - zig_unreachable(); +static LLVMValueRef ir_render_binary_not(CodeGen *g, IrExecutableGen *executable, + IrInstGenBinaryNot *inst) +{ + LLVMValueRef operand = ir_llvm_value(g, inst->operand); + return LLVMBuildNot(g->builder, operand, ""); } -static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrInstructionBoolNot *instruction) { +static LLVMValueRef ir_gen_negation(CodeGen *g, IrInstGen *inst, IrInstGen *operand, bool wrapping) { + LLVMValueRef llvm_operand = ir_llvm_value(g, operand); + ZigType *operand_type = operand->value->type; + ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? + operand_type->data.vector.elem_type : operand_type; + + if (scalar_type->id == ZigTypeIdFloat) { + ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, inst)); + return LLVMBuildFNeg(g->builder, llvm_operand, ""); + } else if (scalar_type->id == ZigTypeIdInt) { + if (wrapping) { + return LLVMBuildNeg(g->builder, llvm_operand, ""); + } else if (ir_want_runtime_safety(g, inst)) { + LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(llvm_operand)); + return gen_overflow_op(g, operand_type, AddSubMulSub, zero, llvm_operand); + } else if (scalar_type->data.integral.is_signed) { + return LLVMBuildNSWNeg(g->builder, llvm_operand, ""); + } else { + return LLVMBuildNUWNeg(g->builder, llvm_operand, ""); + } + } else { + zig_unreachable(); + } +} + +static LLVMValueRef ir_render_negation(CodeGen *g, IrExecutableGen *executable, + IrInstGenNegation *inst) +{ + return ir_gen_negation(g, &inst->base, inst->operand, false); +} + +static LLVMValueRef ir_render_negation_wrapping(CodeGen *g, IrExecutableGen *executable, + IrInstGenNegationWrapping *inst) +{ + return ir_gen_negation(g, &inst->base, inst->operand, true); +} + +static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutableGen *executable, IrInstGenBoolNot *instruction) { LLVMValueRef value = ir_llvm_value(g, instruction->value); LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(value)); return LLVMBuildICmp(g->builder, LLVMIntEQ, value, zero, ""); @@ -3497,14 +3497,14 @@ static void render_decl_var(CodeGen *g, ZigVar *var) { gen_var_debug_decl(g, var); } -static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, IrInstructionDeclVarGen *instruction) { +static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutableGen *executable, IrInstGenDeclVar *instruction) { instruction->var->ptr_instruction = instruction->var_ptr; render_decl_var(g, instruction->var); return nullptr; } -static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, - IrInstructionLoadPtrGen *instruction) +static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutableGen *executable, + IrInstGenLoadPtr *instruction) { ZigType *child_type = instruction->base.value->type; if (!type_has_bits(child_type)) @@ -3706,7 +3706,7 @@ static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_ } } -static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) { +static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutableGen *executable, IrInstGenStorePtr *instruction) { Error err; ZigType *ptr_type = instruction->ptr->value->type; @@ -3716,7 +3716,7 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir codegen_report_errors_and_exit(g); if (!ptr_type_has_bits) return nullptr; - if (instruction->ptr->ref_count == 0) { + if (instruction->ptr->base.ref_count == 0) { // In this case, this StorePtr instruction should be elided. Something happened like this: // var t = true; // const x = if (t) Num.Two else unreachable; @@ -3738,8 +3738,8 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir return nullptr; } -static LLVMValueRef ir_render_vector_store_elem(CodeGen *g, IrExecutable *executable, - IrInstructionVectorStoreElem *instruction) +static LLVMValueRef ir_render_vector_store_elem(CodeGen *g, IrExecutableGen *executable, + IrInstGenVectorStoreElem *instruction) { LLVMValueRef vector_ptr = ir_llvm_value(g, instruction->vector_ptr); LLVMValueRef index = ir_llvm_value(g, instruction->index); @@ -3751,7 +3751,7 @@ static LLVMValueRef ir_render_vector_store_elem(CodeGen *g, IrExecutable *execut return nullptr; } -static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) { +static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutableGen *executable, IrInstGenVarPtr *instruction) { if (instruction->base.value->special != ConstValSpecialRuntime) return ir_llvm_value(g, &instruction->base); ZigVar *var = instruction->var; @@ -3763,8 +3763,8 @@ static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrIn } } -static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutable *executable, - IrInstructionReturnPtr *instruction) +static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutableGen *executable, + IrInstGenReturnPtr *instruction) { if (!type_has_bits(instruction->base.value->type)) return nullptr; @@ -3772,7 +3772,7 @@ static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutable *executable, return g->cur_ret_ptr; } -static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrInstructionElemPtr *instruction) { +static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutableGen *executable, IrInstGenElemPtr *instruction) { LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->array_ptr); ZigType *array_ptr_type = instruction->array_ptr->value->type; assert(array_ptr_type->id == ZigTypeIdPointer); @@ -3948,7 +3948,7 @@ static void render_async_spills(CodeGen *g) { ZigType *frame_type = g->cur_fn->frame_type->data.frame.locals_struct; for (size_t alloca_i = 0; alloca_i < g->cur_fn->alloca_gen_list.length; alloca_i += 1) { - IrInstructionAllocaGen *instruction = g->cur_fn->alloca_gen_list.at(alloca_i); + IrInstGenAlloca *instruction = g->cur_fn->alloca_gen_list.at(alloca_i); if (instruction->field_index == SIZE_MAX) continue; @@ -4015,7 +4015,7 @@ static void gen_init_stack_trace(CodeGen *g, LLVMValueRef trace_field_ptr, LLVMV LLVMBuildStore(g->builder, LLVMConstInt(usize_type_ref, stack_trace_ptr_count, false), addrs_len_ptr); } -static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCallGen *instruction) { +static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrInstGenCall *instruction) { LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMValueRef fn_val; @@ -4150,7 +4150,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_index_trace_arg(g, src_return_type) + 1, ""); bool is_llvm_alloca; - LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, + LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.base.scope, &is_llvm_alloca); LLVMBuildStore(g->builder, my_err_ret_trace_val, err_ret_trace_ptr_ptr); } @@ -4209,7 +4209,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr gen_init_stack_trace(g, trace_field_ptr, addrs_field_ptr); bool is_llvm_alloca; - gen_param_values.append(get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca)); + gen_param_values.append(get_cur_err_ret_trace_val(g, instruction->base.base.scope, &is_llvm_alloca)); } } } else { @@ -4218,7 +4218,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr } if (prefix_arg_err_ret_stack) { bool is_llvm_alloca; - gen_param_values.append(get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca)); + gen_param_values.append(get_cur_err_ret_trace_val(g, instruction->base.base.scope, &is_llvm_alloca)); } } FnWalk fn_walk = {}; @@ -4328,13 +4328,13 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr LLVMPositionBuilderAtEnd(g->builder, call_bb); gen_assert_resume_id(g, &instruction->base, ResumeIdReturn, PanicMsgIdResumedAnAwaitingFn, nullptr); - render_async_var_decls(g, instruction->base.scope); + render_async_var_decls(g, instruction->base.base.scope); if (!type_has_bits(src_return_type)) return nullptr; if (result_loc != nullptr) { - if (instruction->result_loc->id == IrInstructionIdReturnPtr) { + if (instruction->result_loc->id == IrInstGenIdReturnPtr) { instruction->base.spill = nullptr; return g->cur_ret_ptr; } else { @@ -4394,8 +4394,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr } } -static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executable, - IrInstructionStructFieldPtr *instruction) +static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutableGen *executable, + IrInstGenStructFieldPtr *instruction) { Error err; @@ -4445,8 +4445,8 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa return field_ptr_val; } -static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable, - IrInstructionUnionFieldPtr *instruction) +static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutableGen *executable, + IrInstGenUnionFieldPtr *instruction) { if (instruction->base.value->special != ConstValSpecialRuntime) return nullptr; @@ -4545,8 +4545,8 @@ static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok, Buf *src_ return SIZE_MAX; } -static LLVMValueRef ir_render_asm_gen(CodeGen *g, IrExecutable *executable, IrInstructionAsmGen *instruction) { - AstNode *asm_node = instruction->base.source_node; +static LLVMValueRef ir_render_asm_gen(CodeGen *g, IrExecutableGen *executable, IrInstGenAsm *instruction) { + AstNode *asm_node = instruction->base.base.source_node; assert(asm_node->type == NodeTypeAsmExpr); AstNodeAsmExpr *asm_expr = &asm_node->data.asm_expr; @@ -4630,7 +4630,7 @@ static LLVMValueRef ir_render_asm_gen(CodeGen *g, IrExecutable *executable, IrIn for (size_t i = 0; i < asm_expr->input_list.length; i += 1, total_index += 1, param_index += 1) { AsmInput *asm_input = asm_expr->input_list.at(i); buf_replace(asm_input->constraint, ',', '|'); - IrInstruction *ir_input = instruction->input_list[i]; + IrInstGen *ir_input = instruction->input_list[i]; buf_append_buf(&constraint_buf, asm_input->constraint); if (total_index + 1 < total_constraint_count) { buf_append_char(&constraint_buf, ','); @@ -4693,14 +4693,14 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR return gen_load_untyped(g, maybe_field_ptr, 0, false, ""); } -static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable, - IrInstructionTestNonNull *instruction) +static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutableGen *executable, + IrInstGenTestNonNull *instruction) { return gen_non_null_bit(g, instruction->value->value->type, ir_llvm_value(g, instruction->value)); } -static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *executable, - IrInstructionOptionalUnwrapPtr *instruction) +static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutableGen *executable, + IrInstGenOptionalUnwrapPtr *instruction) { if (instruction->base.value->special != ConstValSpecialRuntime) return nullptr; @@ -4802,7 +4802,7 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *expr_type, BuiltinFn return fn_val; } -static LLVMValueRef ir_render_clz(CodeGen *g, IrExecutable *executable, IrInstructionClz *instruction) { +static LLVMValueRef ir_render_clz(CodeGen *g, IrExecutableGen *executable, IrInstGenClz *instruction) { ZigType *int_type = instruction->op->value->type; LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdClz); LLVMValueRef operand = ir_llvm_value(g, instruction->op); @@ -4814,7 +4814,7 @@ static LLVMValueRef ir_render_clz(CodeGen *g, IrExecutable *executable, IrInstru return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); } -static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutable *executable, IrInstructionCtz *instruction) { +static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutableGen *executable, IrInstGenCtz *instruction) { ZigType *int_type = instruction->op->value->type; LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdCtz); LLVMValueRef operand = ir_llvm_value(g, instruction->op); @@ -4826,7 +4826,7 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutable *executable, IrInstru return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); } -static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutable *executable, IrInstructionShuffleVector *instruction) { +static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutableGen *executable, IrInstGenShuffleVector *instruction) { uint64_t len_a = instruction->a->value->type->data.vector.len; uint64_t len_mask = instruction->mask->value->type->data.vector.len; @@ -4835,7 +4835,7 @@ static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutable *executabl // when changing code, so Zig uses negative numbers to index the // second vector. These start at -1 and go down, and are easiest to use // with the ~ operator. Here we convert between the two formats. - IrInstruction *mask = instruction->mask; + IrInstGen *mask = instruction->mask; LLVMValueRef *values = allocate(len_mask); for (uint64_t i = 0; i < len_mask; i++) { if (mask->value->data.x_array.data.s_none.elements[i].special == ConstValSpecialUndef) { @@ -4856,7 +4856,7 @@ static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutable *executabl llvm_mask_value, ""); } -static LLVMValueRef ir_render_splat(CodeGen *g, IrExecutable *executable, IrInstructionSplatGen *instruction) { +static LLVMValueRef ir_render_splat(CodeGen *g, IrExecutableGen *executable, IrInstGenSplat *instruction) { ZigType *result_type = instruction->base.value->type; ir_assert(result_type->id == ZigTypeIdVector, &instruction->base); uint32_t len = result_type->data.vector.len; @@ -4868,7 +4868,7 @@ static LLVMValueRef ir_render_splat(CodeGen *g, IrExecutable *executable, IrInst return LLVMBuildShuffleVector(g->builder, op_vector, undef_vector, LLVMConstNull(mask_llvm_type), ""); } -static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutable *executable, IrInstructionPopCount *instruction) { +static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutableGen *executable, IrInstGenPopCount *instruction) { ZigType *int_type = instruction->op->value->type; LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount); LLVMValueRef operand = ir_llvm_value(g, instruction->op); @@ -4876,7 +4876,7 @@ static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutable *executable, Ir return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); } -static LLVMValueRef ir_render_switch_br(CodeGen *g, IrExecutable *executable, IrInstructionSwitchBr *instruction) { +static LLVMValueRef ir_render_switch_br(CodeGen *g, IrExecutableGen *executable, IrInstGenSwitchBr *instruction) { ZigType *target_type = instruction->target_value->value->type; LLVMBasicBlockRef else_block = instruction->else_block->llvm_block; @@ -4890,7 +4890,7 @@ static LLVMValueRef ir_render_switch_br(CodeGen *g, IrExecutable *executable, Ir (unsigned)instruction->case_count); for (size_t i = 0; i < instruction->case_count; i += 1) { - IrInstructionSwitchBrCase *this_case = &instruction->cases[i]; + IrInstGenSwitchBrCase *this_case = &instruction->cases[i]; LLVMValueRef case_value = ir_llvm_value(g, this_case->value); if (target_type->id == ZigTypeIdPointer) { @@ -4904,7 +4904,7 @@ static LLVMValueRef ir_render_switch_br(CodeGen *g, IrExecutable *executable, Ir return nullptr; } -static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutable *executable, IrInstructionPhi *instruction) { +static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutableGen *executable, IrInstGenPhi *instruction) { if (!type_has_bits(instruction->base.value->type)) return nullptr; @@ -4926,7 +4926,7 @@ static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutable *executable, IrInstru return phi; } -static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutable *executable, IrInstructionRefGen *instruction) { +static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutableGen *executable, IrInstGenRef *instruction) { if (!type_has_bits(instruction->base.value->type)) { return nullptr; } @@ -4940,7 +4940,7 @@ static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutable *executable, IrInstru } } -static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrInstructionErrName *instruction) { +static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutableGen *executable, IrInstGenErrName *instruction) { assert(g->generate_error_name_table); if (g->errors_by_index.length == 1) { @@ -5061,11 +5061,16 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { return fn_val; } -static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable, - IrInstructionTagName *instruction) +static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutableGen *executable, + IrInstGenTagName *instruction) { ZigType *enum_type = instruction->target->value->type; assert(enum_type->id == ZigTypeIdEnum); + if (enum_type->data.enumeration.non_exhaustive) { + add_node_error(g, instruction->base.base.source_node, + buf_sprintf("TODO @tagName on non-exhaustive enum https://github.com/ziglang/zig/issues/3991")); + codegen_report_errors_and_exit(g); + } LLVMValueRef enum_name_function = get_enum_tag_name_function(g, enum_type); @@ -5074,8 +5079,8 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } -static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutable *executable, - IrInstructionFieldParentPtr *instruction) +static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutableGen *executable, + IrInstGenFieldParentPtr *instruction) { ZigType *container_ptr_type = instruction->base.value->type; assert(container_ptr_type->id == ZigTypeIdPointer); @@ -5101,7 +5106,7 @@ static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutable *executa } } -static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, IrInstructionAlignCast *instruction) { +static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutableGen *executable, IrInstGenAlignCast *instruction) { LLVMValueRef target_val = ir_llvm_value(g, instruction->target); assert(target_val); @@ -5164,11 +5169,11 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I return target_val; } -static LLVMValueRef ir_render_error_return_trace(CodeGen *g, IrExecutable *executable, - IrInstructionErrorReturnTrace *instruction) +static LLVMValueRef ir_render_error_return_trace(CodeGen *g, IrExecutableGen *executable, + IrInstGenErrorReturnTrace *instruction) { bool is_llvm_alloca; - LLVMValueRef cur_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca); + LLVMValueRef cur_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.base.scope, &is_llvm_alloca); if (cur_err_ret_trace_val == nullptr) { return LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type(g))); } @@ -5206,7 +5211,7 @@ static enum ZigLLVM_AtomicRMWBinOp to_ZigLLVMAtomicRMWBinOp(AtomicRmwOp op, bool zig_unreachable(); } -static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchgGen *instruction) { +static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, IrInstGenCmpxchg *instruction) { LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr); LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value); LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value); @@ -5247,13 +5252,13 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn return result_loc; } -static LLVMValueRef ir_render_fence(CodeGen *g, IrExecutable *executable, IrInstructionFence *instruction) { +static LLVMValueRef ir_render_fence(CodeGen *g, IrExecutableGen *executable, IrInstGenFence *instruction) { LLVMAtomicOrdering atomic_order = to_LLVMAtomicOrdering(instruction->order); LLVMBuildFence(g->builder, atomic_order, false, ""); return nullptr; } -static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutable *executable, IrInstructionTruncate *instruction) { +static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutableGen *executable, IrInstGenTruncate *instruction) { LLVMValueRef target_val = ir_llvm_value(g, instruction->target); ZigType *dest_type = instruction->base.value->type; ZigType *src_type = instruction->target->value->type; @@ -5268,7 +5273,7 @@ static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutable *executable, IrI } } -static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrInstructionMemset *instruction) { +static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutableGen *executable, IrInstGenMemset *instruction) { LLVMValueRef dest_ptr = ir_llvm_value(g, instruction->dest_ptr); LLVMValueRef len_val = ir_llvm_value(g, instruction->count); @@ -5280,7 +5285,7 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrIns bool val_is_undef = value_is_all_undef(g, instruction->byte->value); LLVMValueRef fill_char; - if (val_is_undef && ir_want_runtime_safety_scope(g, instruction->base.scope)) { + if (val_is_undef && ir_want_runtime_safety_scope(g, instruction->base.base.scope)) { fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); } else { fill_char = ir_llvm_value(g, instruction->byte); @@ -5294,7 +5299,7 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrIns return nullptr; } -static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrInstructionMemcpy *instruction) { +static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutableGen *executable, IrInstGenMemcpy *instruction) { LLVMValueRef dest_ptr = ir_llvm_value(g, instruction->dest_ptr); LLVMValueRef src_ptr = ir_llvm_value(g, instruction->src_ptr); LLVMValueRef len_val = ir_llvm_value(g, instruction->count); @@ -5316,7 +5321,7 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns return nullptr; } -static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInstructionSliceGen *instruction) { +static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrInstGenSlice *instruction) { LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->ptr); ZigType *array_ptr_type = instruction->ptr->value->type; assert(array_ptr_type->id == ZigTypeIdPointer); @@ -5478,13 +5483,13 @@ static LLVMValueRef get_trap_fn_val(CodeGen *g) { } -static LLVMValueRef ir_render_breakpoint(CodeGen *g, IrExecutable *executable, IrInstructionBreakpoint *instruction) { +static LLVMValueRef ir_render_breakpoint(CodeGen *g, IrExecutableGen *executable, IrInstGenBreakpoint *instruction) { LLVMBuildCall(g->builder, get_trap_fn_val(g), nullptr, 0, ""); return nullptr; } -static LLVMValueRef ir_render_return_address(CodeGen *g, IrExecutable *executable, - IrInstructionReturnAddress *instruction) +static LLVMValueRef ir_render_return_address(CodeGen *g, IrExecutableGen *executable, + IrInstGenReturnAddress *instruction) { LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type); LLVMValueRef ptr_val = LLVMBuildCall(g->builder, get_return_address_fn_val(g), &zero, 1, ""); @@ -5505,19 +5510,19 @@ static LLVMValueRef get_frame_address_fn_val(CodeGen *g) { return g->frame_address_fn_val; } -static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutable *executable, - IrInstructionFrameAddress *instruction) +static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutableGen *executable, + IrInstGenFrameAddress *instruction) { LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type); LLVMValueRef ptr_val = LLVMBuildCall(g->builder, get_frame_address_fn_val(g), &zero, 1, ""); return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, ""); } -static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutable *executable, IrInstructionFrameHandle *instruction) { +static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutableGen *executable, IrInstGenFrameHandle *instruction) { return g->cur_frame_ptr; } -static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstructionOverflowOp *instruction) { +static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstGenOverflowOp *instruction) { ZigType *int_type = instruction->result_ptr_type; assert(int_type->id == ZigTypeIdInt); @@ -5542,7 +5547,7 @@ static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstructionOverflowOp return overflow_bit; } -static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutable *executable, IrInstructionOverflowOp *instruction) { +static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutableGen *executable, IrInstGenOverflowOp *instruction) { AddSubMul add_sub_mul; switch (instruction->op) { case IrOverflowOpAdd: @@ -5580,7 +5585,7 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutable *executable, return overflow_bit; } -static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrInstructionTestErrGen *instruction) { +static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutableGen *executable, IrInstGenTestErr *instruction) { ZigType *err_union_type = instruction->err_union->value->type; ZigType *payload_type = err_union_type->data.error_union.payload_type; LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->err_union); @@ -5597,8 +5602,8 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, ""); } -static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, - IrInstructionUnwrapErrCode *instruction) +static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutableGen *executable, + IrInstGenUnwrapErrCode *instruction) { if (instruction->base.value->special != ConstValSpecialRuntime) return nullptr; @@ -5617,8 +5622,8 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab } } -static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, - IrInstructionUnwrapErrPayload *instruction) +static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutableGen *executable, + IrInstGenUnwrapErrPayload *instruction) { Error err; @@ -5661,7 +5666,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block); LLVMPositionBuilderAtEnd(g->builder, err_block); - gen_safety_crash_for_err(g, err_val, instruction->base.scope); + gen_safety_crash_for_err(g, err_val, instruction->base.base.scope); LLVMPositionBuilderAtEnd(g->builder, ok_block); } @@ -5678,7 +5683,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu } } -static LLVMValueRef ir_render_optional_wrap(CodeGen *g, IrExecutable *executable, IrInstructionOptionalWrap *instruction) { +static LLVMValueRef ir_render_optional_wrap(CodeGen *g, IrExecutableGen *executable, IrInstGenOptionalWrap *instruction) { ZigType *wanted_type = instruction->base.value->type; assert(wanted_type->id == ZigTypeIdOptional); @@ -5714,7 +5719,7 @@ static LLVMValueRef ir_render_optional_wrap(CodeGen *g, IrExecutable *executable return result_loc; } -static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutable *executable, IrInstructionErrWrapCode *instruction) { +static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutableGen *executable, IrInstGenErrWrapCode *instruction) { ZigType *wanted_type = instruction->base.value->type; assert(wanted_type->id == ZigTypeIdErrorUnion); @@ -5734,7 +5739,7 @@ static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutable *executable return result_loc; } -static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executable, IrInstructionErrWrapPayload *instruction) { +static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutableGen *executable, IrInstGenErrWrapPayload *instruction) { ZigType *wanted_type = instruction->base.value->type; assert(wanted_type->id == ZigTypeIdErrorUnion); @@ -5765,7 +5770,7 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa return result_loc; } -static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, IrInstructionUnionTag *instruction) { +static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutableGen *executable, IrInstGenUnionTag *instruction) { ZigType *union_type = instruction->value->value->type; ZigType *tag_type = union_type->data.unionation.tag_type; @@ -5783,15 +5788,15 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, Ir return get_handle_value(g, tag_field_ptr, tag_type, ptr_type); } -static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutable *executable, IrInstructionPanic *instruction) { +static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutableGen *executable, IrInstGenPanic *instruction) { bool is_llvm_alloca; - LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca); + LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.base.scope, &is_llvm_alloca); gen_panic(g, ir_llvm_value(g, instruction->msg), err_ret_trace_val, is_llvm_alloca); return nullptr; } -static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable, - IrInstructionAtomicRmw *instruction) +static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutableGen *executable, + IrInstGenAtomicRmw *instruction) { bool is_signed; ZigType *operand_type = instruction->operand->value->type; @@ -5801,8 +5806,8 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable, } else { is_signed = false; } - enum ZigLLVM_AtomicRMWBinOp op = to_ZigLLVMAtomicRMWBinOp(instruction->resolved_op, is_signed, is_float); - LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->resolved_ordering); + enum ZigLLVM_AtomicRMWBinOp op = to_ZigLLVMAtomicRMWBinOp(instruction->op, is_signed, is_float); + LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->ordering); LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); LLVMValueRef operand = ir_llvm_value(g, instruction->operand); @@ -5819,20 +5824,20 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable, return LLVMBuildIntToPtr(g->builder, uncasted_result, get_llvm_type(g, operand_type), ""); } -static LLVMValueRef ir_render_atomic_load(CodeGen *g, IrExecutable *executable, - IrInstructionAtomicLoad *instruction) +static LLVMValueRef ir_render_atomic_load(CodeGen *g, IrExecutableGen *executable, + IrInstGenAtomicLoad *instruction) { - LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->resolved_ordering); + LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->ordering); LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); LLVMValueRef load_inst = gen_load(g, ptr, instruction->ptr->value->type, ""); LLVMSetOrdering(load_inst, ordering); return load_inst; } -static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutable *executable, - IrInstructionAtomicStore *instruction) +static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutableGen *executable, + IrInstGenAtomicStore *instruction) { - LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->resolved_ordering); + LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->ordering); LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); LLVMValueRef value = ir_llvm_value(g, instruction->value); LLVMValueRef store_inst = gen_store(g, value, ptr, instruction->ptr->value->type); @@ -5840,13 +5845,13 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutable *executable, return nullptr; } -static LLVMValueRef ir_render_float_op(CodeGen *g, IrExecutable *executable, IrInstructionFloatOp *instruction) { +static LLVMValueRef ir_render_float_op(CodeGen *g, IrExecutableGen *executable, IrInstGenFloatOp *instruction) { LLVMValueRef operand = ir_llvm_value(g, instruction->operand); LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFloatOp, instruction->fn_id); return LLVMBuildCall(g->builder, fn_val, &operand, 1, ""); } -static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutable *executable, IrInstructionMulAdd *instruction) { +static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutableGen *executable, IrInstGenMulAdd *instruction) { LLVMValueRef op1 = ir_llvm_value(g, instruction->op1); LLVMValueRef op2 = ir_llvm_value(g, instruction->op2); LLVMValueRef op3 = ir_llvm_value(g, instruction->op3); @@ -5861,7 +5866,7 @@ static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutable *executable, IrIn return LLVMBuildCall(g->builder, fn_val, args, 3, ""); } -static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInstructionBswap *instruction) { +static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutableGen *executable, IrInstGenBswap *instruction) { LLVMValueRef op = ir_llvm_value(g, instruction->op); ZigType *expr_type = instruction->base.value->type; bool is_vector = expr_type->id == ZigTypeIdVector; @@ -5895,7 +5900,7 @@ static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInst return LLVMBuildTrunc(g->builder, shifted, get_llvm_type(g, expr_type), ""); } -static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutable *executable, IrInstructionBitReverse *instruction) { +static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutableGen *executable, IrInstGenBitReverse *instruction) { LLVMValueRef op = ir_llvm_value(g, instruction->op); ZigType *int_type = instruction->base.value->type; assert(int_type->id == ZigTypeIdInt); @@ -5903,8 +5908,8 @@ static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutable *executable, return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); } -static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executable, - IrInstructionVectorToArray *instruction) +static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutableGen *executable, + IrInstGenVectorToArray *instruction) { ZigType *array_type = instruction->base.value->type; assert(array_type->id == ZigTypeIdArray); @@ -5937,8 +5942,8 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab return result_loc; } -static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executable, - IrInstructionArrayToVector *instruction) +static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutableGen *executable, + IrInstGenArrayToVector *instruction) { ZigType *vector_type = instruction->base.value->type; assert(vector_type->id == ZigTypeIdVector); @@ -5974,8 +5979,8 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab } } -static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable, - IrInstructionAssertZero *instruction) +static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutableGen *executable, + IrInstGenAssertZero *instruction) { LLVMValueRef target = ir_llvm_value(g, instruction->target); ZigType *int_type = instruction->target->value->type; @@ -5985,8 +5990,8 @@ static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable, return nullptr; } -static LLVMValueRef ir_render_assert_non_null(CodeGen *g, IrExecutable *executable, - IrInstructionAssertNonNull *instruction) +static LLVMValueRef ir_render_assert_non_null(CodeGen *g, IrExecutableGen *executable, + IrInstGenAssertNonNull *instruction) { LLVMValueRef target = ir_llvm_value(g, instruction->target); ZigType *target_type = instruction->target->value->type; @@ -6010,8 +6015,8 @@ static LLVMValueRef ir_render_assert_non_null(CodeGen *g, IrExecutable *executab return nullptr; } -static LLVMValueRef ir_render_suspend_begin(CodeGen *g, IrExecutable *executable, - IrInstructionSuspendBegin *instruction) +static LLVMValueRef ir_render_suspend_begin(CodeGen *g, IrExecutableGen *executable, + IrInstGenSuspendBegin *instruction) { if (fn_is_async(g->cur_fn)) { instruction->resume_bb = gen_suspend_begin(g, "SuspendResume"); @@ -6019,8 +6024,8 @@ static LLVMValueRef ir_render_suspend_begin(CodeGen *g, IrExecutable *executable return nullptr; } -static LLVMValueRef ir_render_suspend_finish(CodeGen *g, IrExecutable *executable, - IrInstructionSuspendFinish *instruction) +static LLVMValueRef ir_render_suspend_finish(CodeGen *g, IrExecutableGen *executable, + IrInstGenSuspendFinish *instruction) { LLVMBuildRetVoid(g->builder); @@ -6028,11 +6033,11 @@ static LLVMValueRef ir_render_suspend_finish(CodeGen *g, IrExecutable *executabl if (ir_want_runtime_safety(g, &instruction->base)) { LLVMBuildStore(g->builder, g->cur_bad_not_suspended_index, g->cur_async_resume_index_ptr); } - render_async_var_decls(g, instruction->base.scope); + render_async_var_decls(g, instruction->base.base.scope); return nullptr; } -static LLVMValueRef gen_await_early_return(CodeGen *g, IrInstruction *source_instr, +static LLVMValueRef gen_await_early_return(CodeGen *g, IrInstGen *source_instr, LLVMValueRef target_frame_ptr, ZigType *result_type, ZigType *ptr_result_type, LLVMValueRef result_loc, bool non_async) { @@ -6058,7 +6063,7 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, IrInstruction *source_ins frame_index_trace_arg(g, result_type), ""); LLVMValueRef src_trace_ptr = LLVMBuildLoad(g->builder, their_trace_ptr_ptr, ""); bool is_llvm_alloca; - LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val(g, source_instr->scope, &is_llvm_alloca); + LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val(g, source_instr->base.scope, &is_llvm_alloca); LLVMValueRef args[] = { dest_trace_ptr, src_trace_ptr }; ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); @@ -6071,7 +6076,7 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, IrInstruction *source_ins } } -static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInstructionAwaitGen *instruction) { +static LLVMValueRef ir_render_await(CodeGen *g, IrExecutableGen *executable, IrInstGenAwait *instruction) { LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMValueRef zero = LLVMConstNull(usize_type_ref); LLVMValueRef target_frame_ptr = ir_llvm_value(g, instruction->frame); @@ -6108,7 +6113,7 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst // supply the error return trace pointer if (codegen_fn_has_err_ret_tracing_arg(g, result_type)) { bool is_llvm_alloca; - LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca); + LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.base.scope, &is_llvm_alloca); assert(my_err_ret_trace_val != nullptr); LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_index_trace_arg(g, result_type) + 1, ""); @@ -6156,7 +6161,7 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst return nullptr; } -static LLVMValueRef ir_render_resume(CodeGen *g, IrExecutable *executable, IrInstructionResume *instruction) { +static LLVMValueRef ir_render_resume(CodeGen *g, IrExecutableGen *executable, IrInstGenResume *instruction) { LLVMValueRef frame = ir_llvm_value(g, instruction->frame); ZigType *frame_type = instruction->frame->value->type; assert(frame_type->id == ZigTypeIdAnyFrame); @@ -6165,15 +6170,15 @@ static LLVMValueRef ir_render_resume(CodeGen *g, IrExecutable *executable, IrIns return nullptr; } -static LLVMValueRef ir_render_frame_size(CodeGen *g, IrExecutable *executable, - IrInstructionFrameSizeGen *instruction) +static LLVMValueRef ir_render_frame_size(CodeGen *g, IrExecutableGen *executable, + IrInstGenFrameSize *instruction) { LLVMValueRef fn_val = ir_llvm_value(g, instruction->fn); return gen_frame_size(g, fn_val); } -static LLVMValueRef ir_render_spill_begin(CodeGen *g, IrExecutable *executable, - IrInstructionSpillBegin *instruction) +static LLVMValueRef ir_render_spill_begin(CodeGen *g, IrExecutableGen *executable, + IrInstGenSpillBegin *instruction) { if (!fn_is_async(g->cur_fn)) return nullptr; @@ -6192,7 +6197,7 @@ static LLVMValueRef ir_render_spill_begin(CodeGen *g, IrExecutable *executable, zig_unreachable(); } -static LLVMValueRef ir_render_spill_end(CodeGen *g, IrExecutable *executable, IrInstructionSpillEnd *instruction) { +static LLVMValueRef ir_render_spill_end(CodeGen *g, IrExecutableGen *executable, IrInstGenSpillEnd *instruction) { if (!fn_is_async(g->cur_fn)) return ir_llvm_value(g, instruction->begin->operand); @@ -6208,17 +6213,17 @@ static LLVMValueRef ir_render_spill_end(CodeGen *g, IrExecutable *executable, Ir zig_unreachable(); } -static LLVMValueRef ir_render_vector_extract_elem(CodeGen *g, IrExecutable *executable, - IrInstructionVectorExtractElem *instruction) +static LLVMValueRef ir_render_vector_extract_elem(CodeGen *g, IrExecutableGen *executable, + IrInstGenVectorExtractElem *instruction) { LLVMValueRef vector = ir_llvm_value(g, instruction->vector); LLVMValueRef index = ir_llvm_value(g, instruction->index); return LLVMBuildExtractElement(g->builder, vector, index, ""); } -static void set_debug_location(CodeGen *g, IrInstruction *instruction) { - AstNode *source_node = instruction->source_node; - Scope *scope = instruction->scope; +static void set_debug_location(CodeGen *g, IrInstGen *instruction) { + AstNode *source_node = instruction->base.source_node; + Scope *scope = instruction->base.scope; assert(source_node); assert(scope); @@ -6227,263 +6232,183 @@ static void set_debug_location(CodeGen *g, IrInstruction *instruction) { (int)source_node->column + 1, get_di_scope(g, scope)); } -static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) { +static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutableGen *executable, IrInstGen *instruction) { switch (instruction->id) { - case IrInstructionIdInvalid: - case IrInstructionIdConst: - case IrInstructionIdTypeOf: - case IrInstructionIdFieldPtr: - case IrInstructionIdSetCold: - case IrInstructionIdSetRuntimeSafety: - case IrInstructionIdSetFloatMode: - case IrInstructionIdArrayType: - case IrInstructionIdAnyFrameType: - case IrInstructionIdSliceType: - case IrInstructionIdSizeOf: - case IrInstructionIdSwitchTarget: - case IrInstructionIdContainerInitFields: - case IrInstructionIdCompileErr: - case IrInstructionIdCompileLog: - case IrInstructionIdImport: - case IrInstructionIdCImport: - case IrInstructionIdCInclude: - case IrInstructionIdCDefine: - case IrInstructionIdCUndef: - case IrInstructionIdEmbedFile: - case IrInstructionIdIntType: - case IrInstructionIdVectorType: - case IrInstructionIdMemberCount: - case IrInstructionIdMemberType: - case IrInstructionIdMemberName: - case IrInstructionIdAlignOf: - case IrInstructionIdFnProto: - case IrInstructionIdTestComptime: - case IrInstructionIdCheckSwitchProngs: - case IrInstructionIdCheckStatementIsVoid: - case IrInstructionIdTypeName: - case IrInstructionIdDeclRef: - case IrInstructionIdSwitchVar: - case IrInstructionIdSwitchElseVar: - case IrInstructionIdByteOffsetOf: - case IrInstructionIdBitOffsetOf: - case IrInstructionIdTypeInfo: - case IrInstructionIdType: - case IrInstructionIdHasField: - case IrInstructionIdTypeId: - case IrInstructionIdSetEvalBranchQuota: - case IrInstructionIdPtrType: - case IrInstructionIdOpaqueType: - case IrInstructionIdSetAlignStack: - case IrInstructionIdArgType: - case IrInstructionIdTagType: - case IrInstructionIdExport: - case IrInstructionIdErrorUnion: - case IrInstructionIdAddImplicitReturnType: - case IrInstructionIdIntCast: - case IrInstructionIdFloatCast: - case IrInstructionIdIntToFloat: - case IrInstructionIdFloatToInt: - case IrInstructionIdBoolToInt: - case IrInstructionIdErrSetCast: - case IrInstructionIdFromBytes: - case IrInstructionIdToBytes: - case IrInstructionIdEnumToInt: - case IrInstructionIdCheckRuntimeScope: - case IrInstructionIdDeclVarSrc: - case IrInstructionIdPtrCastSrc: - case IrInstructionIdCmpxchgSrc: - case IrInstructionIdLoadPtr: - case IrInstructionIdHasDecl: - case IrInstructionIdUndeclaredIdent: - case IrInstructionIdCallExtra: - case IrInstructionIdCallSrc: - case IrInstructionIdCallSrcArgs: - case IrInstructionIdAllocaSrc: - case IrInstructionIdEndExpr: - case IrInstructionIdImplicitCast: - case IrInstructionIdResolveResult: - case IrInstructionIdResetResult: - case IrInstructionIdContainerInitList: - case IrInstructionIdSliceSrc: - case IrInstructionIdRef: - case IrInstructionIdBitCastSrc: - case IrInstructionIdTestErrSrc: - case IrInstructionIdUnionInitNamedField: - case IrInstructionIdFrameType: - case IrInstructionIdFrameSizeSrc: - case IrInstructionIdAllocaGen: - case IrInstructionIdAwaitSrc: - case IrInstructionIdSplatSrc: - case IrInstructionIdMergeErrSets: - case IrInstructionIdAsmSrc: + case IrInstGenIdInvalid: + case IrInstGenIdConst: + case IrInstGenIdAlloca: zig_unreachable(); - case IrInstructionIdDeclVarGen: - return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction); - case IrInstructionIdReturn: - return ir_render_return(g, executable, (IrInstructionReturn *)instruction); - case IrInstructionIdBinOp: - return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction); - case IrInstructionIdCast: - return ir_render_cast(g, executable, (IrInstructionCast *)instruction); - case IrInstructionIdUnreachable: - return ir_render_unreachable(g, executable, (IrInstructionUnreachable *)instruction); - case IrInstructionIdCondBr: - return ir_render_cond_br(g, executable, (IrInstructionCondBr *)instruction); - case IrInstructionIdBr: - return ir_render_br(g, executable, (IrInstructionBr *)instruction); - case IrInstructionIdUnOp: - return ir_render_un_op(g, executable, (IrInstructionUnOp *)instruction); - case IrInstructionIdLoadPtrGen: - return ir_render_load_ptr(g, executable, (IrInstructionLoadPtrGen *)instruction); - case IrInstructionIdStorePtr: - return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction); - case IrInstructionIdVectorStoreElem: - return ir_render_vector_store_elem(g, executable, (IrInstructionVectorStoreElem *)instruction); - case IrInstructionIdVarPtr: - return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction); - case IrInstructionIdReturnPtr: - return ir_render_return_ptr(g, executable, (IrInstructionReturnPtr *)instruction); - case IrInstructionIdElemPtr: - return ir_render_elem_ptr(g, executable, (IrInstructionElemPtr *)instruction); - case IrInstructionIdCallGen: - return ir_render_call(g, executable, (IrInstructionCallGen *)instruction); - case IrInstructionIdStructFieldPtr: - return ir_render_struct_field_ptr(g, executable, (IrInstructionStructFieldPtr *)instruction); - case IrInstructionIdUnionFieldPtr: - return ir_render_union_field_ptr(g, executable, (IrInstructionUnionFieldPtr *)instruction); - case IrInstructionIdAsmGen: - return ir_render_asm_gen(g, executable, (IrInstructionAsmGen *)instruction); - case IrInstructionIdTestNonNull: - return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction); - case IrInstructionIdOptionalUnwrapPtr: - return ir_render_optional_unwrap_ptr(g, executable, (IrInstructionOptionalUnwrapPtr *)instruction); - case IrInstructionIdClz: - return ir_render_clz(g, executable, (IrInstructionClz *)instruction); - case IrInstructionIdCtz: - return ir_render_ctz(g, executable, (IrInstructionCtz *)instruction); - case IrInstructionIdPopCount: - return ir_render_pop_count(g, executable, (IrInstructionPopCount *)instruction); - case IrInstructionIdSwitchBr: - return ir_render_switch_br(g, executable, (IrInstructionSwitchBr *)instruction); - case IrInstructionIdBswap: - return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction); - case IrInstructionIdBitReverse: - return ir_render_bit_reverse(g, executable, (IrInstructionBitReverse *)instruction); - case IrInstructionIdPhi: - return ir_render_phi(g, executable, (IrInstructionPhi *)instruction); - case IrInstructionIdRefGen: - return ir_render_ref(g, executable, (IrInstructionRefGen *)instruction); - case IrInstructionIdErrName: - return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction); - case IrInstructionIdCmpxchgGen: - return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchgGen *)instruction); - case IrInstructionIdFence: - return ir_render_fence(g, executable, (IrInstructionFence *)instruction); - case IrInstructionIdTruncate: - return ir_render_truncate(g, executable, (IrInstructionTruncate *)instruction); - case IrInstructionIdBoolNot: - return ir_render_bool_not(g, executable, (IrInstructionBoolNot *)instruction); - case IrInstructionIdMemset: - return ir_render_memset(g, executable, (IrInstructionMemset *)instruction); - case IrInstructionIdMemcpy: - return ir_render_memcpy(g, executable, (IrInstructionMemcpy *)instruction); - case IrInstructionIdSliceGen: - return ir_render_slice(g, executable, (IrInstructionSliceGen *)instruction); - case IrInstructionIdBreakpoint: - return ir_render_breakpoint(g, executable, (IrInstructionBreakpoint *)instruction); - case IrInstructionIdReturnAddress: - return ir_render_return_address(g, executable, (IrInstructionReturnAddress *)instruction); - case IrInstructionIdFrameAddress: - return ir_render_frame_address(g, executable, (IrInstructionFrameAddress *)instruction); - case IrInstructionIdFrameHandle: - return ir_render_handle(g, executable, (IrInstructionFrameHandle *)instruction); - case IrInstructionIdOverflowOp: - return ir_render_overflow_op(g, executable, (IrInstructionOverflowOp *)instruction); - case IrInstructionIdTestErrGen: - return ir_render_test_err(g, executable, (IrInstructionTestErrGen *)instruction); - case IrInstructionIdUnwrapErrCode: - return ir_render_unwrap_err_code(g, executable, (IrInstructionUnwrapErrCode *)instruction); - case IrInstructionIdUnwrapErrPayload: - return ir_render_unwrap_err_payload(g, executable, (IrInstructionUnwrapErrPayload *)instruction); - case IrInstructionIdOptionalWrap: - return ir_render_optional_wrap(g, executable, (IrInstructionOptionalWrap *)instruction); - case IrInstructionIdErrWrapCode: - return ir_render_err_wrap_code(g, executable, (IrInstructionErrWrapCode *)instruction); - case IrInstructionIdErrWrapPayload: - return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction); - case IrInstructionIdUnionTag: - return ir_render_union_tag(g, executable, (IrInstructionUnionTag *)instruction); - case IrInstructionIdPtrCastGen: - return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction); - case IrInstructionIdBitCastGen: - return ir_render_bit_cast(g, executable, (IrInstructionBitCastGen *)instruction); - case IrInstructionIdWidenOrShorten: - return ir_render_widen_or_shorten(g, executable, (IrInstructionWidenOrShorten *)instruction); - case IrInstructionIdPtrToInt: - return ir_render_ptr_to_int(g, executable, (IrInstructionPtrToInt *)instruction); - case IrInstructionIdIntToPtr: - return ir_render_int_to_ptr(g, executable, (IrInstructionIntToPtr *)instruction); - case IrInstructionIdIntToEnum: - return ir_render_int_to_enum(g, executable, (IrInstructionIntToEnum *)instruction); - case IrInstructionIdIntToErr: - return ir_render_int_to_err(g, executable, (IrInstructionIntToErr *)instruction); - case IrInstructionIdErrToInt: - return ir_render_err_to_int(g, executable, (IrInstructionErrToInt *)instruction); - case IrInstructionIdPanic: - return ir_render_panic(g, executable, (IrInstructionPanic *)instruction); - case IrInstructionIdTagName: - return ir_render_enum_tag_name(g, executable, (IrInstructionTagName *)instruction); - case IrInstructionIdFieldParentPtr: - return ir_render_field_parent_ptr(g, executable, (IrInstructionFieldParentPtr *)instruction); - case IrInstructionIdAlignCast: - return ir_render_align_cast(g, executable, (IrInstructionAlignCast *)instruction); - case IrInstructionIdErrorReturnTrace: - return ir_render_error_return_trace(g, executable, (IrInstructionErrorReturnTrace *)instruction); - case IrInstructionIdAtomicRmw: - return ir_render_atomic_rmw(g, executable, (IrInstructionAtomicRmw *)instruction); - case IrInstructionIdAtomicLoad: - return ir_render_atomic_load(g, executable, (IrInstructionAtomicLoad *)instruction); - case IrInstructionIdAtomicStore: - return ir_render_atomic_store(g, executable, (IrInstructionAtomicStore *)instruction); - case IrInstructionIdSaveErrRetAddr: - return ir_render_save_err_ret_addr(g, executable, (IrInstructionSaveErrRetAddr *)instruction); - case IrInstructionIdFloatOp: - return ir_render_float_op(g, executable, (IrInstructionFloatOp *)instruction); - case IrInstructionIdMulAdd: - return ir_render_mul_add(g, executable, (IrInstructionMulAdd *)instruction); - case IrInstructionIdArrayToVector: - return ir_render_array_to_vector(g, executable, (IrInstructionArrayToVector *)instruction); - case IrInstructionIdVectorToArray: - return ir_render_vector_to_array(g, executable, (IrInstructionVectorToArray *)instruction); - case IrInstructionIdAssertZero: - return ir_render_assert_zero(g, executable, (IrInstructionAssertZero *)instruction); - case IrInstructionIdAssertNonNull: - return ir_render_assert_non_null(g, executable, (IrInstructionAssertNonNull *)instruction); - case IrInstructionIdResizeSlice: - return ir_render_resize_slice(g, executable, (IrInstructionResizeSlice *)instruction); - case IrInstructionIdPtrOfArrayToSlice: - return ir_render_ptr_of_array_to_slice(g, executable, (IrInstructionPtrOfArrayToSlice *)instruction); - case IrInstructionIdSuspendBegin: - return ir_render_suspend_begin(g, executable, (IrInstructionSuspendBegin *)instruction); - case IrInstructionIdSuspendFinish: - return ir_render_suspend_finish(g, executable, (IrInstructionSuspendFinish *)instruction); - case IrInstructionIdResume: - return ir_render_resume(g, executable, (IrInstructionResume *)instruction); - case IrInstructionIdFrameSizeGen: - return ir_render_frame_size(g, executable, (IrInstructionFrameSizeGen *)instruction); - case IrInstructionIdAwaitGen: - return ir_render_await(g, executable, (IrInstructionAwaitGen *)instruction); - case IrInstructionIdSpillBegin: - return ir_render_spill_begin(g, executable, (IrInstructionSpillBegin *)instruction); - case IrInstructionIdSpillEnd: - return ir_render_spill_end(g, executable, (IrInstructionSpillEnd *)instruction); - case IrInstructionIdShuffleVector: - return ir_render_shuffle_vector(g, executable, (IrInstructionShuffleVector *) instruction); - case IrInstructionIdSplatGen: - return ir_render_splat(g, executable, (IrInstructionSplatGen *) instruction); - case IrInstructionIdVectorExtractElem: - return ir_render_vector_extract_elem(g, executable, (IrInstructionVectorExtractElem *) instruction); + case IrInstGenIdDeclVar: + return ir_render_decl_var(g, executable, (IrInstGenDeclVar *)instruction); + case IrInstGenIdReturn: + return ir_render_return(g, executable, (IrInstGenReturn *)instruction); + case IrInstGenIdBinOp: + return ir_render_bin_op(g, executable, (IrInstGenBinOp *)instruction); + case IrInstGenIdCast: + return ir_render_cast(g, executable, (IrInstGenCast *)instruction); + case IrInstGenIdUnreachable: + return ir_render_unreachable(g, executable, (IrInstGenUnreachable *)instruction); + case IrInstGenIdCondBr: + return ir_render_cond_br(g, executable, (IrInstGenCondBr *)instruction); + case IrInstGenIdBr: + return ir_render_br(g, executable, (IrInstGenBr *)instruction); + case IrInstGenIdBinaryNot: + return ir_render_binary_not(g, executable, (IrInstGenBinaryNot *)instruction); + case IrInstGenIdNegation: + return ir_render_negation(g, executable, (IrInstGenNegation *)instruction); + case IrInstGenIdNegationWrapping: + return ir_render_negation_wrapping(g, executable, (IrInstGenNegationWrapping *)instruction); + case IrInstGenIdLoadPtr: + return ir_render_load_ptr(g, executable, (IrInstGenLoadPtr *)instruction); + case IrInstGenIdStorePtr: + return ir_render_store_ptr(g, executable, (IrInstGenStorePtr *)instruction); + case IrInstGenIdVectorStoreElem: + return ir_render_vector_store_elem(g, executable, (IrInstGenVectorStoreElem *)instruction); + case IrInstGenIdVarPtr: + return ir_render_var_ptr(g, executable, (IrInstGenVarPtr *)instruction); + case IrInstGenIdReturnPtr: + return ir_render_return_ptr(g, executable, (IrInstGenReturnPtr *)instruction); + case IrInstGenIdElemPtr: + return ir_render_elem_ptr(g, executable, (IrInstGenElemPtr *)instruction); + case IrInstGenIdCall: + return ir_render_call(g, executable, (IrInstGenCall *)instruction); + case IrInstGenIdStructFieldPtr: + return ir_render_struct_field_ptr(g, executable, (IrInstGenStructFieldPtr *)instruction); + case IrInstGenIdUnionFieldPtr: + return ir_render_union_field_ptr(g, executable, (IrInstGenUnionFieldPtr *)instruction); + case IrInstGenIdAsm: + return ir_render_asm_gen(g, executable, (IrInstGenAsm *)instruction); + case IrInstGenIdTestNonNull: + return ir_render_test_non_null(g, executable, (IrInstGenTestNonNull *)instruction); + case IrInstGenIdOptionalUnwrapPtr: + return ir_render_optional_unwrap_ptr(g, executable, (IrInstGenOptionalUnwrapPtr *)instruction); + case IrInstGenIdClz: + return ir_render_clz(g, executable, (IrInstGenClz *)instruction); + case IrInstGenIdCtz: + return ir_render_ctz(g, executable, (IrInstGenCtz *)instruction); + case IrInstGenIdPopCount: + return ir_render_pop_count(g, executable, (IrInstGenPopCount *)instruction); + case IrInstGenIdSwitchBr: + return ir_render_switch_br(g, executable, (IrInstGenSwitchBr *)instruction); + case IrInstGenIdBswap: + return ir_render_bswap(g, executable, (IrInstGenBswap *)instruction); + case IrInstGenIdBitReverse: + return ir_render_bit_reverse(g, executable, (IrInstGenBitReverse *)instruction); + case IrInstGenIdPhi: + return ir_render_phi(g, executable, (IrInstGenPhi *)instruction); + case IrInstGenIdRef: + return ir_render_ref(g, executable, (IrInstGenRef *)instruction); + case IrInstGenIdErrName: + return ir_render_err_name(g, executable, (IrInstGenErrName *)instruction); + case IrInstGenIdCmpxchg: + return ir_render_cmpxchg(g, executable, (IrInstGenCmpxchg *)instruction); + case IrInstGenIdFence: + return ir_render_fence(g, executable, (IrInstGenFence *)instruction); + case IrInstGenIdTruncate: + return ir_render_truncate(g, executable, (IrInstGenTruncate *)instruction); + case IrInstGenIdBoolNot: + return ir_render_bool_not(g, executable, (IrInstGenBoolNot *)instruction); + case IrInstGenIdMemset: + return ir_render_memset(g, executable, (IrInstGenMemset *)instruction); + case IrInstGenIdMemcpy: + return ir_render_memcpy(g, executable, (IrInstGenMemcpy *)instruction); + case IrInstGenIdSlice: + return ir_render_slice(g, executable, (IrInstGenSlice *)instruction); + case IrInstGenIdBreakpoint: + return ir_render_breakpoint(g, executable, (IrInstGenBreakpoint *)instruction); + case IrInstGenIdReturnAddress: + return ir_render_return_address(g, executable, (IrInstGenReturnAddress *)instruction); + case IrInstGenIdFrameAddress: + return ir_render_frame_address(g, executable, (IrInstGenFrameAddress *)instruction); + case IrInstGenIdFrameHandle: + return ir_render_handle(g, executable, (IrInstGenFrameHandle *)instruction); + case IrInstGenIdOverflowOp: + return ir_render_overflow_op(g, executable, (IrInstGenOverflowOp *)instruction); + case IrInstGenIdTestErr: + return ir_render_test_err(g, executable, (IrInstGenTestErr *)instruction); + case IrInstGenIdUnwrapErrCode: + return ir_render_unwrap_err_code(g, executable, (IrInstGenUnwrapErrCode *)instruction); + case IrInstGenIdUnwrapErrPayload: + return ir_render_unwrap_err_payload(g, executable, (IrInstGenUnwrapErrPayload *)instruction); + case IrInstGenIdOptionalWrap: + return ir_render_optional_wrap(g, executable, (IrInstGenOptionalWrap *)instruction); + case IrInstGenIdErrWrapCode: + return ir_render_err_wrap_code(g, executable, (IrInstGenErrWrapCode *)instruction); + case IrInstGenIdErrWrapPayload: + return ir_render_err_wrap_payload(g, executable, (IrInstGenErrWrapPayload *)instruction); + case IrInstGenIdUnionTag: + return ir_render_union_tag(g, executable, (IrInstGenUnionTag *)instruction); + case IrInstGenIdPtrCast: + return ir_render_ptr_cast(g, executable, (IrInstGenPtrCast *)instruction); + case IrInstGenIdBitCast: + return ir_render_bit_cast(g, executable, (IrInstGenBitCast *)instruction); + case IrInstGenIdWidenOrShorten: + return ir_render_widen_or_shorten(g, executable, (IrInstGenWidenOrShorten *)instruction); + case IrInstGenIdPtrToInt: + return ir_render_ptr_to_int(g, executable, (IrInstGenPtrToInt *)instruction); + case IrInstGenIdIntToPtr: + return ir_render_int_to_ptr(g, executable, (IrInstGenIntToPtr *)instruction); + case IrInstGenIdIntToEnum: + return ir_render_int_to_enum(g, executable, (IrInstGenIntToEnum *)instruction); + case IrInstGenIdIntToErr: + return ir_render_int_to_err(g, executable, (IrInstGenIntToErr *)instruction); + case IrInstGenIdErrToInt: + return ir_render_err_to_int(g, executable, (IrInstGenErrToInt *)instruction); + case IrInstGenIdPanic: + return ir_render_panic(g, executable, (IrInstGenPanic *)instruction); + case IrInstGenIdTagName: + return ir_render_enum_tag_name(g, executable, (IrInstGenTagName *)instruction); + case IrInstGenIdFieldParentPtr: + return ir_render_field_parent_ptr(g, executable, (IrInstGenFieldParentPtr *)instruction); + case IrInstGenIdAlignCast: + return ir_render_align_cast(g, executable, (IrInstGenAlignCast *)instruction); + case IrInstGenIdErrorReturnTrace: + return ir_render_error_return_trace(g, executable, (IrInstGenErrorReturnTrace *)instruction); + case IrInstGenIdAtomicRmw: + return ir_render_atomic_rmw(g, executable, (IrInstGenAtomicRmw *)instruction); + case IrInstGenIdAtomicLoad: + return ir_render_atomic_load(g, executable, (IrInstGenAtomicLoad *)instruction); + case IrInstGenIdAtomicStore: + return ir_render_atomic_store(g, executable, (IrInstGenAtomicStore *)instruction); + case IrInstGenIdSaveErrRetAddr: + return ir_render_save_err_ret_addr(g, executable, (IrInstGenSaveErrRetAddr *)instruction); + case IrInstGenIdFloatOp: + return ir_render_float_op(g, executable, (IrInstGenFloatOp *)instruction); + case IrInstGenIdMulAdd: + return ir_render_mul_add(g, executable, (IrInstGenMulAdd *)instruction); + case IrInstGenIdArrayToVector: + return ir_render_array_to_vector(g, executable, (IrInstGenArrayToVector *)instruction); + case IrInstGenIdVectorToArray: + return ir_render_vector_to_array(g, executable, (IrInstGenVectorToArray *)instruction); + case IrInstGenIdAssertZero: + return ir_render_assert_zero(g, executable, (IrInstGenAssertZero *)instruction); + case IrInstGenIdAssertNonNull: + return ir_render_assert_non_null(g, executable, (IrInstGenAssertNonNull *)instruction); + case IrInstGenIdResizeSlice: + return ir_render_resize_slice(g, executable, (IrInstGenResizeSlice *)instruction); + case IrInstGenIdPtrOfArrayToSlice: + return ir_render_ptr_of_array_to_slice(g, executable, (IrInstGenPtrOfArrayToSlice *)instruction); + case IrInstGenIdSuspendBegin: + return ir_render_suspend_begin(g, executable, (IrInstGenSuspendBegin *)instruction); + case IrInstGenIdSuspendFinish: + return ir_render_suspend_finish(g, executable, (IrInstGenSuspendFinish *)instruction); + case IrInstGenIdResume: + return ir_render_resume(g, executable, (IrInstGenResume *)instruction); + case IrInstGenIdFrameSize: + return ir_render_frame_size(g, executable, (IrInstGenFrameSize *)instruction); + case IrInstGenIdAwait: + return ir_render_await(g, executable, (IrInstGenAwait *)instruction); + case IrInstGenIdSpillBegin: + return ir_render_spill_begin(g, executable, (IrInstGenSpillBegin *)instruction); + case IrInstGenIdSpillEnd: + return ir_render_spill_end(g, executable, (IrInstGenSpillEnd *)instruction); + case IrInstGenIdShuffleVector: + return ir_render_shuffle_vector(g, executable, (IrInstGenShuffleVector *) instruction); + case IrInstGenIdSplat: + return ir_render_splat(g, executable, (IrInstGenSplat *) instruction); + case IrInstGenIdVectorExtractElem: + return ir_render_vector_extract_elem(g, executable, (IrInstGenVectorExtractElem *) instruction); } zig_unreachable(); } @@ -6491,21 +6416,21 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, static void ir_render(CodeGen *g, ZigFn *fn_entry) { assert(fn_entry); - IrExecutable *executable = &fn_entry->analyzed_executable; + IrExecutableGen *executable = &fn_entry->analyzed_executable; assert(executable->basic_block_list.length > 0); for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) { - IrBasicBlock *current_block = executable->basic_block_list.at(block_i); + IrBasicBlockGen *current_block = executable->basic_block_list.at(block_i); if (get_scope_typeof(current_block->scope) != nullptr) { LLVMBuildBr(g->builder, current_block->llvm_block); } assert(current_block->llvm_block); LLVMPositionBuilderAtEnd(g->builder, current_block->llvm_block); for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) { - IrInstruction *instruction = current_block->instruction_list.at(instr_i); - if (instruction->ref_count == 0 && !ir_has_side_effects(instruction)) + IrInstGen *instruction = current_block->instruction_list.at(instr_i); + if (instruction->base.ref_count == 0 && !ir_inst_gen_has_side_effects(instruction)) continue; - if (get_scope_typeof(instruction->scope) != nullptr) + if (get_scope_typeof(instruction->base.scope) != nullptr) continue; if (!g->strip_debug_symbols) { @@ -7397,7 +7322,7 @@ static void generate_error_name_table(CodeGen *g) { } static void build_all_basic_blocks(CodeGen *g, ZigFn *fn) { - IrExecutable *executable = &fn->analyzed_executable; + IrExecutableGen *executable = &fn->analyzed_executable; assert(executable->basic_block_list.length > 0); LLVMValueRef fn_val = fn_llvm_value(g, fn); LLVMBasicBlockRef first_bb = nullptr; @@ -7406,7 +7331,7 @@ static void build_all_basic_blocks(CodeGen *g, ZigFn *fn) { g->cur_preamble_llvm_block = first_bb; } for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) { - IrBasicBlock *bb = executable->basic_block_list.at(block_i); + IrBasicBlockGen *bb = executable->basic_block_list.at(block_i); bb->llvm_block = LLVMAppendBasicBlock(fn_val, bb->name_hint); } if (first_bb == nullptr) { @@ -7639,10 +7564,10 @@ static void do_code_gen(CodeGen *g) { if (!is_async) { // allocate async frames for noasync calls & awaits to async functions ZigType *largest_call_frame_type = nullptr; - IrInstruction *all_calls_alloca = ir_create_alloca(g, &fn_table_entry->fndef_scope->base, + IrInstGen *all_calls_alloca = ir_create_alloca(g, &fn_table_entry->fndef_scope->base, fn_table_entry->body_node, fn_table_entry, g->builtin_types.entry_void, "@async_call_frame"); for (size_t i = 0; i < fn_table_entry->call_list.length; i += 1) { - IrInstructionCallGen *call = fn_table_entry->call_list.at(i); + IrInstGenCall *call = fn_table_entry->call_list.at(i); if (call->fn_entry == nullptr) continue; if (!fn_is_async(call->fn_entry)) @@ -7664,7 +7589,7 @@ static void do_code_gen(CodeGen *g) { } // allocate temporary stack data for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_gen_list.length; alloca_i += 1) { - IrInstructionAllocaGen *instruction = fn_table_entry->alloca_gen_list.at(alloca_i); + IrInstGenAlloca *instruction = fn_table_entry->alloca_gen_list.at(alloca_i); ZigType *ptr_type = instruction->base.value->type; assert(ptr_type->id == ZigTypeIdPointer); ZigType *child_type = ptr_type->data.pointer.child_type; @@ -7672,7 +7597,7 @@ static void do_code_gen(CodeGen *g) { zig_unreachable(); if (!type_has_bits(child_type)) continue; - if (instruction->base.ref_count == 0) + if (instruction->base.base.ref_count == 0) continue; if (instruction->base.value->special != ConstValSpecialRuntime) { if (const_ptr_pointee(nullptr, g, instruction->base.value, nullptr)->special != @@ -7789,7 +7714,7 @@ static void do_code_gen(CodeGen *g) { ZigLLVMSetCurrentDebugLocation(g->builder, (int)source_node->line + 1, (int)source_node->column + 1, get_di_scope(g, fn_table_entry->child_scope)); } - IrExecutable *executable = &fn_table_entry->analyzed_executable; + IrExecutableGen *executable = &fn_table_entry->analyzed_executable; LLVMBasicBlockRef bad_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadResume"); LLVMPositionBuilderAtEnd(g->builder, bad_resume_block); gen_assertion_scope(g, PanicMsgIdBadResume, fn_table_entry->child_scope); @@ -7816,7 +7741,7 @@ static void do_code_gen(CodeGen *g) { g->cur_async_switch_instr = switch_instr; LLVMValueRef zero = LLVMConstNull(usize_type_ref); - IrBasicBlock *entry_block = executable->basic_block_list.at(0); + IrBasicBlockGen *entry_block = executable->basic_block_list.at(0); LLVMAddCase(switch_instr, zero, entry_block->llvm_block); g->cur_resume_block_count += 1; @@ -7848,7 +7773,7 @@ static void do_code_gen(CodeGen *g) { gen_init_stack_trace(g, trace_field_ptr, addrs_field_ptr); } - render_async_var_decls(g, entry_block->instruction_list.at(0)->scope); + render_async_var_decls(g, entry_block->instruction_list.at(0)->base.scope); } else { // create debug variable declarations for parameters // rely on the first variables in the variable_list being parameters. @@ -7937,6 +7862,12 @@ static void zig_llvm_emit_output(CodeGen *g) { default: zig_unreachable(); } + LLVMDisposeModule(g->module); + g->module = nullptr; + LLVMDisposeTargetData(g->target_data_ref); + g->target_data_ref = nullptr; + LLVMDisposeTargetMachine(g->target_machine); + g->target_machine = nullptr; } struct CIntTypeInfo { @@ -8574,6 +8505,17 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { buf_appendf(contents, "pub const os = Os.%s;\n", cur_os); buf_appendf(contents, "pub const arch = %s;\n", cur_arch); buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi); + { + buf_append_str(contents, "pub const cpu_features: CpuFeatures = "); + if (g->zig_target->cpu_features != nullptr) { + const char *ptr; + size_t len; + stage2_cpu_features_get_builtin_str(g->zig_target->cpu_features, &ptr, &len); + buf_append_mem(contents, ptr, len); + } else { + buf_append_str(contents, "arch.getBaselineCpuFeatures();\n"); + } + } if (g->libc_link_lib != nullptr && g->zig_target->glibc_version != nullptr) { buf_appendf(contents, "pub const glibc_version: ?Version = Version{.major = %d, .minor = %d, .patch = %d};\n", @@ -8641,6 +8583,12 @@ static Error define_builtin_compile_vars(CodeGen *g) { cache_int(&cache_hash, g->zig_target->vendor); cache_int(&cache_hash, g->zig_target->os); cache_int(&cache_hash, g->zig_target->abi); + if (g->zig_target->cpu_features != nullptr) { + const char *ptr; + size_t len; + stage2_cpu_features_get_cache_hash(g->zig_target->cpu_features, &ptr, &len); + cache_str(&cache_hash, ptr); + } if (g->zig_target->glibc_version != nullptr) { cache_int(&cache_hash, g->zig_target->glibc_version->major); cache_int(&cache_hash, g->zig_target->glibc_version->minor); @@ -8765,37 +8713,25 @@ static void init(CodeGen *g) { reloc_mode = LLVMRelocStatic; } - const char *target_specific_cpu_args; - const char *target_specific_features; + const char *target_specific_cpu_args = ""; + const char *target_specific_features = ""; + if (g->zig_target->is_native) { - // LLVM creates invalid binaries on Windows sometimes. - // See https://github.com/ziglang/zig/issues/508 - // As a workaround we do not use target native features on Windows. - if (g->zig_target->os == OsWindows || g->zig_target->os == OsUefi) { - target_specific_cpu_args = ""; - target_specific_features = ""; - } else { - target_specific_cpu_args = ZigLLVMGetHostCPUName(); - target_specific_features = ZigLLVMGetNativeFeatures(); - } - } else if (target_is_riscv(g->zig_target)) { - // TODO https://github.com/ziglang/zig/issues/2883 - // Be aware of https://github.com/ziglang/zig/issues/3275 - target_specific_cpu_args = ""; - target_specific_features = riscv_default_features; - } else if (g->zig_target->arch == ZigLLVM_x86) { - // This is because we're really targeting i686 rather than i386. - // It's pretty much impossible to use many of the language features - // such as fp16 if you stick use the x87 only. This is also what clang - // uses as base cpu. - // TODO https://github.com/ziglang/zig/issues/2883 - target_specific_cpu_args = "pentium4"; - target_specific_features = (g->zig_target->os == OsFreestanding) ? "-sse": ""; - } else { - target_specific_cpu_args = ""; - target_specific_features = ""; + target_specific_cpu_args = ZigLLVMGetHostCPUName(); + target_specific_features = ZigLLVMGetNativeFeatures(); } + // Override CPU and features if defined by user. + if (g->zig_target->cpu_features != nullptr) { + target_specific_cpu_args = stage2_cpu_features_get_llvm_cpu(g->zig_target->cpu_features); + target_specific_features = stage2_cpu_features_get_llvm_features(g->zig_target->cpu_features); + } + if (g->verbose_llvm_cpu_features) { + fprintf(stderr, "name=%s triple=%s\n", buf_ptr(g->root_out_name), buf_ptr(&g->llvm_triple_str)); + fprintf(stderr, "name=%s target_specific_cpu_args=%s\n", buf_ptr(g->root_out_name), target_specific_cpu_args); + fprintf(stderr, "name=%s target_specific_features=%s\n", buf_ptr(g->root_out_name), target_specific_features); + } + g->target_machine = ZigLLVMCreateTargetMachine(target_ref, buf_ptr(&g->llvm_triple_str), target_specific_cpu_args, target_specific_features, opt_level, reloc_mode, LLVMCodeModelDefault, g->function_sections); @@ -8842,15 +8778,17 @@ static void init(CodeGen *g) { define_builtin_types(g); define_intern_values(g); - IrInstruction *sentinel_instructions = allocate(2); - g->invalid_instruction = &sentinel_instructions[0]; - g->invalid_instruction->value = allocate(1, "ZigValue"); - g->invalid_instruction->value->type = g->builtin_types.entry_invalid; + IrInstGen *sentinel_instructions = allocate(2); + g->invalid_inst_gen = &sentinel_instructions[0]; + g->invalid_inst_gen->value = allocate(1, "ZigValue"); + g->invalid_inst_gen->value->type = g->builtin_types.entry_invalid; g->unreach_instruction = &sentinel_instructions[1]; g->unreach_instruction->value = allocate(1, "ZigValue"); g->unreach_instruction->value->type = g->builtin_types.entry_unreachable; + g->invalid_inst_src = allocate(1); + define_builtin_fns(g); Error err; if ((err = define_builtin_compile_vars(g))) { @@ -8992,7 +8930,10 @@ static void detect_libc(CodeGen *g) { "See `zig libc --help` for more details.\n", err_str(err)); exit(1); } - if ((err = os_make_path(g->cache_dir))) { + Buf libc_txt_dir = BUF_INIT; + os_path_dirname(libc_txt, &libc_txt_dir); + buf_deinit(&libc_txt_dir); + if ((err = os_make_path(&libc_txt_dir))) { fprintf(stderr, "Unable to create %s directory: %s\n", buf_ptr(g->cache_dir), err_str(err)); exit(1); @@ -9121,21 +9062,22 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa args.append("-target"); args.append(buf_ptr(&g->llvm_triple_str)); - if (target_is_musl(g->zig_target) && target_is_riscv(g->zig_target)) { - // Musl depends on atomic instructions, which are disabled by default in Clang/LLVM's - // cross compilation CPU info for RISCV. - // TODO: https://github.com/ziglang/zig/issues/2883 + const char *llvm_cpu = stage2_cpu_features_get_llvm_cpu(g->zig_target->cpu_features); + if (llvm_cpu != nullptr) { + args.append("-Xclang"); + args.append("-target-cpu"); + args.append("-Xclang"); + args.append(llvm_cpu); + } + const char *llvm_target_features = stage2_cpu_features_get_llvm_features(g->zig_target->cpu_features); + if (llvm_target_features != nullptr) { args.append("-Xclang"); args.append("-target-feature"); args.append("-Xclang"); - args.append(riscv_default_features); - } else if (g->zig_target->os == OsFreestanding && g->zig_target->arch == ZigLLVM_x86) { - args.append("-Xclang"); - args.append("-target-feature"); - args.append("-Xclang"); - args.append("-sse"); + args.append(llvm_target_features); } } + if (g->zig_target->os == OsFreestanding) { args.append("-ffreestanding"); } @@ -9783,6 +9725,7 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e zig_unreachable(); case ZigTypeIdVoid: case ZigTypeIdUnreachable: + return; case ZigTypeIdBool: g->c_want_stdbool = true; return; @@ -10329,6 +10272,12 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { cache_int(ch, g->zig_target->vendor); cache_int(ch, g->zig_target->os); cache_int(ch, g->zig_target->abi); + if (g->zig_target->cpu_features != nullptr) { + const char *ptr; + size_t len; + stage2_cpu_features_get_cache_hash(g->zig_target->cpu_features, &ptr, &len); + cache_str(ch, ptr); + } if (g->zig_target->glibc_version != nullptr) { cache_int(ch, g->zig_target->glibc_version->major); cache_int(ch, g->zig_target->glibc_version->minor); @@ -10669,6 +10618,7 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o child_gen->verbose_llvm_ir = parent_gen->verbose_llvm_ir; child_gen->verbose_cimport = parent_gen->verbose_cimport; child_gen->verbose_cc = parent_gen->verbose_cc; + child_gen->verbose_llvm_cpu_features = parent_gen->verbose_llvm_cpu_features; child_gen->llvm_argv = parent_gen->llvm_argv; child_gen->dynamic_linker_path = parent_gen->dynamic_linker_path; diff --git a/src/error.cpp b/src/error.cpp index 9fc0383b1b..5bf1667db9 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -58,6 +58,12 @@ const char *err_str(Error err) { case ErrorNotLazy: return "not lazy"; case ErrorIsAsync: return "is async"; case ErrorImportOutsidePkgPath: return "import of file outside package path"; + case ErrorUnknownCpu: return "unknown CPU"; + case ErrorUnknownSubArchitecture: return "unknown sub-architecture"; + case ErrorUnknownCpuFeature: return "unknown CPU feature"; + case ErrorInvalidCpuFeatures: return "invalid CPU features"; + case ErrorInvalidLlvmCpuFeaturesFormat: return "invalid LLVM CPU features format"; + case ErrorUnknownApplicationBinaryInterface: return "unknown application binary interface"; } return "(invalid error)"; } diff --git a/src/ir.cpp b/src/ir.cpp index cb47806f1b..4e06ab5f65 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -17,27 +17,33 @@ #include -struct IrBuilder { +struct IrBuilderSrc { CodeGen *codegen; - IrExecutable *exec; - IrBasicBlock *current_basic_block; + IrExecutableSrc *exec; + IrBasicBlockSrc *current_basic_block; AstNode *main_block_node; }; +struct IrBuilderGen { + CodeGen *codegen; + IrExecutableGen *exec; + IrBasicBlockGen *current_basic_block; +}; + struct IrAnalyze { CodeGen *codegen; - IrBuilder old_irb; - IrBuilder new_irb; + IrBuilderSrc old_irb; + IrBuilderGen new_irb; size_t old_bb_index; size_t instruction_index; ZigType *explicit_return_type; AstNode *explicit_return_type_source_node; - ZigList src_implicit_return_type_list; + ZigList src_implicit_return_type_list; ZigList resume_stack; - IrBasicBlock *const_predecessor_bb; + IrBasicBlockSrc *const_predecessor_bb; size_t ref_count; size_t break_debug_id; // for debugging purposes - IrInstruction *return_ptr; + IrInstGen *return_ptr; // For the purpose of using in a debugger void dump(); @@ -202,412 +208,537 @@ struct DbgIrBreakPoint { DbgIrBreakPoint dbg_ir_breakpoints_buf[20]; size_t dbg_ir_breakpoints_count = 0; -static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope); -static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval, +static IrInstSrc *ir_gen_node(IrBuilderSrc *irb, AstNode *node, Scope *scope); +static IrInstSrc *ir_gen_node_extra(IrBuilderSrc *irb, AstNode *node, Scope *scope, LVal lval, ResultLoc *result_loc); -static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type); -static IrInstruction *ir_implicit_cast2(IrAnalyze *ira, IrInstruction *value_source_instr, - IrInstruction *value, ZigType *expected_type); -static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr, +static IrInstGen *ir_implicit_cast(IrAnalyze *ira, IrInstGen *value, ZigType *expected_type); +static IrInstGen *ir_implicit_cast2(IrAnalyze *ira, IrInst *value_source_instr, + IrInstGen *value, ZigType *expected_type); +static IrInstGen *ir_get_deref(IrAnalyze *ira, IrInst *source_instr, IrInstGen *ptr, ResultLoc *result_loc); -static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg); -static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name, - IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing); -static void ir_assert(bool ok, IrInstruction *source_instruction); -static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var); -static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op); -static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval, ResultLoc *result_loc); -static IrInstruction *ir_expr_wrap(IrBuilder *irb, Scope *scope, IrInstruction *inst, ResultLoc *result_loc); +static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutableSrc *exec, AstNode *source_node, Buf *msg); +static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name, + IrInst* source_instr, IrInstGen *container_ptr, ZigType *container_type, bool initializing); +static void ir_assert(bool ok, IrInst* source_instruction); +static void ir_assert_gen(bool ok, IrInstGen *source_instruction); +static IrInstGen *ir_get_var_ptr(IrAnalyze *ira, IrInst *source_instr, ZigVar *var); +static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op); +static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value, LVal lval, ResultLoc *result_loc); +static IrInstSrc *ir_expr_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc); static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align); static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align); static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ZigValue *val); static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val); static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, ZigValue *out_val, ZigValue *ptr_val); -static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr, - ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on); -static ZigValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed); +static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrInstGen *ptr, + ZigType *dest_type, IrInst *dest_type_src, bool safety_check_on); +static ZigValue *ir_resolve_const(IrAnalyze *ira, IrInstGen *value, UndefAllowed undef_allowed); static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align); -static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target, +static IrInstGen *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInst* source_instr, IrInstGen *target, ZigType *ptr_type); -static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, +static IrInstGen *ir_analyze_bit_cast(IrAnalyze *ira, IrInst* source_instr, IrInstGen *value, ZigType *dest_type); -static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr, - ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, - bool allow_discard); -static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr, - ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, - bool allow_discard); -static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *base_ptr, bool safety_check_on, bool initializing); -static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *base_ptr, bool safety_check_on, bool initializing); -static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *base_ptr, bool initializing); -static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *ptr, IrInstruction *uncasted_value, bool allow_write_through_const); -static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *union_type, IrInstruction *field_name, AstNode *expr_node, +static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_instr, + ResultLoc *result_loc, ZigType *value_type, IrInstGen *value, bool force_runtime, bool allow_discard); +static IrInstGen *ir_resolve_result(IrAnalyze *ira, IrInst *suspend_source_instr, + ResultLoc *result_loc, ZigType *value_type, IrInstGen *value, bool force_runtime, bool allow_discard); +static IrInstGen *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *base_ptr, bool safety_check_on, bool initializing); +static IrInstGen *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *base_ptr, bool safety_check_on, bool initializing); +static IrInstGen *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *base_ptr, bool initializing); +static IrInstGen *ir_analyze_store_ptr(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *ptr, IrInstGen *uncasted_value, bool allow_write_through_const); +static IrInstSrc *ir_gen_union_init_expr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *union_type, IrInstSrc *field_name, AstNode *expr_node, LVal lval, ResultLoc *parent_result_loc); static void ir_reset_result(ResultLoc *result_loc); -static Buf *get_anon_type_name(CodeGen *codegen, IrExecutable *exec, const char *kind_name, +static Buf *get_anon_type_name(CodeGen *codegen, IrExecutableSrc *exec, const char *kind_name, Scope *scope, AstNode *source_node, Buf *out_bare_name); -static ResultLocCast *ir_build_cast_result_loc(IrBuilder *irb, IrInstruction *dest_type, +static ResultLocCast *ir_build_cast_result_loc(IrBuilderSrc *irb, IrInstSrc *dest_type, ResultLoc *parent_result_loc); -static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction *source_instr, - TypeStructField *field, IrInstruction *struct_ptr, ZigType *struct_type, bool initializing); -static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name, - IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type); +static IrInstGen *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInst* source_instr, + TypeStructField *field, IrInstGen *struct_ptr, ZigType *struct_type, bool initializing); +static IrInstGen *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name, + IrInst* source_instr, IrInstGen *container_ptr, ZigType *container_type); static ResultLoc *no_result_loc(void); -static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value); +static IrInstGen *ir_analyze_test_non_null(IrAnalyze *ira, IrInst *source_inst, IrInstGen *value); +static IrInstGen *ir_error_dependency_loop(IrAnalyze *ira, IrInst *source_instr); -static void destroy_instruction(IrInstruction *inst) { +static void destroy_instruction_src(IrInstSrc *inst) { #ifdef ZIG_ENABLE_MEM_PROFILE - const char *name = ir_instruction_type_str(inst->id); + const char *name = ir_inst_src_type_str(inst->id); #else const char *name = nullptr; #endif switch (inst->id) { - case IrInstructionIdInvalid: + case IrInstSrcIdInvalid: zig_unreachable(); - case IrInstructionIdReturn: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdConst: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdBinOp: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdMergeErrSets: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdDeclVarSrc: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdCast: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdCallSrc: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdCallSrcArgs: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdCallExtra: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdCallGen: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdUnOp: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdCondBr: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdBr: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdPhi: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdContainerInitList: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdContainerInitFields: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdUnreachable: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdElemPtr: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdVarPtr: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdReturnPtr: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdLoadPtr: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdLoadPtrGen: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdStorePtr: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdVectorStoreElem: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdTypeOf: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdFieldPtr: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdStructFieldPtr: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdUnionFieldPtr: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSetCold: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSetRuntimeSafety: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSetFloatMode: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdArrayType: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSliceType: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdAnyFrameType: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdAsmSrc: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdAsmGen: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSizeOf: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdTestNonNull: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdOptionalUnwrapPtr: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdPopCount: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdClz: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdCtz: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdBswap: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdBitReverse: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSwitchBr: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSwitchVar: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSwitchElseVar: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSwitchTarget: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdUnionTag: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdImport: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdRef: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdRefGen: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdCompileErr: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdCompileLog: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdErrName: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdCImport: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdCInclude: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdCDefine: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdCUndef: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdEmbedFile: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdCmpxchgSrc: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdCmpxchgGen: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdFence: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdTruncate: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdIntCast: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdFloatCast: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdErrSetCast: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdFromBytes: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdToBytes: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdIntToFloat: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdFloatToInt: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdBoolToInt: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdIntType: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdVectorType: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdShuffleVector: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSplatSrc: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSplatGen: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdBoolNot: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdMemset: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdMemcpy: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSliceSrc: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSliceGen: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdMemberCount: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdMemberType: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdMemberName: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdBreakpoint: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdReturnAddress: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdFrameAddress: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdFrameHandle: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdFrameType: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdFrameSizeSrc: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdFrameSizeGen: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdAlignOf: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdOverflowOp: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdTestErrSrc: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdTestErrGen: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdUnwrapErrCode: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdUnwrapErrPayload: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdOptionalWrap: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdErrWrapCode: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdErrWrapPayload: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdFnProto: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdTestComptime: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdPtrCastSrc: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdPtrCastGen: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdBitCastSrc: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdBitCastGen: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdWidenOrShorten: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdPtrToInt: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdIntToPtr: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdIntToEnum: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdIntToErr: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdErrToInt: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdCheckSwitchProngs: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdCheckStatementIsVoid: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdTypeName: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdTagName: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdPtrType: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdDeclRef: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdPanic: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdFieldParentPtr: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdByteOffsetOf: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdBitOffsetOf: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdTypeInfo: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdType: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdHasField: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdTypeId: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSetEvalBranchQuota: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdAlignCast: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdImplicitCast: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdResolveResult: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdResetResult: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdOpaqueType: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSetAlignStack: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdArgType: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdTagType: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdExport: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdErrorReturnTrace: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdErrorUnion: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdAtomicRmw: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSaveErrRetAddr: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdAddImplicitReturnType: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdFloatOp: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdMulAdd: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdAtomicLoad: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdAtomicStore: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdEnumToInt: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdCheckRuntimeScope: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdDeclVarGen: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdArrayToVector: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdVectorToArray: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdPtrOfArrayToSlice: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdAssertZero: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdAssertNonNull: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdResizeSlice: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdHasDecl: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdUndeclaredIdent: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdAllocaSrc: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdAllocaGen: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdEndExpr: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdUnionInitNamedField: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSuspendBegin: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSuspendFinish: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdResume: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdAwaitSrc: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdAwaitGen: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSpillBegin: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdSpillEnd: - return destroy(reinterpret_cast(inst), name); - case IrInstructionIdVectorExtractElem: - return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdReturn: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdConst: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdBinOp: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdMergeErrSets: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdDeclVar: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdCall: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdCallExtra: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdUnOp: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdCondBr: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdBr: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdPhi: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdContainerInitList: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdContainerInitFields: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdUnreachable: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdElemPtr: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdVarPtr: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdLoadPtr: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdStorePtr: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdTypeOf: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdFieldPtr: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdSetCold: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdSetRuntimeSafety: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdSetFloatMode: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdArrayType: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdSliceType: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdAnyFrameType: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdAsm: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdSizeOf: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdTestNonNull: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdOptionalUnwrapPtr: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdPopCount: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdClz: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdCtz: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdBswap: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdBitReverse: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdSwitchBr: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdSwitchVar: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdSwitchElseVar: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdSwitchTarget: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdImport: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdRef: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdCompileErr: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdCompileLog: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdErrName: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdCImport: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdCInclude: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdCDefine: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdCUndef: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdEmbedFile: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdCmpxchg: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdFence: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdTruncate: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdIntCast: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdFloatCast: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdErrSetCast: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdFromBytes: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdToBytes: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdIntToFloat: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdFloatToInt: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdBoolToInt: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdIntType: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdVectorType: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdShuffleVector: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdSplat: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdBoolNot: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdMemset: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdMemcpy: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdSlice: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdMemberCount: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdMemberType: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdMemberName: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdBreakpoint: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdReturnAddress: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdFrameAddress: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdFrameHandle: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdFrameType: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdFrameSize: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdAlignOf: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdOverflowOp: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdTestErr: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdUnwrapErrCode: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdUnwrapErrPayload: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdFnProto: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdTestComptime: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdPtrCast: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdBitCast: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdPtrToInt: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdIntToPtr: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdIntToEnum: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdIntToErr: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdErrToInt: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdCheckSwitchProngs: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdCheckStatementIsVoid: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdTypeName: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdTagName: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdPtrType: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdDeclRef: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdPanic: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdFieldParentPtr: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdByteOffsetOf: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdBitOffsetOf: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdTypeInfo: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdType: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdHasField: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdTypeId: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdSetEvalBranchQuota: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdAlignCast: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdImplicitCast: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdResolveResult: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdResetResult: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdOpaqueType: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdSetAlignStack: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdArgType: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdTagType: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdExport: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdErrorReturnTrace: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdErrorUnion: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdAtomicRmw: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdSaveErrRetAddr: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdAddImplicitReturnType: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdFloatOp: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdMulAdd: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdAtomicLoad: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdAtomicStore: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdEnumToInt: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdCheckRuntimeScope: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdHasDecl: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdUndeclaredIdent: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdAlloca: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdEndExpr: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdUnionInitNamedField: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdSuspendBegin: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdSuspendFinish: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdResume: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdAwait: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdSpillBegin: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdSpillEnd: + return destroy(reinterpret_cast(inst), name); + case IrInstSrcIdCallArgs: + return destroy(reinterpret_cast(inst), name); + } + zig_unreachable(); +} + +void destroy_instruction_gen(IrInstGen *inst) { +#ifdef ZIG_ENABLE_MEM_PROFILE + const char *name = ir_inst_gen_type_str(inst->id); +#else + const char *name = nullptr; +#endif + switch (inst->id) { + case IrInstGenIdInvalid: + zig_unreachable(); + case IrInstGenIdReturn: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdConst: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdBinOp: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdCast: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdCall: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdCondBr: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdBr: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdPhi: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdUnreachable: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdElemPtr: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdVarPtr: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdReturnPtr: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdLoadPtr: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdStorePtr: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdVectorStoreElem: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdStructFieldPtr: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdUnionFieldPtr: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdAsm: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdTestNonNull: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdOptionalUnwrapPtr: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdPopCount: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdClz: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdCtz: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdBswap: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdBitReverse: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdSwitchBr: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdUnionTag: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdRef: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdErrName: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdCmpxchg: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdFence: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdTruncate: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdShuffleVector: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdSplat: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdBoolNot: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdMemset: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdMemcpy: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdSlice: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdBreakpoint: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdReturnAddress: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdFrameAddress: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdFrameHandle: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdFrameSize: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdOverflowOp: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdTestErr: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdUnwrapErrCode: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdUnwrapErrPayload: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdOptionalWrap: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdErrWrapCode: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdErrWrapPayload: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdPtrCast: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdBitCast: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdWidenOrShorten: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdPtrToInt: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdIntToPtr: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdIntToEnum: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdIntToErr: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdErrToInt: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdTagName: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdPanic: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdFieldParentPtr: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdAlignCast: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdErrorReturnTrace: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdAtomicRmw: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdSaveErrRetAddr: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdFloatOp: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdMulAdd: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdAtomicLoad: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdAtomicStore: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdDeclVar: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdArrayToVector: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdVectorToArray: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdPtrOfArrayToSlice: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdAssertZero: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdAssertNonNull: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdResizeSlice: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdAlloca: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdSuspendBegin: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdSuspendFinish: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdResume: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdAwait: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdSpillBegin: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdSpillEnd: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdVectorExtractElem: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdBinaryNot: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdNegation: + return destroy(reinterpret_cast(inst), name); + case IrInstGenIdNegationWrapping: + return destroy(reinterpret_cast(inst), name); } zig_unreachable(); } @@ -623,17 +754,17 @@ static void ira_deref(IrAnalyze *ira) { assert(ira->ref_count != 0); for (size_t bb_i = 0; bb_i < ira->old_irb.exec->basic_block_list.length; bb_i += 1) { - IrBasicBlock *pass1_bb = ira->old_irb.exec->basic_block_list.items[bb_i]; + IrBasicBlockSrc *pass1_bb = ira->old_irb.exec->basic_block_list.items[bb_i]; for (size_t inst_i = 0; inst_i < pass1_bb->instruction_list.length; inst_i += 1) { - IrInstruction *pass1_inst = pass1_bb->instruction_list.items[inst_i]; - destroy_instruction(pass1_inst); + IrInstSrc *pass1_inst = pass1_bb->instruction_list.items[inst_i]; + destroy_instruction_src(pass1_inst); } - destroy(pass1_bb, "IrBasicBlock"); + destroy(pass1_bb, "IrBasicBlockSrc"); } ira->old_irb.exec->basic_block_list.deinit(); ira->old_irb.exec->tld_list.deinit(); // cannot destroy here because of var->owner_exec - //destroy(ira->old_irb.exec, "IrExecutablePass1"); + //destroy(ira->old_irb.exec, "IrExecutableSrc"); ira->src_implicit_return_type_list.deinit(); ira->resume_stack.deinit(); destroy(ira, "IrAnalyze"); @@ -780,7 +911,7 @@ static bool types_have_same_zig_comptime_repr(CodeGen *codegen, ZigType *expecte zig_unreachable(); } -static bool ir_should_inline(IrExecutable *exec, Scope *scope) { +static bool ir_should_inline(IrExecutableSrc *exec, Scope *scope) { if (exec->is_inline) return true; @@ -796,23 +927,35 @@ static bool ir_should_inline(IrExecutable *exec, Scope *scope) { return false; } -static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) { +static void ir_instruction_append(IrBasicBlockSrc *basic_block, IrInstSrc *instruction) { assert(basic_block); assert(instruction); basic_block->instruction_list.append(instruction); } -static size_t exec_next_debug_id(IrExecutable *exec) { +static void ir_inst_gen_append(IrBasicBlockGen *basic_block, IrInstGen *instruction) { + assert(basic_block); + assert(instruction); + basic_block->instruction_list.append(instruction); +} + +static size_t exec_next_debug_id(IrExecutableSrc *exec) { size_t result = exec->next_debug_id; exec->next_debug_id += 1; return result; } -static ZigFn *exec_fn_entry(IrExecutable *exec) { +static size_t exec_next_debug_id_gen(IrExecutableGen *exec) { + size_t result = exec->next_debug_id; + exec->next_debug_id += 1; + return result; +} + +static ZigFn *exec_fn_entry(IrExecutableSrc *exec) { return exec->fn_entry; } -static Buf *exec_c_import_buf(IrExecutable *exec) { +static Buf *exec_c_import_buf(IrExecutableSrc *exec) { return exec->c_import_buf; } @@ -820,28 +963,42 @@ static bool value_is_comptime(ZigValue *const_val) { return const_val->special != ConstValSpecialRuntime; } -static bool instr_is_comptime(IrInstruction *instruction) { +static bool instr_is_comptime(IrInstGen *instruction) { return value_is_comptime(instruction->value); } -static bool instr_is_unreachable(IrInstruction *instruction) { - return instruction->value->type && instruction->value->type->id == ZigTypeIdUnreachable; +static bool instr_is_unreachable(IrInstSrc *instruction) { + return instruction->is_noreturn; } -static void ir_link_new_bb(IrBasicBlock *new_bb, IrBasicBlock *old_bb) { - new_bb->other = old_bb; - old_bb->other = new_bb; +static void ir_link_new_bb(IrBasicBlockGen *new_bb, IrBasicBlockSrc *old_bb) { + new_bb->parent = old_bb; + old_bb->child = new_bb; } -static void ir_ref_bb(IrBasicBlock *bb) { +static void ir_ref_bb(IrBasicBlockSrc *bb) { bb->ref_count += 1; } -static void ir_ref_instruction(IrInstruction *instruction, IrBasicBlock *cur_bb) { - assert(instruction->id != IrInstructionIdInvalid); - instruction->ref_count += 1; - if (instruction->owner_bb != cur_bb && !instr_is_comptime(instruction)) +static void ir_ref_bb_gen(IrBasicBlockGen *bb) { + bb->ref_count += 1; +} + +static void ir_ref_instruction(IrInstSrc *instruction, IrBasicBlockSrc *cur_bb) { + assert(instruction->id != IrInstSrcIdInvalid); + instruction->base.ref_count += 1; + if (instruction->owner_bb != cur_bb && !instr_is_unreachable(instruction) + && instruction->id != IrInstSrcIdConst) + { ir_ref_bb(instruction->owner_bb); + } +} + +static void ir_ref_inst_gen(IrInstGen *instruction, IrBasicBlockGen *cur_bb) { + assert(instruction->id != IrInstGenIdInvalid); + instruction->base.ref_count += 1; + if (instruction->owner_bb != cur_bb && !instr_is_comptime(instruction)) + ir_ref_bb_gen(instruction->owner_bb); } static void ir_ref_var(ZigVar *var) { @@ -890,962 +1047,1259 @@ ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) { return res_type; } -static IrBasicBlock *ir_create_basic_block(IrBuilder *irb, Scope *scope, const char *name_hint) { - IrBasicBlock *result = allocate(1, "IrBasicBlock"); +static IrBasicBlockSrc *ir_create_basic_block(IrBuilderSrc *irb, Scope *scope, const char *name_hint) { + IrBasicBlockSrc *result = allocate(1, "IrBasicBlockSrc"); result->scope = scope; result->name_hint = name_hint; result->debug_id = exec_next_debug_id(irb->exec); - result->index = SIZE_MAX; // set later + result->index = UINT32_MAX; // set later return result; } -static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) { - IrBasicBlock *new_bb = ir_create_basic_block(irb, other_bb->scope, other_bb->name_hint); +static IrBasicBlockGen *ir_create_basic_block_gen(IrAnalyze *ira, Scope *scope, const char *name_hint) { + IrBasicBlockGen *result = allocate(1, "IrBasicBlockGen"); + result->scope = scope; + result->name_hint = name_hint; + result->debug_id = exec_next_debug_id_gen(ira->new_irb.exec); + result->index = UINT32_MAX; // set later + return result; +} + +static IrBasicBlockGen *ir_build_bb_from(IrAnalyze *ira, IrBasicBlockSrc *other_bb) { + IrBasicBlockGen *new_bb = ir_create_basic_block_gen(ira, other_bb->scope, other_bb->name_hint); ir_link_new_bb(new_bb, other_bb); return new_bb; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVarSrc *) { - return IrInstructionIdDeclVarSrc; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcDeclVar *) { + return IrInstSrcIdDeclVar; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVarGen *) { - return IrInstructionIdDeclVarGen; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcBr *) { + return IrInstSrcIdBr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) { - return IrInstructionIdCondBr; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCondBr *) { + return IrInstSrcIdCondBr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionBr *) { - return IrInstructionIdBr; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchBr *) { + return IrInstSrcIdSwitchBr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSwitchBr *) { - return IrInstructionIdSwitchBr; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchVar *) { + return IrInstSrcIdSwitchVar; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSwitchVar *) { - return IrInstructionIdSwitchVar; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchElseVar *) { + return IrInstSrcIdSwitchElseVar; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSwitchElseVar *) { - return IrInstructionIdSwitchElseVar; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchTarget *) { + return IrInstSrcIdSwitchTarget; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSwitchTarget *) { - return IrInstructionIdSwitchTarget; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcPhi *) { + return IrInstSrcIdPhi; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionPhi *) { - return IrInstructionIdPhi; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnOp *) { + return IrInstSrcIdUnOp; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionUnOp *) { - return IrInstructionIdUnOp; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcBinOp *) { + return IrInstSrcIdBinOp; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionBinOp *) { - return IrInstructionIdBinOp; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcMergeErrSets *) { + return IrInstSrcIdMergeErrSets; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionMergeErrSets *) { - return IrInstructionIdMergeErrSets; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcLoadPtr *) { + return IrInstSrcIdLoadPtr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionExport *) { - return IrInstructionIdExport; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcStorePtr *) { + return IrInstSrcIdStorePtr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionLoadPtr *) { - return IrInstructionIdLoadPtr; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFieldPtr *) { + return IrInstSrcIdFieldPtr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionLoadPtrGen *) { - return IrInstructionIdLoadPtrGen; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcElemPtr *) { + return IrInstSrcIdElemPtr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionStorePtr *) { - return IrInstructionIdStorePtr; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcVarPtr *) { + return IrInstSrcIdVarPtr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorStoreElem *) { - return IrInstructionIdVectorStoreElem; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCall *) { + return IrInstSrcIdCall; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldPtr *) { - return IrInstructionIdFieldPtr; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCallArgs *) { + return IrInstSrcIdCallArgs; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionStructFieldPtr *) { - return IrInstructionIdStructFieldPtr; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCallExtra *) { + return IrInstSrcIdCallExtra; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionFieldPtr *) { - return IrInstructionIdUnionFieldPtr; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcConst *) { + return IrInstSrcIdConst; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionElemPtr *) { - return IrInstructionIdElemPtr; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcReturn *) { + return IrInstSrcIdReturn; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionVarPtr *) { - return IrInstructionIdVarPtr; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcContainerInitList *) { + return IrInstSrcIdContainerInitList; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionReturnPtr *) { - return IrInstructionIdReturnPtr; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcContainerInitFields *) { + return IrInstSrcIdContainerInitFields; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionCallSrc *) { - return IrInstructionIdCallSrc; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnreachable *) { + return IrInstSrcIdUnreachable; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionCallSrcArgs *) { - return IrInstructionIdCallSrcArgs; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcTypeOf *) { + return IrInstSrcIdTypeOf; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionCallExtra *) { - return IrInstructionIdCallExtra; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetCold *) { + return IrInstSrcIdSetCold; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionCallGen *) { - return IrInstructionIdCallGen; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetRuntimeSafety *) { + return IrInstSrcIdSetRuntimeSafety; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionConst *) { - return IrInstructionIdConst; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetFloatMode *) { + return IrInstSrcIdSetFloatMode; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionReturn *) { - return IrInstructionIdReturn; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcArrayType *) { + return IrInstSrcIdArrayType; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) { - return IrInstructionIdCast; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAnyFrameType *) { + return IrInstSrcIdAnyFrameType; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionResizeSlice *) { - return IrInstructionIdResizeSlice; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSliceType *) { + return IrInstSrcIdSliceType; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionContainerInitList *) { - return IrInstructionIdContainerInitList; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAsm *) { + return IrInstSrcIdAsm; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionContainerInitFields *) { - return IrInstructionIdContainerInitFields; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSizeOf *) { + return IrInstSrcIdSizeOf; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionUnreachable *) { - return IrInstructionIdUnreachable; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcTestNonNull *) { + return IrInstSrcIdTestNonNull; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeOf *) { - return IrInstructionIdTypeOf; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcOptionalUnwrapPtr *) { + return IrInstSrcIdOptionalUnwrapPtr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSetCold *) { - return IrInstructionIdSetCold; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcClz *) { + return IrInstSrcIdClz; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSetRuntimeSafety *) { - return IrInstructionIdSetRuntimeSafety; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCtz *) { + return IrInstSrcIdCtz; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFloatMode *) { - return IrInstructionIdSetFloatMode; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcPopCount *) { + return IrInstSrcIdPopCount; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayType *) { - return IrInstructionIdArrayType; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcBswap *) { + return IrInstSrcIdBswap; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionAnyFrameType *) { - return IrInstructionIdAnyFrameType; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcBitReverse *) { + return IrInstSrcIdBitReverse; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceType *) { - return IrInstructionIdSliceType; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcImport *) { + return IrInstSrcIdImport; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionAsmSrc *) { - return IrInstructionIdAsmSrc; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCImport *) { + return IrInstSrcIdCImport; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionAsmGen *) { - return IrInstructionIdAsmGen; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCInclude *) { + return IrInstSrcIdCInclude; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSizeOf *) { - return IrInstructionIdSizeOf; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCDefine *) { + return IrInstSrcIdCDefine; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionTestNonNull *) { - return IrInstructionIdTestNonNull; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCUndef *) { + return IrInstSrcIdCUndef; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionOptionalUnwrapPtr *) { - return IrInstructionIdOptionalUnwrapPtr; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcRef *) { + return IrInstSrcIdRef; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionClz *) { - return IrInstructionIdClz; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCompileErr *) { + return IrInstSrcIdCompileErr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionCtz *) { - return IrInstructionIdCtz; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCompileLog *) { + return IrInstSrcIdCompileLog; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionPopCount *) { - return IrInstructionIdPopCount; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrName *) { + return IrInstSrcIdErrName; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionBswap *) { - return IrInstructionIdBswap; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcEmbedFile *) { + return IrInstSrcIdEmbedFile; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionBitReverse *) { - return IrInstructionIdBitReverse; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCmpxchg *) { + return IrInstSrcIdCmpxchg; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionTag *) { - return IrInstructionIdUnionTag; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFence *) { + return IrInstSrcIdFence; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionImport *) { - return IrInstructionIdImport; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcTruncate *) { + return IrInstSrcIdTruncate; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionCImport *) { - return IrInstructionIdCImport; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntCast *) { + return IrInstSrcIdIntCast; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionCInclude *) { - return IrInstructionIdCInclude; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFloatCast *) { + return IrInstSrcIdFloatCast; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionCDefine *) { - return IrInstructionIdCDefine; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToFloat *) { + return IrInstSrcIdIntToFloat; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionCUndef *) { - return IrInstructionIdCUndef; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFloatToInt *) { + return IrInstSrcIdFloatToInt; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionRef *) { - return IrInstructionIdRef; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcBoolToInt *) { + return IrInstSrcIdBoolToInt; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionRefGen *) { - return IrInstructionIdRefGen; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntType *) { + return IrInstSrcIdIntType; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionCompileErr *) { - return IrInstructionIdCompileErr; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcVectorType *) { + return IrInstSrcIdVectorType; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionCompileLog *) { - return IrInstructionIdCompileLog; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcShuffleVector *) { + return IrInstSrcIdShuffleVector; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionErrName *) { - return IrInstructionIdErrName; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSplat *) { + return IrInstSrcIdSplat; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionEmbedFile *) { - return IrInstructionIdEmbedFile; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcBoolNot *) { + return IrInstSrcIdBoolNot; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgSrc *) { - return IrInstructionIdCmpxchgSrc; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemset *) { + return IrInstSrcIdMemset; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgGen *) { - return IrInstructionIdCmpxchgGen; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemcpy *) { + return IrInstSrcIdMemcpy; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionFence *) { - return IrInstructionIdFence; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSlice *) { + return IrInstSrcIdSlice; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionTruncate *) { - return IrInstructionIdTruncate; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemberCount *) { + return IrInstSrcIdMemberCount; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionIntCast *) { - return IrInstructionIdIntCast; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemberType *) { + return IrInstSrcIdMemberType; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionFloatCast *) { - return IrInstructionIdFloatCast; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemberName *) { + return IrInstSrcIdMemberName; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionErrSetCast *) { - return IrInstructionIdErrSetCast; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcBreakpoint *) { + return IrInstSrcIdBreakpoint; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionToBytes *) { - return IrInstructionIdToBytes; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcReturnAddress *) { + return IrInstSrcIdReturnAddress; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionFromBytes *) { - return IrInstructionIdFromBytes; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameAddress *) { + return IrInstSrcIdFrameAddress; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToFloat *) { - return IrInstructionIdIntToFloat; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameHandle *) { + return IrInstSrcIdFrameHandle; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionFloatToInt *) { - return IrInstructionIdFloatToInt; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameType *) { + return IrInstSrcIdFrameType; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolToInt *) { - return IrInstructionIdBoolToInt; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameSize *) { + return IrInstSrcIdFrameSize; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionIntType *) { - return IrInstructionIdIntType; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAlignOf *) { + return IrInstSrcIdAlignOf; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorType *) { - return IrInstructionIdVectorType; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcOverflowOp *) { + return IrInstSrcIdOverflowOp; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionShuffleVector *) { - return IrInstructionIdShuffleVector; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcTestErr *) { + return IrInstSrcIdTestErr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSplatSrc *) { - return IrInstructionIdSplatSrc; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcMulAdd *) { + return IrInstSrcIdMulAdd; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSplatGen *) { - return IrInstructionIdSplatGen; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFloatOp *) { + return IrInstSrcIdFloatOp; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) { - return IrInstructionIdBoolNot; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnwrapErrCode *) { + return IrInstSrcIdUnwrapErrCode; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionMemset *) { - return IrInstructionIdMemset; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnwrapErrPayload *) { + return IrInstSrcIdUnwrapErrPayload; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionMemcpy *) { - return IrInstructionIdMemcpy; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFnProto *) { + return IrInstSrcIdFnProto; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceSrc *) { - return IrInstructionIdSliceSrc; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcTestComptime *) { + return IrInstSrcIdTestComptime; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceGen *) { - return IrInstructionIdSliceGen; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcPtrCast *) { + return IrInstSrcIdPtrCast; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberCount *) { - return IrInstructionIdMemberCount; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcBitCast *) { + return IrInstSrcIdBitCast; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberType *) { - return IrInstructionIdMemberType; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToPtr *) { + return IrInstSrcIdIntToPtr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionMemberName *) { - return IrInstructionIdMemberName; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcPtrToInt *) { + return IrInstSrcIdPtrToInt; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionBreakpoint *) { - return IrInstructionIdBreakpoint; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToEnum *) { + return IrInstSrcIdIntToEnum; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionReturnAddress *) { - return IrInstructionIdReturnAddress; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcEnumToInt *) { + return IrInstSrcIdEnumToInt; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameAddress *) { - return IrInstructionIdFrameAddress; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToErr *) { + return IrInstSrcIdIntToErr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameHandle *) { - return IrInstructionIdFrameHandle; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrToInt *) { + return IrInstSrcIdErrToInt; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameType *) { - return IrInstructionIdFrameType; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCheckSwitchProngs *) { + return IrInstSrcIdCheckSwitchProngs; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameSizeSrc *) { - return IrInstructionIdFrameSizeSrc; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCheckStatementIsVoid *) { + return IrInstSrcIdCheckStatementIsVoid; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameSizeGen *) { - return IrInstructionIdFrameSizeGen; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcTypeName *) { + return IrInstSrcIdTypeName; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignOf *) { - return IrInstructionIdAlignOf; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcDeclRef *) { + return IrInstSrcIdDeclRef; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionOverflowOp *) { - return IrInstructionIdOverflowOp; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcPanic *) { + return IrInstSrcIdPanic; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionTestErrSrc *) { - return IrInstructionIdTestErrSrc; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcTagName *) { + return IrInstSrcIdTagName; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionTestErrGen *) { - return IrInstructionIdTestErrGen; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcTagType *) { + return IrInstSrcIdTagType; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionMulAdd *) { - return IrInstructionIdMulAdd; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFieldParentPtr *) { + return IrInstSrcIdFieldParentPtr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapErrCode *) { - return IrInstructionIdUnwrapErrCode; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcByteOffsetOf *) { + return IrInstSrcIdByteOffsetOf; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapErrPayload *) { - return IrInstructionIdUnwrapErrPayload; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcBitOffsetOf *) { + return IrInstSrcIdBitOffsetOf; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionOptionalWrap *) { - return IrInstructionIdOptionalWrap; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcTypeInfo *) { + return IrInstSrcIdTypeInfo; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionErrWrapPayload *) { - return IrInstructionIdErrWrapPayload; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcType *) { + return IrInstSrcIdType; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionErrWrapCode *) { - return IrInstructionIdErrWrapCode; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcHasField *) { + return IrInstSrcIdHasField; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionFnProto *) { - return IrInstructionIdFnProto; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcTypeId *) { + return IrInstSrcIdTypeId; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *) { - return IrInstructionIdTestComptime; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetEvalBranchQuota *) { + return IrInstSrcIdSetEvalBranchQuota; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastSrc *) { - return IrInstructionIdPtrCastSrc; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcPtrType *) { + return IrInstSrcIdPtrType; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastGen *) { - return IrInstructionIdPtrCastGen; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAlignCast *) { + return IrInstSrcIdAlignCast; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCastSrc *) { - return IrInstructionIdBitCastSrc; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcImplicitCast *) { + return IrInstSrcIdImplicitCast; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCastGen *) { - return IrInstructionIdBitCastGen; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcResolveResult *) { + return IrInstSrcIdResolveResult; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionWidenOrShorten *) { - return IrInstructionIdWidenOrShorten; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcResetResult *) { + return IrInstSrcIdResetResult; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrToInt *) { - return IrInstructionIdPtrToInt; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcOpaqueType *) { + return IrInstSrcIdOpaqueType; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToPtr *) { - return IrInstructionIdIntToPtr; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetAlignStack *) { + return IrInstSrcIdSetAlignStack; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToEnum *) { - return IrInstructionIdIntToEnum; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcArgType *) { + return IrInstSrcIdArgType; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumToInt *) { - return IrInstructionIdEnumToInt; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcExport *) { + return IrInstSrcIdExport; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToErr *) { - return IrInstructionIdIntToErr; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrorReturnTrace *) { + return IrInstSrcIdErrorReturnTrace; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionErrToInt *) { - return IrInstructionIdErrToInt; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrorUnion *) { + return IrInstSrcIdErrorUnion; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckSwitchProngs *) { - return IrInstructionIdCheckSwitchProngs; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAtomicRmw *) { + return IrInstSrcIdAtomicRmw; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckStatementIsVoid *) { - return IrInstructionIdCheckStatementIsVoid; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAtomicLoad *) { + return IrInstSrcIdAtomicLoad; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeName *) { - return IrInstructionIdTypeName; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAtomicStore *) { + return IrInstSrcIdAtomicStore; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclRef *) { - return IrInstructionIdDeclRef; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSaveErrRetAddr *) { + return IrInstSrcIdSaveErrRetAddr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionPanic *) { - return IrInstructionIdPanic; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAddImplicitReturnType *) { + return IrInstSrcIdAddImplicitReturnType; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionTagName *) { - return IrInstructionIdTagName; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrSetCast *) { + return IrInstSrcIdErrSetCast; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionTagType *) { - return IrInstructionIdTagType; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcToBytes *) { + return IrInstSrcIdToBytes; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldParentPtr *) { - return IrInstructionIdFieldParentPtr; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcFromBytes *) { + return IrInstSrcIdFromBytes; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionByteOffsetOf *) { - return IrInstructionIdByteOffsetOf; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcCheckRuntimeScope *) { + return IrInstSrcIdCheckRuntimeScope; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionBitOffsetOf *) { - return IrInstructionIdBitOffsetOf; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcHasDecl *) { + return IrInstSrcIdHasDecl; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeInfo *) { - return IrInstructionIdTypeInfo; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcUndeclaredIdent *) { + return IrInstSrcIdUndeclaredIdent; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionType *) { - return IrInstructionIdType; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAlloca *) { + return IrInstSrcIdAlloca; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionHasField *) { - return IrInstructionIdHasField; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcEndExpr *) { + return IrInstSrcIdEndExpr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeId *) { - return IrInstructionIdTypeId; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnionInitNamedField *) { + return IrInstSrcIdUnionInitNamedField; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSetEvalBranchQuota *) { - return IrInstructionIdSetEvalBranchQuota; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSuspendBegin *) { + return IrInstSrcIdSuspendBegin; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrType *) { - return IrInstructionIdPtrType; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSuspendFinish *) { + return IrInstSrcIdSuspendFinish; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignCast *) { - return IrInstructionIdAlignCast; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcAwait *) { + return IrInstSrcIdAwait; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionImplicitCast *) { - return IrInstructionIdImplicitCast; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcResume *) { + return IrInstSrcIdResume; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionResolveResult *) { - return IrInstructionIdResolveResult; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSpillBegin *) { + return IrInstSrcIdSpillBegin; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionResetResult *) { - return IrInstructionIdResetResult; +static constexpr IrInstSrcId ir_inst_id(IrInstSrcSpillEnd *) { + return IrInstSrcIdSpillEnd; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrOfArrayToSlice *) { - return IrInstructionIdPtrOfArrayToSlice; + +static constexpr IrInstGenId ir_inst_id(IrInstGenDeclVar *) { + return IrInstGenIdDeclVar; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenBr *) { + return IrInstGenIdBr; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenCondBr *) { + return IrInstGenIdCondBr; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenSwitchBr *) { + return IrInstGenIdSwitchBr; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenPhi *) { + return IrInstGenIdPhi; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenBinaryNot *) { + return IrInstGenIdBinaryNot; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenNegation *) { + return IrInstGenIdNegation; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenNegationWrapping *) { + return IrInstGenIdNegationWrapping; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenBinOp *) { + return IrInstGenIdBinOp; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenLoadPtr *) { + return IrInstGenIdLoadPtr; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenStorePtr *) { + return IrInstGenIdStorePtr; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenVectorStoreElem *) { + return IrInstGenIdVectorStoreElem; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenStructFieldPtr *) { + return IrInstGenIdStructFieldPtr; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenUnionFieldPtr *) { + return IrInstGenIdUnionFieldPtr; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenElemPtr *) { + return IrInstGenIdElemPtr; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenVarPtr *) { + return IrInstGenIdVarPtr; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenReturnPtr *) { + return IrInstGenIdReturnPtr; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenCall *) { + return IrInstGenIdCall; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenReturn *) { + return IrInstGenIdReturn; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenCast *) { + return IrInstGenIdCast; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenResizeSlice *) { + return IrInstGenIdResizeSlice; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenUnreachable *) { + return IrInstGenIdUnreachable; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenAsm *) { + return IrInstGenIdAsm; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenTestNonNull *) { + return IrInstGenIdTestNonNull; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenOptionalUnwrapPtr *) { + return IrInstGenIdOptionalUnwrapPtr; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenOptionalWrap *) { + return IrInstGenIdOptionalWrap; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenUnionTag *) { + return IrInstGenIdUnionTag; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenClz *) { + return IrInstGenIdClz; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenCtz *) { + return IrInstGenIdCtz; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenPopCount *) { + return IrInstGenIdPopCount; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenBswap *) { + return IrInstGenIdBswap; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenBitReverse *) { + return IrInstGenIdBitReverse; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenRef *) { + return IrInstGenIdRef; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenErrName *) { + return IrInstGenIdErrName; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenCmpxchg *) { + return IrInstGenIdCmpxchg; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenFence *) { + return IrInstGenIdFence; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenTruncate *) { + return IrInstGenIdTruncate; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenShuffleVector *) { + return IrInstGenIdShuffleVector; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenSplat *) { + return IrInstGenIdSplat; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenBoolNot *) { + return IrInstGenIdBoolNot; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenMemset *) { + return IrInstGenIdMemset; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenMemcpy *) { + return IrInstGenIdMemcpy; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenSlice *) { + return IrInstGenIdSlice; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenBreakpoint *) { + return IrInstGenIdBreakpoint; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenReturnAddress *) { + return IrInstGenIdReturnAddress; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenFrameAddress *) { + return IrInstGenIdFrameAddress; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenFrameHandle *) { + return IrInstGenIdFrameHandle; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenFrameSize *) { + return IrInstGenIdFrameSize; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenOverflowOp *) { + return IrInstGenIdOverflowOp; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenTestErr *) { + return IrInstGenIdTestErr; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenMulAdd *) { + return IrInstGenIdMulAdd; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenFloatOp *) { + return IrInstGenIdFloatOp; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenUnwrapErrCode *) { + return IrInstGenIdUnwrapErrCode; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenUnwrapErrPayload *) { + return IrInstGenIdUnwrapErrPayload; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenErrWrapCode *) { + return IrInstGenIdErrWrapCode; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenErrWrapPayload *) { + return IrInstGenIdErrWrapPayload; +} + +static constexpr IrInstGenId ir_inst_id(IrInstGenPtrCast *) { + return IrInstGenIdPtrCast; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionOpaqueType *) { - return IrInstructionIdOpaqueType; +static constexpr IrInstGenId ir_inst_id(IrInstGenBitCast *) { + return IrInstGenIdBitCast; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSetAlignStack *) { - return IrInstructionIdSetAlignStack; +static constexpr IrInstGenId ir_inst_id(IrInstGenWidenOrShorten *) { + return IrInstGenIdWidenOrShorten; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionArgType *) { - return IrInstructionIdArgType; +static constexpr IrInstGenId ir_inst_id(IrInstGenIntToPtr *) { + return IrInstGenIdIntToPtr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionErrorReturnTrace *) { - return IrInstructionIdErrorReturnTrace; +static constexpr IrInstGenId ir_inst_id(IrInstGenPtrToInt *) { + return IrInstGenIdPtrToInt; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionErrorUnion *) { - return IrInstructionIdErrorUnion; +static constexpr IrInstGenId ir_inst_id(IrInstGenIntToEnum *) { + return IrInstGenIdIntToEnum; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicRmw *) { - return IrInstructionIdAtomicRmw; +static constexpr IrInstGenId ir_inst_id(IrInstGenIntToErr *) { + return IrInstGenIdIntToErr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicLoad *) { - return IrInstructionIdAtomicLoad; +static constexpr IrInstGenId ir_inst_id(IrInstGenErrToInt *) { + return IrInstGenIdErrToInt; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicStore *) { - return IrInstructionIdAtomicStore; +static constexpr IrInstGenId ir_inst_id(IrInstGenPanic *) { + return IrInstGenIdPanic; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSaveErrRetAddr *) { - return IrInstructionIdSaveErrRetAddr; +static constexpr IrInstGenId ir_inst_id(IrInstGenTagName *) { + return IrInstGenIdTagName; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionAddImplicitReturnType *) { - return IrInstructionIdAddImplicitReturnType; +static constexpr IrInstGenId ir_inst_id(IrInstGenFieldParentPtr *) { + return IrInstGenIdFieldParentPtr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionFloatOp *) { - return IrInstructionIdFloatOp; +static constexpr IrInstGenId ir_inst_id(IrInstGenAlignCast *) { + return IrInstGenIdAlignCast; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) { - return IrInstructionIdCheckRuntimeScope; +static constexpr IrInstGenId ir_inst_id(IrInstGenErrorReturnTrace *) { + return IrInstGenIdErrorReturnTrace; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorToArray *) { - return IrInstructionIdVectorToArray; +static constexpr IrInstGenId ir_inst_id(IrInstGenAtomicRmw *) { + return IrInstGenIdAtomicRmw; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayToVector *) { - return IrInstructionIdArrayToVector; +static constexpr IrInstGenId ir_inst_id(IrInstGenAtomicLoad *) { + return IrInstGenIdAtomicLoad; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionAssertZero *) { - return IrInstructionIdAssertZero; +static constexpr IrInstGenId ir_inst_id(IrInstGenAtomicStore *) { + return IrInstGenIdAtomicStore; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionAssertNonNull *) { - return IrInstructionIdAssertNonNull; +static constexpr IrInstGenId ir_inst_id(IrInstGenSaveErrRetAddr *) { + return IrInstGenIdSaveErrRetAddr; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionHasDecl *) { - return IrInstructionIdHasDecl; +static constexpr IrInstGenId ir_inst_id(IrInstGenVectorToArray *) { + return IrInstGenIdVectorToArray; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionUndeclaredIdent *) { - return IrInstructionIdUndeclaredIdent; +static constexpr IrInstGenId ir_inst_id(IrInstGenArrayToVector *) { + return IrInstGenIdArrayToVector; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionAllocaSrc *) { - return IrInstructionIdAllocaSrc; +static constexpr IrInstGenId ir_inst_id(IrInstGenAssertZero *) { + return IrInstGenIdAssertZero; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionAllocaGen *) { - return IrInstructionIdAllocaGen; +static constexpr IrInstGenId ir_inst_id(IrInstGenAssertNonNull *) { + return IrInstGenIdAssertNonNull; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionEndExpr *) { - return IrInstructionIdEndExpr; +static constexpr IrInstGenId ir_inst_id(IrInstGenPtrOfArrayToSlice *) { + return IrInstGenIdPtrOfArrayToSlice; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionInitNamedField *) { - return IrInstructionIdUnionInitNamedField; +static constexpr IrInstGenId ir_inst_id(IrInstGenSuspendBegin *) { + return IrInstGenIdSuspendBegin; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSuspendBegin *) { - return IrInstructionIdSuspendBegin; +static constexpr IrInstGenId ir_inst_id(IrInstGenSuspendFinish *) { + return IrInstGenIdSuspendFinish; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSuspendFinish *) { - return IrInstructionIdSuspendFinish; +static constexpr IrInstGenId ir_inst_id(IrInstGenAwait *) { + return IrInstGenIdAwait; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionAwaitSrc *) { - return IrInstructionIdAwaitSrc; +static constexpr IrInstGenId ir_inst_id(IrInstGenResume *) { + return IrInstGenIdResume; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionAwaitGen *) { - return IrInstructionIdAwaitGen; +static constexpr IrInstGenId ir_inst_id(IrInstGenSpillBegin *) { + return IrInstGenIdSpillBegin; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionResume *) { - return IrInstructionIdResume; +static constexpr IrInstGenId ir_inst_id(IrInstGenSpillEnd *) { + return IrInstGenIdSpillEnd; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSpillBegin *) { - return IrInstructionIdSpillBegin; +static constexpr IrInstGenId ir_inst_id(IrInstGenVectorExtractElem *) { + return IrInstGenIdVectorExtractElem; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSpillEnd *) { - return IrInstructionIdSpillEnd; +static constexpr IrInstGenId ir_inst_id(IrInstGenAlloca *) { + return IrInstGenIdAlloca; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorExtractElem *) { - return IrInstructionIdVectorExtractElem; +static constexpr IrInstGenId ir_inst_id(IrInstGenConst *) { + return IrInstGenIdConst; } template -static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { +static T *ir_create_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { const char *name = nullptr; #ifdef ZIG_ENABLE_MEM_PROFILE T *dummy = nullptr; - name = ir_instruction_type_str(ir_instruction_id(dummy)); + name = ir_inst_src_type_str(ir_inst_id(dummy)); #endif T *special_instruction = allocate(1, name); - special_instruction->base.id = ir_instruction_id(special_instruction); - special_instruction->base.scope = scope; - special_instruction->base.source_node = source_node; - special_instruction->base.debug_id = exec_next_debug_id(irb->exec); + special_instruction->base.id = ir_inst_id(special_instruction); + special_instruction->base.base.scope = scope; + special_instruction->base.base.source_node = source_node; + special_instruction->base.base.debug_id = exec_next_debug_id(irb->exec); + special_instruction->base.owner_bb = irb->current_basic_block; + return special_instruction; +} + +template +static T *ir_create_inst_gen(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { + const char *name = nullptr; +#ifdef ZIG_ENABLE_MEM_PROFILE + T *dummy = nullptr; + name = ir_inst_gen_type_str(ir_inst_id(dummy)); +#endif + T *special_instruction = allocate(1, name); + special_instruction->base.id = ir_inst_id(special_instruction); + special_instruction->base.base.scope = scope; + special_instruction->base.base.source_node = source_node; + special_instruction->base.base.debug_id = exec_next_debug_id_gen(irb->exec); special_instruction->base.owner_bb = irb->current_basic_block; special_instruction->base.value = allocate(1, "ZigValue"); return special_instruction; } template -static T *ir_create_instruction_noval(IrBuilder *irb, Scope *scope, AstNode *source_node) { +static T *ir_create_inst_noval(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { const char *name = nullptr; #ifdef ZIG_ENABLE_MEM_PROFILE T *dummy = nullptr; - name = ir_instruction_type_str(ir_instruction_id(dummy)); + name = ir_inst_gen_type_str(ir_inst_id(dummy)); #endif T *special_instruction = allocate(1, name); - special_instruction->base.id = ir_instruction_id(special_instruction); - special_instruction->base.scope = scope; - special_instruction->base.source_node = source_node; - special_instruction->base.debug_id = exec_next_debug_id(irb->exec); + special_instruction->base.id = ir_inst_id(special_instruction); + special_instruction->base.base.scope = scope; + special_instruction->base.base.source_node = source_node; + special_instruction->base.base.debug_id = exec_next_debug_id_gen(irb->exec); special_instruction->base.owner_bb = irb->current_basic_block; return special_instruction; } template -static T *ir_build_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { +static T *ir_build_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { T *special_instruction = ir_create_instruction(irb, scope, source_node); ir_instruction_append(irb->current_basic_block, &special_instruction->base); return special_instruction; } -static IrInstruction *ir_build_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, ZigType *dest_type, - IrInstruction *value, CastOp cast_op) -{ - IrInstructionCast *cast_instruction = ir_build_instruction(irb, scope, source_node); - cast_instruction->dest_type = dest_type; - cast_instruction->value = value; - cast_instruction->cast_op = cast_op; - - ir_ref_instruction(value, irb->current_basic_block); - - return &cast_instruction->base; +template +static T *ir_build_inst_gen(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { + T *special_instruction = ir_create_inst_gen(irb, scope, source_node); + ir_inst_gen_append(irb->current_basic_block, &special_instruction->base); + return special_instruction; } -static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *condition, - IrBasicBlock *then_block, IrBasicBlock *else_block, IrInstruction *is_comptime) +template +static T *ir_build_inst_noreturn(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { + T *special_instruction = ir_create_inst_noval(irb, scope, source_node); + special_instruction->base.value = irb->codegen->intern.for_unreachable(); + ir_inst_gen_append(irb->current_basic_block, &special_instruction->base); + return special_instruction; +} + +template +static T *ir_build_inst_void(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { + T *special_instruction = ir_create_inst_noval(irb, scope, source_node); + special_instruction->base.value = irb->codegen->intern.for_void(); + ir_inst_gen_append(irb->current_basic_block, &special_instruction->base); + return special_instruction; +} + +IrInstGen *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn, + ZigType *var_type, const char *name_hint) { - IrInstructionCondBr *cond_br_instruction = ir_build_instruction(irb, scope, source_node); - cond_br_instruction->base.value->type = irb->codegen->builtin_types.entry_unreachable; - cond_br_instruction->base.value->special = ConstValSpecialStatic; - cond_br_instruction->condition = condition; - cond_br_instruction->then_block = then_block; - cond_br_instruction->else_block = else_block; - cond_br_instruction->is_comptime = is_comptime; + IrInstGenAlloca *alloca_gen = allocate(1); + alloca_gen->base.id = IrInstGenIdAlloca; + alloca_gen->base.base.source_node = source_node; + alloca_gen->base.base.scope = scope; + alloca_gen->base.value = allocate(1, "ZigValue"); + alloca_gen->base.value->type = get_pointer_to_type(g, var_type, false); + alloca_gen->base.base.ref_count = 1; + alloca_gen->name_hint = name_hint; + fn->alloca_gen_list.append(alloca_gen); + return &alloca_gen->base; +} + +static IrInstGen *ir_build_cast(IrAnalyze *ira, IrInst *source_instr,ZigType *dest_type, + IrInstGen *value, CastOp cast_op) +{ + IrInstGenCast *inst = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); + inst->base.value->type = dest_type; + inst->value = value; + inst->cast_op = cast_op; + + ir_ref_inst_gen(value, ira->new_irb.current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_cond_br(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *condition, + IrBasicBlockSrc *then_block, IrBasicBlockSrc *else_block, IrInstSrc *is_comptime) +{ + IrInstSrcCondBr *inst = ir_build_instruction(irb, scope, source_node); + inst->base.is_noreturn = true; + inst->condition = condition; + inst->then_block = then_block; + inst->else_block = else_block; + inst->is_comptime = is_comptime; ir_ref_instruction(condition, irb->current_basic_block); ir_ref_bb(then_block); ir_ref_bb(else_block); if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block); - return &cond_br_instruction->base; + return &inst->base; } -static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *operand) +static IrInstGen *ir_build_cond_br_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *condition, + IrBasicBlockGen *then_block, IrBasicBlockGen *else_block) { - IrInstructionReturn *return_instruction = ir_build_instruction(irb, scope, source_node); - return_instruction->base.value->type = irb->codegen->builtin_types.entry_unreachable; - return_instruction->base.value->special = ConstValSpecialStatic; - return_instruction->operand = operand; + IrInstGenCondBr *inst = ir_build_inst_noreturn(&ira->new_irb, source_instr->scope, source_instr->source_node); + inst->condition = condition; + inst->then_block = then_block; + inst->else_block = else_block; + + ir_ref_inst_gen(condition, ira->new_irb.current_basic_block); + ir_ref_bb_gen(then_block); + ir_ref_bb_gen(else_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_return_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *operand) { + IrInstSrcReturn *inst = ir_build_instruction(irb, scope, source_node); + inst->base.is_noreturn = true; + inst->operand = operand; if (operand != nullptr) ir_ref_instruction(operand, irb->current_basic_block); - return &return_instruction->base; + return &inst->base; } -static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) { - IrInstructionConst *const_instruction = ir_create_instruction_noval(irb, scope, source_node); +static IrInstGen *ir_build_return_gen(IrAnalyze *ira, IrInst *source_inst, IrInstGen *operand) { + IrInstGenReturn *inst = ir_build_inst_noreturn(&ira->new_irb, + source_inst->scope, source_inst->source_node); + inst->operand = operand; + + if (operand != nullptr) ir_ref_inst_gen(operand, ira->new_irb.current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_const_void(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); ir_instruction_append(irb->current_basic_block, &const_instruction->base); - const_instruction->base.value = irb->codegen->intern.for_void(); + const_instruction->value = irb->codegen->intern.for_void(); return &const_instruction->base; } -static IrInstruction *ir_build_const_undefined(IrBuilder *irb, Scope *scope, AstNode *source_node) { - IrInstructionConst *const_instruction = ir_create_instruction_noval(irb, scope, source_node); +static IrInstSrc *ir_build_const_undefined(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); ir_instruction_append(irb->current_basic_block, &const_instruction->base); - const_instruction->base.value = irb->codegen->intern.for_undefined(); + const_instruction->value = irb->codegen->intern.for_undefined(); return &const_instruction->base; } -static IrInstruction *ir_build_const_uint(IrBuilder *irb, Scope *scope, AstNode *source_node, uint64_t value) { - IrInstructionConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->base.value->type = irb->codegen->builtin_types.entry_num_lit_int; - const_instruction->base.value->special = ConstValSpecialStatic; - bigint_init_unsigned(&const_instruction->base.value->data.x_bigint, value); +static IrInstSrc *ir_build_const_uint(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, uint64_t value) { + IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); + const_instruction->value = create_const_vals(1); + const_instruction->value->type = irb->codegen->builtin_types.entry_num_lit_int; + const_instruction->value->special = ConstValSpecialStatic; + bigint_init_unsigned(&const_instruction->value->data.x_bigint, value); return &const_instruction->base; } -static IrInstruction *ir_build_const_bigint(IrBuilder *irb, Scope *scope, AstNode *source_node, BigInt *bigint) { - IrInstructionConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->base.value->type = irb->codegen->builtin_types.entry_num_lit_int; - const_instruction->base.value->special = ConstValSpecialStatic; - bigint_init_bigint(&const_instruction->base.value->data.x_bigint, bigint); +static IrInstSrc *ir_build_const_bigint(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, BigInt *bigint) { + IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); + const_instruction->value = create_const_vals(1); + const_instruction->value->type = irb->codegen->builtin_types.entry_num_lit_int; + const_instruction->value->special = ConstValSpecialStatic; + bigint_init_bigint(&const_instruction->value->data.x_bigint, bigint); return &const_instruction->base; } -static IrInstruction *ir_build_const_bigfloat(IrBuilder *irb, Scope *scope, AstNode *source_node, BigFloat *bigfloat) { - IrInstructionConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->base.value->type = irb->codegen->builtin_types.entry_num_lit_float; - const_instruction->base.value->special = ConstValSpecialStatic; - bigfloat_init_bigfloat(&const_instruction->base.value->data.x_bigfloat, bigfloat); +static IrInstSrc *ir_build_const_bigfloat(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, BigFloat *bigfloat) { + IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); + const_instruction->value = create_const_vals(1); + const_instruction->value->type = irb->codegen->builtin_types.entry_num_lit_float; + const_instruction->value->special = ConstValSpecialStatic; + bigfloat_init_bigfloat(&const_instruction->value->data.x_bigfloat, bigfloat); return &const_instruction->base; } -static IrInstruction *ir_build_const_null(IrBuilder *irb, Scope *scope, AstNode *source_node) { - IrInstructionConst *const_instruction = ir_create_instruction_noval(irb, scope, source_node); +static IrInstSrc *ir_build_const_null(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); ir_instruction_append(irb->current_basic_block, &const_instruction->base); - const_instruction->base.value = irb->codegen->intern.for_null(); + const_instruction->value = irb->codegen->intern.for_null(); return &const_instruction->base; } -static IrInstruction *ir_build_const_usize(IrBuilder *irb, Scope *scope, AstNode *source_node, uint64_t value) { - IrInstructionConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->base.value->type = irb->codegen->builtin_types.entry_usize; - const_instruction->base.value->special = ConstValSpecialStatic; - bigint_init_unsigned(&const_instruction->base.value->data.x_bigint, value); +static IrInstSrc *ir_build_const_usize(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, uint64_t value) { + IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); + const_instruction->value = create_const_vals(1); + const_instruction->value->type = irb->codegen->builtin_types.entry_usize; + const_instruction->value->special = ConstValSpecialStatic; + bigint_init_unsigned(&const_instruction->value->data.x_bigint, value); return &const_instruction->base; } -static IrInstruction *ir_create_const_type(IrBuilder *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_create_const_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigType *type_entry) { - IrInstructionConst *const_instruction = ir_create_instruction(irb, scope, source_node); - const_instruction->base.value->type = irb->codegen->builtin_types.entry_type; - const_instruction->base.value->special = ConstValSpecialStatic; - const_instruction->base.value->data.x_type = type_entry; + IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); + const_instruction->value = create_const_vals(1); + const_instruction->value->type = irb->codegen->builtin_types.entry_type; + const_instruction->value->special = ConstValSpecialStatic; + const_instruction->value->data.x_type = type_entry; return &const_instruction->base; } -static IrInstruction *ir_build_const_type(IrBuilder *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_const_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigType *type_entry) { - IrInstruction *instruction = ir_create_const_type(irb, scope, source_node, type_entry); + IrInstSrc *instruction = ir_create_const_type(irb, scope, source_node, type_entry); ir_instruction_append(irb->current_basic_block, instruction); return instruction; } -static IrInstruction *ir_create_const_fn(IrBuilder *irb, Scope *scope, AstNode *source_node, ZigFn *fn_entry) { - IrInstructionConst *const_instruction = ir_create_instruction(irb, scope, source_node); - const_instruction->base.value->type = fn_entry->type_entry; - const_instruction->base.value->special = ConstValSpecialStatic; - const_instruction->base.value->data.x_ptr.data.fn.fn_entry = fn_entry; - const_instruction->base.value->data.x_ptr.mut = ConstPtrMutComptimeConst; - const_instruction->base.value->data.x_ptr.special = ConstPtrSpecialFunction; +static IrInstSrc *ir_build_const_import(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigType *import) { + IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); + const_instruction->value = create_const_vals(1); + const_instruction->value->type = irb->codegen->builtin_types.entry_type; + const_instruction->value->special = ConstValSpecialStatic; + const_instruction->value->data.x_type = import; return &const_instruction->base; } -static IrInstruction *ir_build_const_import(IrBuilder *irb, Scope *scope, AstNode *source_node, ZigType *import) { - IrInstructionConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->base.value->type = irb->codegen->builtin_types.entry_type; - const_instruction->base.value->special = ConstValSpecialStatic; - const_instruction->base.value->data.x_type = import; +static IrInstSrc *ir_build_const_bool(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, bool value) { + IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); + const_instruction->value = create_const_vals(1); + const_instruction->value->type = irb->codegen->builtin_types.entry_bool; + const_instruction->value->special = ConstValSpecialStatic; + const_instruction->value->data.x_bool = value; return &const_instruction->base; } -static IrInstruction *ir_build_const_bool(IrBuilder *irb, Scope *scope, AstNode *source_node, bool value) { - IrInstructionConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->base.value->type = irb->codegen->builtin_types.entry_bool; - const_instruction->base.value->special = ConstValSpecialStatic; - const_instruction->base.value->data.x_bool = value; +static IrInstSrc *ir_build_const_enum_literal(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *name) { + IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, source_node); + const_instruction->value = create_const_vals(1); + const_instruction->value->type = irb->codegen->builtin_types.entry_enum_literal; + const_instruction->value->special = ConstValSpecialStatic; + const_instruction->value->data.x_enum_literal = name; return &const_instruction->base; } -static IrInstruction *ir_build_const_enum_literal(IrBuilder *irb, Scope *scope, AstNode *source_node, Buf *name) { - IrInstructionConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->base.value->type = irb->codegen->builtin_types.entry_enum_literal; - const_instruction->base.value->special = ConstValSpecialStatic; - const_instruction->base.value->data.x_enum_literal = name; - return &const_instruction->base; -} - -static IrInstruction *ir_build_const_bound_fn(IrBuilder *irb, Scope *scope, AstNode *source_node, - ZigFn *fn_entry, IrInstruction *first_arg) -{ - IrInstructionConst *const_instruction = ir_build_instruction(irb, scope, source_node); - const_instruction->base.value->type = get_bound_fn_type(irb->codegen, fn_entry); - const_instruction->base.value->special = ConstValSpecialStatic; - const_instruction->base.value->data.x_bound_fn.fn = fn_entry; - const_instruction->base.value->data.x_bound_fn.first_arg = first_arg; - return &const_instruction->base; -} - -static IrInstruction *ir_create_const_str_lit(IrBuilder *irb, Scope *scope, AstNode *source_node, Buf *str) { - IrInstructionConst *const_instruction = ir_create_instruction(irb, scope, source_node); - init_const_str_lit(irb->codegen, const_instruction->base.value, str); +static IrInstSrc *ir_create_const_str_lit(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *str) { + IrInstSrcConst *const_instruction = ir_create_instruction(irb, scope, source_node); + const_instruction->value = create_const_vals(1); + init_const_str_lit(irb->codegen, const_instruction->value, str); return &const_instruction->base; } -static IrInstruction *ir_build_const_str_lit(IrBuilder *irb, Scope *scope, AstNode *source_node, Buf *str) { - IrInstruction *instruction = ir_create_const_str_lit(irb, scope, source_node, str); +static IrInstSrc *ir_build_const_str_lit(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *str) { + IrInstSrc *instruction = ir_create_const_str_lit(irb, scope, source_node, str); ir_instruction_append(irb->current_basic_block, instruction); return instruction; } -static IrInstruction *ir_build_bin_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrBinOp op_id, - IrInstruction *op1, IrInstruction *op2, bool safety_check_on) +static IrInstSrc *ir_build_bin_op(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrBinOp op_id, + IrInstSrc *op1, IrInstSrc *op2, bool safety_check_on) { - IrInstructionBinOp *bin_op_instruction = ir_build_instruction(irb, scope, source_node); - bin_op_instruction->op_id = op_id; - bin_op_instruction->op1 = op1; - bin_op_instruction->op2 = op2; - bin_op_instruction->safety_check_on = safety_check_on; + IrInstSrcBinOp *inst = ir_build_instruction(irb, scope, source_node); + inst->op_id = op_id; + inst->op1 = op1; + inst->op2 = op2; + inst->safety_check_on = safety_check_on; ir_ref_instruction(op1, irb->current_basic_block); ir_ref_instruction(op2, irb->current_basic_block); - return &bin_op_instruction->base; + return &inst->base; } -static IrInstruction *ir_build_bin_op_gen(IrAnalyze *ira, IrInstruction *source_instr, ZigType *res_type, - IrBinOp op_id, IrInstruction *op1, IrInstruction *op2, bool safety_check_on) +static IrInstGen *ir_build_bin_op_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *res_type, + IrBinOp op_id, IrInstGen *op1, IrInstGen *op2, bool safety_check_on) { - IrInstructionBinOp *bin_op_instruction = ir_build_instruction(&ira->new_irb, + IrInstGenBinOp *inst = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); - bin_op_instruction->base.value->type = res_type; - bin_op_instruction->op_id = op_id; - bin_op_instruction->op1 = op1; - bin_op_instruction->op2 = op2; - bin_op_instruction->safety_check_on = safety_check_on; + inst->base.value->type = res_type; + inst->op_id = op_id; + inst->op1 = op1; + inst->op2 = op2; + inst->safety_check_on = safety_check_on; - ir_ref_instruction(op1, ira->new_irb.current_basic_block); - ir_ref_instruction(op2, ira->new_irb.current_basic_block); + ir_ref_inst_gen(op1, ira->new_irb.current_basic_block); + ir_ref_inst_gen(op2, ira->new_irb.current_basic_block); - return &bin_op_instruction->base; + return &inst->base; } -static IrInstruction *ir_build_merge_err_sets(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *op1, IrInstruction *op2, Buf *type_name) +static IrInstSrc *ir_build_merge_err_sets(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *op1, IrInstSrc *op2, Buf *type_name) { - IrInstructionMergeErrSets *merge_err_sets_instruction = ir_build_instruction(irb, scope, source_node); - merge_err_sets_instruction->op1 = op1; - merge_err_sets_instruction->op2 = op2; - merge_err_sets_instruction->type_name = type_name; + IrInstSrcMergeErrSets *inst = ir_build_instruction(irb, scope, source_node); + inst->op1 = op1; + inst->op2 = op2; + inst->type_name = type_name; ir_ref_instruction(op1, irb->current_basic_block); ir_ref_instruction(op2, irb->current_basic_block); - return &merge_err_sets_instruction->base; + return &inst->base; } -static IrInstruction *ir_build_var_ptr_x(IrBuilder *irb, Scope *scope, AstNode *source_node, ZigVar *var, +static IrInstSrc *ir_build_var_ptr_x(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var, ScopeFnDef *crossed_fndef_scope) { - IrInstructionVarPtr *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcVarPtr *instruction = ir_build_instruction(irb, scope, source_node); instruction->var = var; instruction->crossed_fndef_scope = crossed_fndef_scope; @@ -1854,24 +2308,30 @@ static IrInstruction *ir_build_var_ptr_x(IrBuilder *irb, Scope *scope, AstNode * return &instruction->base; } -static IrInstruction *ir_build_var_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, ZigVar *var) { +static IrInstSrc *ir_build_var_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var) { return ir_build_var_ptr_x(irb, scope, source_node, var, nullptr); } -static IrInstruction *ir_build_return_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node, - ZigType *ty) -{ - IrInstructionReturnPtr *instruction = ir_build_instruction(&ira->new_irb, - scope, source_node); +static IrInstGen *ir_build_var_ptr_gen(IrAnalyze *ira, IrInst *source_instr, ZigVar *var) { + IrInstGenVarPtr *instruction = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); + instruction->var = var; + + ir_ref_var(var); + + return &instruction->base; +} + +static IrInstGen *ir_build_return_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *ty) { + IrInstGenReturnPtr *instruction = ir_build_inst_gen(&ira->new_irb, scope, source_node); instruction->base.value->type = ty; return &instruction->base; } -static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *array_ptr, IrInstruction *elem_index, bool safety_check_on, PtrLen ptr_len, +static IrInstSrc *ir_build_elem_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *array_ptr, IrInstSrc *elem_index, bool safety_check_on, PtrLen ptr_len, AstNode *init_array_type_source_node) { - IrInstructionElemPtr *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcElemPtr *instruction = ir_build_instruction(irb, scope, source_node); instruction->array_ptr = array_ptr; instruction->elem_index = elem_index; instruction->safety_check_on = safety_check_on; @@ -1884,10 +2344,25 @@ static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *s return &instruction->base; } -static IrInstruction *ir_build_field_ptr_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *container_ptr, IrInstruction *field_name_expr, bool initializing) +static IrInstGen *ir_build_elem_ptr_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, + IrInstGen *array_ptr, IrInstGen *elem_index, bool safety_check_on, ZigType *return_type) { - IrInstructionFieldPtr *instruction = ir_build_instruction(irb, scope, source_node); + IrInstGenElemPtr *instruction = ir_build_inst_gen(&ira->new_irb, scope, source_node); + instruction->base.value->type = return_type; + instruction->array_ptr = array_ptr; + instruction->elem_index = elem_index; + instruction->safety_check_on = safety_check_on; + + ir_ref_inst_gen(array_ptr, ira->new_irb.current_basic_block); + ir_ref_inst_gen(elem_index, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_field_ptr_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *container_ptr, IrInstSrc *field_name_expr, bool initializing) +{ + IrInstSrcFieldPtr *instruction = ir_build_instruction(irb, scope, source_node); instruction->container_ptr = container_ptr; instruction->field_name_buffer = nullptr; instruction->field_name_expr = field_name_expr; @@ -1899,10 +2374,10 @@ static IrInstruction *ir_build_field_ptr_instruction(IrBuilder *irb, Scope *scop return &instruction->base; } -static IrInstruction *ir_build_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *container_ptr, Buf *field_name, bool initializing) +static IrInstSrc *ir_build_field_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *container_ptr, Buf *field_name, bool initializing) { - IrInstructionFieldPtr *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcFieldPtr *instruction = ir_build_instruction(irb, scope, source_node); instruction->container_ptr = container_ptr; instruction->field_name_buffer = field_name; instruction->field_name_expr = nullptr; @@ -1913,10 +2388,10 @@ static IrInstruction *ir_build_field_ptr(IrBuilder *irb, Scope *scope, AstNode * return &instruction->base; } -static IrInstruction *ir_build_has_field(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *container_type, IrInstruction *field_name) +static IrInstSrc *ir_build_has_field(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *container_type, IrInstSrc *field_name) { - IrInstructionHasField *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcHasField *instruction = ir_build_instruction(irb, scope, source_node); instruction->container_type = container_type; instruction->field_name = field_name; @@ -1926,36 +2401,39 @@ static IrInstruction *ir_build_has_field(IrBuilder *irb, Scope *scope, AstNode * return &instruction->base; } -static IrInstruction *ir_build_struct_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *struct_ptr, TypeStructField *field) +static IrInstGen *ir_build_struct_field_ptr(IrAnalyze *ira, IrInst *source_instr, + IrInstGen *struct_ptr, TypeStructField *field, ZigType *ptr_type) { - IrInstructionStructFieldPtr *instruction = ir_build_instruction(irb, scope, source_node); - instruction->struct_ptr = struct_ptr; - instruction->field = field; + IrInstGenStructFieldPtr *inst = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); + inst->base.value->type = ptr_type; + inst->struct_ptr = struct_ptr; + inst->field = field; - ir_ref_instruction(struct_ptr, irb->current_basic_block); + ir_ref_inst_gen(struct_ptr, ira->new_irb.current_basic_block); - return &instruction->base; + return &inst->base; } -static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *union_ptr, TypeUnionField *field, bool safety_check_on, bool initializing) +static IrInstGen *ir_build_union_field_ptr(IrAnalyze *ira, IrInst *source_instr, + IrInstGen *union_ptr, TypeUnionField *field, bool safety_check_on, bool initializing, ZigType *ptr_type) { - IrInstructionUnionFieldPtr *instruction = ir_build_instruction(irb, scope, source_node); - instruction->initializing = initializing; - instruction->safety_check_on = safety_check_on; - instruction->union_ptr = union_ptr; - instruction->field = field; + IrInstGenUnionFieldPtr *inst = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + inst->base.value->type = ptr_type; + inst->initializing = initializing; + inst->safety_check_on = safety_check_on; + inst->union_ptr = union_ptr; + inst->field = field; - ir_ref_instruction(union_ptr, irb->current_basic_block); + ir_ref_inst_gen(union_ptr, ira->new_irb.current_basic_block); - return &instruction->base; + return &inst->base; } -static IrInstruction *ir_build_call_extra(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *options, IrInstruction *fn_ref, IrInstruction *args, ResultLoc *result_loc) +static IrInstSrc *ir_build_call_extra(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *options, IrInstSrc *fn_ref, IrInstSrc *args, ResultLoc *result_loc) { - IrInstructionCallExtra *call_instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcCallExtra *call_instruction = ir_build_instruction(irb, scope, source_node); call_instruction->options = options; call_instruction->fn_ref = fn_ref; call_instruction->args = args; @@ -1968,11 +2446,11 @@ static IrInstruction *ir_build_call_extra(IrBuilder *irb, Scope *scope, AstNode return &call_instruction->base; } -static IrInstruction *ir_build_call_src_args(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *options, IrInstruction *fn_ref, IrInstruction **args_ptr, size_t args_len, +static IrInstSrc *ir_build_call_args(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *options, IrInstSrc *fn_ref, IrInstSrc **args_ptr, size_t args_len, ResultLoc *result_loc) { - IrInstructionCallSrcArgs *call_instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcCallArgs *call_instruction = ir_build_instruction(irb, scope, source_node); call_instruction->options = options; call_instruction->fn_ref = fn_ref; call_instruction->args_ptr = args_ptr; @@ -1987,12 +2465,12 @@ static IrInstruction *ir_build_call_src_args(IrBuilder *irb, Scope *scope, AstNo return &call_instruction->base; } -static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *source_node, - ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args, - IrInstruction *ret_ptr, CallModifier modifier, bool is_async_call_builtin, - IrInstruction *new_stack, ResultLoc *result_loc) +static IrInstSrc *ir_build_call_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + ZigFn *fn_entry, IrInstSrc *fn_ref, size_t arg_count, IrInstSrc **args, + IrInstSrc *ret_ptr, CallModifier modifier, bool is_async_call_builtin, + IrInstSrc *new_stack, ResultLoc *result_loc) { - IrInstructionCallSrc *call_instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcCall *call_instruction = ir_build_instruction(irb, scope, source_node); call_instruction->fn_entry = fn_entry; call_instruction->fn_ref = fn_ref; call_instruction->args = args; @@ -2012,12 +2490,12 @@ static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *s return &call_instruction->base; } -static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *source_instruction, - ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args, - CallModifier modifier, IrInstruction *new_stack, bool is_async_call_builtin, - IrInstruction *result_loc, ZigType *return_type) +static IrInstGenCall *ir_build_call_gen(IrAnalyze *ira, IrInst *source_instruction, + ZigFn *fn_entry, IrInstGen *fn_ref, size_t arg_count, IrInstGen **args, + CallModifier modifier, IrInstGen *new_stack, bool is_async_call_builtin, + IrInstGen *result_loc, ZigType *return_type) { - IrInstructionCallGen *call_instruction = ir_build_instruction(&ira->new_irb, + IrInstGenCall *call_instruction = ir_build_inst_gen(&ira->new_irb, source_instruction->scope, source_instruction->source_node); call_instruction->base.value->type = return_type; call_instruction->fn_entry = fn_entry; @@ -2029,23 +2507,23 @@ static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *so call_instruction->new_stack = new_stack; call_instruction->result_loc = result_loc; - if (fn_ref != nullptr) ir_ref_instruction(fn_ref, ira->new_irb.current_basic_block); + if (fn_ref != nullptr) ir_ref_inst_gen(fn_ref, ira->new_irb.current_basic_block); for (size_t i = 0; i < arg_count; i += 1) - ir_ref_instruction(args[i], ira->new_irb.current_basic_block); - if (new_stack != nullptr) ir_ref_instruction(new_stack, ira->new_irb.current_basic_block); - if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block); + ir_ref_inst_gen(args[i], ira->new_irb.current_basic_block); + if (new_stack != nullptr) ir_ref_inst_gen(new_stack, ira->new_irb.current_basic_block); + if (result_loc != nullptr) ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block); return call_instruction; } -static IrInstruction *ir_build_phi(IrBuilder *irb, Scope *scope, AstNode *source_node, - size_t incoming_count, IrBasicBlock **incoming_blocks, IrInstruction **incoming_values, +static IrInstSrc *ir_build_phi(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + size_t incoming_count, IrBasicBlockSrc **incoming_blocks, IrInstSrc **incoming_values, ResultLocPeerParent *peer_parent) { assert(incoming_count != 0); assert(incoming_count != SIZE_MAX); - IrInstructionPhi *phi_instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcPhi *phi_instruction = ir_build_instruction(irb, scope, source_node); phi_instruction->incoming_count = incoming_count; phi_instruction->incoming_blocks = incoming_blocks; phi_instruction->incoming_values = incoming_values; @@ -2059,56 +2537,77 @@ static IrInstruction *ir_build_phi(IrBuilder *irb, Scope *scope, AstNode *source return &phi_instruction->base; } -static IrInstruction *ir_create_br(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrBasicBlock *dest_block, IrInstruction *is_comptime) +static IrInstGen *ir_build_phi_gen(IrAnalyze *ira, IrInst *source_instr, size_t incoming_count, + IrBasicBlockGen **incoming_blocks, IrInstGen **incoming_values, ZigType *result_type) { - IrInstructionBr *br_instruction = ir_create_instruction(irb, scope, source_node); - br_instruction->base.value->type = irb->codegen->builtin_types.entry_unreachable; - br_instruction->base.value->special = ConstValSpecialStatic; - br_instruction->dest_block = dest_block; - br_instruction->is_comptime = is_comptime; + assert(incoming_count != 0); + assert(incoming_count != SIZE_MAX); + + IrInstGenPhi *phi_instruction = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + phi_instruction->base.value->type = result_type; + phi_instruction->incoming_count = incoming_count; + phi_instruction->incoming_blocks = incoming_blocks; + phi_instruction->incoming_values = incoming_values; + + for (size_t i = 0; i < incoming_count; i += 1) { + ir_ref_bb_gen(incoming_blocks[i]); + ir_ref_inst_gen(incoming_values[i], ira->new_irb.current_basic_block); + } + + return &phi_instruction->base; +} + +static IrInstSrc *ir_build_br(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrBasicBlockSrc *dest_block, IrInstSrc *is_comptime) +{ + IrInstSrcBr *inst = ir_build_instruction(irb, scope, source_node); + inst->base.is_noreturn = true; + inst->dest_block = dest_block; + inst->is_comptime = is_comptime; ir_ref_bb(dest_block); if (is_comptime) ir_ref_instruction(is_comptime, irb->current_basic_block); - return &br_instruction->base; + return &inst->base; } -static IrInstruction *ir_build_br(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrBasicBlock *dest_block, IrInstruction *is_comptime) -{ - IrInstruction *instruction = ir_create_br(irb, scope, source_node, dest_block, is_comptime); - ir_instruction_append(irb->current_basic_block, instruction); - return instruction; +static IrInstGen *ir_build_br_gen(IrAnalyze *ira, IrInst *source_instr, IrBasicBlockGen *dest_block) { + IrInstGenBr *inst = ir_build_inst_noreturn(&ira->new_irb, source_instr->scope, source_instr->source_node); + inst->dest_block = dest_block; + + ir_ref_bb_gen(dest_block); + + return &inst->base; } -static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *child_type, bool is_const, bool is_volatile, PtrLen ptr_len, - IrInstruction *sentinel, IrInstruction *align_value, +static IrInstSrc *ir_build_ptr_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *child_type, bool is_const, bool is_volatile, PtrLen ptr_len, + IrInstSrc *sentinel, IrInstSrc *align_value, uint32_t bit_offset_start, uint32_t host_int_bytes, bool is_allow_zero) { - IrInstructionPtrType *ptr_type_of_instruction = ir_build_instruction(irb, scope, source_node); - ptr_type_of_instruction->sentinel = sentinel; - ptr_type_of_instruction->align_value = align_value; - ptr_type_of_instruction->child_type = child_type; - ptr_type_of_instruction->is_const = is_const; - ptr_type_of_instruction->is_volatile = is_volatile; - ptr_type_of_instruction->ptr_len = ptr_len; - ptr_type_of_instruction->bit_offset_start = bit_offset_start; - ptr_type_of_instruction->host_int_bytes = host_int_bytes; - ptr_type_of_instruction->is_allow_zero = is_allow_zero; + IrInstSrcPtrType *inst = ir_build_instruction(irb, scope, source_node); + inst->sentinel = sentinel; + inst->align_value = align_value; + inst->child_type = child_type; + inst->is_const = is_const; + inst->is_volatile = is_volatile; + inst->ptr_len = ptr_len; + inst->bit_offset_start = bit_offset_start; + inst->host_int_bytes = host_int_bytes; + inst->is_allow_zero = is_allow_zero; if (sentinel) ir_ref_instruction(sentinel, irb->current_basic_block); if (align_value) ir_ref_instruction(align_value, irb->current_basic_block); ir_ref_instruction(child_type, irb->current_basic_block); - return &ptr_type_of_instruction->base; + return &inst->base; } -static IrInstruction *ir_build_un_op_lval(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, - IrInstruction *value, LVal lval, ResultLoc *result_loc) +static IrInstSrc *ir_build_un_op_lval(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, + IrInstSrc *value, LVal lval, ResultLoc *result_loc) { - IrInstructionUnOp *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcUnOp *instruction = ir_build_instruction(irb, scope, source_node); instruction->op_id = op_id; instruction->value = value; instruction->lval = lval; @@ -2119,18 +2618,55 @@ static IrInstruction *ir_build_un_op_lval(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, - IrInstruction *value) +static IrInstSrc *ir_build_un_op(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, + IrInstSrc *value) { return ir_build_un_op_lval(irb, scope, source_node, op_id, value, LValNone, nullptr); } -static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node, - size_t item_count, IrInstruction **elem_result_loc_list, IrInstruction *result_loc, +static IrInstGen *ir_build_negation(IrAnalyze *ira, IrInst *source_instr, IrInstGen *operand, ZigType *expr_type) { + IrInstGenNegation *instruction = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->base.value->type = expr_type; + instruction->operand = operand; + + ir_ref_inst_gen(operand, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstGen *ir_build_negation_wrapping(IrAnalyze *ira, IrInst *source_instr, IrInstGen *operand, + ZigType *expr_type) +{ + IrInstGenNegationWrapping *instruction = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->base.value->type = expr_type; + instruction->operand = operand; + + ir_ref_inst_gen(operand, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstGen *ir_build_binary_not(IrAnalyze *ira, IrInst *source_instr, IrInstGen *operand, + ZigType *expr_type) +{ + IrInstGenBinaryNot *instruction = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->base.value->type = expr_type; + instruction->operand = operand; + + ir_ref_inst_gen(operand, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_container_init_list(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + size_t item_count, IrInstSrc **elem_result_loc_list, IrInstSrc *result_loc, AstNode *init_array_type_source_node) { - IrInstructionContainerInitList *container_init_list_instruction = - ir_build_instruction(irb, scope, source_node); + IrInstSrcContainerInitList *container_init_list_instruction = + ir_build_instruction(irb, scope, source_node); container_init_list_instruction->item_count = item_count; container_init_list_instruction->elem_result_loc_list = elem_result_loc_list; container_init_list_instruction->result_loc = result_loc; @@ -2144,11 +2680,11 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, return &container_init_list_instruction->base; } -static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scope, AstNode *source_node, - size_t field_count, IrInstructionContainerInitFieldsField *fields, IrInstruction *result_loc) +static IrInstSrc *ir_build_container_init_fields(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + size_t field_count, IrInstSrcContainerInitFieldsField *fields, IrInstSrc *result_loc) { - IrInstructionContainerInitFields *container_init_fields_instruction = - ir_build_instruction(irb, scope, source_node); + IrInstSrcContainerInitFields *container_init_fields_instruction = + ir_build_instruction(irb, scope, source_node); container_init_fields_instruction->field_count = field_count; container_init_fields_instruction->fields = fields; container_init_fields_instruction->result_loc = result_loc; @@ -2161,20 +2697,21 @@ static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scop return &container_init_fields_instruction->base; } -static IrInstruction *ir_build_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node) { - IrInstructionUnreachable *unreachable_instruction = - ir_build_instruction(irb, scope, source_node); - unreachable_instruction->base.value->special = ConstValSpecialStatic; - unreachable_instruction->base.value->type = irb->codegen->builtin_types.entry_unreachable; - return &unreachable_instruction->base; +static IrInstSrc *ir_build_unreachable(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcUnreachable *inst = ir_build_instruction(irb, scope, source_node); + inst->base.is_noreturn = true; + return &inst->base; } -static IrInstructionStorePtr *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *ptr, IrInstruction *value) +static IrInstGen *ir_build_unreachable_gen(IrAnalyze *ira, IrInst *source_instr) { + IrInstGenUnreachable *inst = ir_build_inst_noreturn(&ira->new_irb, source_instr->scope, source_instr->source_node); + return &inst->base; +} + +static IrInstSrcStorePtr *ir_build_store_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *ptr, IrInstSrc *value) { - IrInstructionStorePtr *instruction = ir_build_instruction(irb, scope, source_node); - instruction->base.value->special = ConstValSpecialStatic; - instruction->base.value->type = irb->codegen->builtin_types.entry_void; + IrInstSrcStorePtr *instruction = ir_build_instruction(irb, scope, source_node); instruction->ptr = ptr; instruction->value = value; @@ -2184,76 +2721,83 @@ static IrInstructionStorePtr *ir_build_store_ptr(IrBuilder *irb, Scope *scope, A return instruction; } -static IrInstruction *ir_build_vector_store_elem(IrAnalyze *ira, IrInstruction *source_instruction, - IrInstruction *vector_ptr, IrInstruction *index, IrInstruction *value) +static IrInstGen *ir_build_store_ptr_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *ptr, IrInstGen *value) { + IrInstGenStorePtr *instruction = ir_build_inst_void(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->ptr = ptr; + instruction->value = value; + + ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block); + ir_ref_inst_gen(value, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstGen *ir_build_vector_store_elem(IrAnalyze *ira, IrInst *src_inst, + IrInstGen *vector_ptr, IrInstGen *index, IrInstGen *value) { - IrInstructionVectorStoreElem *inst = ir_build_instruction( - &ira->new_irb, source_instruction->scope, source_instruction->source_node); - inst->base.value->type = ira->codegen->builtin_types.entry_void; + IrInstGenVectorStoreElem *inst = ir_build_inst_void( + &ira->new_irb, src_inst->scope, src_inst->source_node); inst->vector_ptr = vector_ptr; inst->index = index; inst->value = value; - ir_ref_instruction(vector_ptr, ira->new_irb.current_basic_block); - ir_ref_instruction(index, ira->new_irb.current_basic_block); - ir_ref_instruction(value, ira->new_irb.current_basic_block); + ir_ref_inst_gen(vector_ptr, ira->new_irb.current_basic_block); + ir_ref_inst_gen(index, ira->new_irb.current_basic_block); + ir_ref_inst_gen(value, ira->new_irb.current_basic_block); return &inst->base; } -static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node, - ZigVar *var, IrInstruction *align_value, IrInstruction *ptr) +static IrInstSrc *ir_build_var_decl_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + ZigVar *var, IrInstSrc *align_value, IrInstSrc *ptr) { - IrInstructionDeclVarSrc *decl_var_instruction = ir_build_instruction(irb, scope, source_node); - decl_var_instruction->base.value->special = ConstValSpecialStatic; - decl_var_instruction->base.value->type = irb->codegen->builtin_types.entry_void; - decl_var_instruction->var = var; - decl_var_instruction->align_value = align_value; - decl_var_instruction->ptr = ptr; + IrInstSrcDeclVar *inst = ir_build_instruction(irb, scope, source_node); + inst->var = var; + inst->align_value = align_value; + inst->ptr = ptr; if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block); ir_ref_instruction(ptr, irb->current_basic_block); - return &decl_var_instruction->base; + return &inst->base; } -static IrInstruction *ir_build_var_decl_gen(IrAnalyze *ira, IrInstruction *source_instruction, - ZigVar *var, IrInstruction *var_ptr) +static IrInstGen *ir_build_var_decl_gen(IrAnalyze *ira, IrInst *source_instruction, + ZigVar *var, IrInstGen *var_ptr) { - IrInstructionDeclVarGen *decl_var_instruction = ir_build_instruction(&ira->new_irb, + IrInstGenDeclVar *inst = ir_build_inst_gen(&ira->new_irb, source_instruction->scope, source_instruction->source_node); - decl_var_instruction->base.value->special = ConstValSpecialStatic; - decl_var_instruction->base.value->type = ira->codegen->builtin_types.entry_void; - decl_var_instruction->var = var; - decl_var_instruction->var_ptr = var_ptr; + inst->base.value->special = ConstValSpecialStatic; + inst->base.value->type = ira->codegen->builtin_types.entry_void; + inst->var = var; + inst->var_ptr = var_ptr; - ir_ref_instruction(var_ptr, ira->new_irb.current_basic_block); + ir_ref_inst_gen(var_ptr, ira->new_irb.current_basic_block); - return &decl_var_instruction->base; + return &inst->base; } -static IrInstruction *ir_build_resize_slice(IrAnalyze *ira, IrInstruction *source_instruction, - IrInstruction *operand, ZigType *ty, IrInstruction *result_loc) +static IrInstGen *ir_build_resize_slice(IrAnalyze *ira, IrInst *source_instruction, + IrInstGen *operand, ZigType *ty, IrInstGen *result_loc) { - IrInstructionResizeSlice *instruction = ir_build_instruction(&ira->new_irb, + IrInstGenResizeSlice *instruction = ir_build_inst_gen(&ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->base.value->type = ty; instruction->operand = operand; instruction->result_loc = result_loc; - ir_ref_instruction(operand, ira->new_irb.current_basic_block); - if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block); + ir_ref_inst_gen(operand, ira->new_irb.current_basic_block); + if (result_loc != nullptr) ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *target, IrInstruction *options) +static IrInstSrc *ir_build_export(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target, IrInstSrc *options) { - IrInstructionExport *export_instruction = ir_build_instruction( + IrInstSrcExport *export_instruction = ir_build_instruction( irb, scope, source_node); - export_instruction->base.value->special = ConstValSpecialStatic; - export_instruction->base.value->type = irb->codegen->builtin_types.entry_void; export_instruction->target = target; export_instruction->options = options; @@ -2263,8 +2807,8 @@ static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *sou return &export_instruction->base; } -static IrInstruction *ir_build_load_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *ptr) { - IrInstructionLoadPtr *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_load_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *ptr) { + IrInstSrcLoadPtr *instruction = ir_build_instruction(irb, scope, source_node); instruction->ptr = ptr; ir_ref_instruction(ptr, irb->current_basic_block); @@ -2272,8 +2816,23 @@ static IrInstruction *ir_build_load_ptr(IrBuilder *irb, Scope *scope, AstNode *s return &instruction->base; } -static IrInstruction *ir_build_typeof(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { - IrInstructionTypeOf *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstGen *ir_build_load_ptr_gen(IrAnalyze *ira, IrInst *source_instruction, + IrInstGen *ptr, ZigType *ty, IrInstGen *result_loc) +{ + IrInstGenLoadPtr *instruction = ir_build_inst_gen( + &ira->new_irb, source_instruction->scope, source_instruction->source_node); + instruction->base.value->type = ty; + instruction->ptr = ptr; + instruction->result_loc = result_loc; + + ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block); + if (result_loc != nullptr) ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_typeof(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { + IrInstSrcTypeOf *instruction = ir_build_instruction(irb, scope, source_node); instruction->value = value; ir_ref_instruction(value, irb->current_basic_block); @@ -2281,8 +2840,8 @@ static IrInstruction *ir_build_typeof(IrBuilder *irb, Scope *scope, AstNode *sou return &instruction->base; } -static IrInstruction *ir_build_set_cold(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *is_cold) { - IrInstructionSetCold *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_set_cold(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *is_cold) { + IrInstSrcSetCold *instruction = ir_build_instruction(irb, scope, source_node); instruction->is_cold = is_cold; ir_ref_instruction(is_cold, irb->current_basic_block); @@ -2290,21 +2849,21 @@ static IrInstruction *ir_build_set_cold(IrBuilder *irb, Scope *scope, AstNode *s return &instruction->base; } -static IrInstruction *ir_build_set_runtime_safety(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *safety_on) +static IrInstSrc *ir_build_set_runtime_safety(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *safety_on) { - IrInstructionSetRuntimeSafety *instruction = ir_build_instruction(irb, scope, source_node); - instruction->safety_on = safety_on; + IrInstSrcSetRuntimeSafety *inst = ir_build_instruction(irb, scope, source_node); + inst->safety_on = safety_on; ir_ref_instruction(safety_on, irb->current_basic_block); - return &instruction->base; + return &inst->base; } -static IrInstruction *ir_build_set_float_mode(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *mode_value) +static IrInstSrc *ir_build_set_float_mode(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *mode_value) { - IrInstructionSetFloatMode *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSetFloatMode *instruction = ir_build_instruction(irb, scope, source_node); instruction->mode_value = mode_value; ir_ref_instruction(mode_value, irb->current_basic_block); @@ -2312,10 +2871,10 @@ static IrInstruction *ir_build_set_float_mode(IrBuilder *irb, Scope *scope, AstN return &instruction->base; } -static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *size, - IrInstruction *sentinel, IrInstruction *child_type) +static IrInstSrc *ir_build_array_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *size, + IrInstSrc *sentinel, IrInstSrc *child_type) { - IrInstructionArrayType *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcArrayType *instruction = ir_build_instruction(irb, scope, source_node); instruction->size = size; instruction->sentinel = sentinel; instruction->child_type = child_type; @@ -2327,10 +2886,10 @@ static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_anyframe_type(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *payload_type) +static IrInstSrc *ir_build_anyframe_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *payload_type) { - IrInstructionAnyFrameType *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcAnyFrameType *instruction = ir_build_instruction(irb, scope, source_node); instruction->payload_type = payload_type; if (payload_type != nullptr) ir_ref_instruction(payload_type, irb->current_basic_block); @@ -2338,11 +2897,11 @@ static IrInstruction *ir_build_anyframe_type(IrBuilder *irb, Scope *scope, AstNo return &instruction->base; } -static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *child_type, bool is_const, bool is_volatile, - IrInstruction *sentinel, IrInstruction *align_value, bool is_allow_zero) +static IrInstSrc *ir_build_slice_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *child_type, bool is_const, bool is_volatile, + IrInstSrc *sentinel, IrInstSrc *align_value, bool is_allow_zero) { - IrInstructionSliceType *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSliceType *instruction = ir_build_instruction(irb, scope, source_node); instruction->is_const = is_const; instruction->is_volatile = is_volatile; instruction->child_type = child_type; @@ -2357,11 +2916,11 @@ static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_asm_src(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *asm_template, IrInstruction **input_list, IrInstruction **output_types, +static IrInstSrc *ir_build_asm_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *asm_template, IrInstSrc **input_list, IrInstSrc **output_types, ZigVar **output_vars, size_t return_count, bool has_side_effects, bool is_global) { - IrInstructionAsmSrc *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcAsm *instruction = ir_build_instruction(irb, scope, source_node); instruction->asm_template = asm_template; instruction->input_list = input_list; instruction->output_types = output_types; @@ -2372,24 +2931,25 @@ static IrInstruction *ir_build_asm_src(IrBuilder *irb, Scope *scope, AstNode *so assert(source_node->type == NodeTypeAsmExpr); for (size_t i = 0; i < source_node->data.asm_expr.output_list.length; i += 1) { - IrInstruction *output_type = output_types[i]; + IrInstSrc *output_type = output_types[i]; if (output_type) ir_ref_instruction(output_type, irb->current_basic_block); } for (size_t i = 0; i < source_node->data.asm_expr.input_list.length; i += 1) { - IrInstruction *input_value = input_list[i]; + IrInstSrc *input_value = input_list[i]; ir_ref_instruction(input_value, irb->current_basic_block); } return &instruction->base; } -static IrInstruction *ir_build_asm_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, +static IrInstGen *ir_build_asm_gen(IrAnalyze *ira, IrInst *source_instr, Buf *asm_template, AsmToken *token_list, size_t token_list_len, - IrInstruction **input_list, IrInstruction **output_types, ZigVar **output_vars, size_t return_count, - bool has_side_effects) + IrInstGen **input_list, IrInstGen **output_types, ZigVar **output_vars, size_t return_count, + bool has_side_effects, ZigType *return_type) { - IrInstructionAsmGen *instruction = ir_build_instruction(&ira->new_irb, scope, source_node); + IrInstGenAsm *instruction = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); + instruction->base.value->type = return_type; instruction->asm_template = asm_template; instruction->token_list = token_list; instruction->token_list_len = token_list_len; @@ -2399,22 +2959,24 @@ static IrInstruction *ir_build_asm_gen(IrAnalyze *ira, Scope *scope, AstNode *so instruction->return_count = return_count; instruction->has_side_effects = has_side_effects; - assert(source_node->type == NodeTypeAsmExpr); - for (size_t i = 0; i < source_node->data.asm_expr.output_list.length; i += 1) { - IrInstruction *output_type = output_types[i]; - if (output_type) ir_ref_instruction(output_type, ira->new_irb.current_basic_block); + assert(source_instr->source_node->type == NodeTypeAsmExpr); + for (size_t i = 0; i < source_instr->source_node->data.asm_expr.output_list.length; i += 1) { + IrInstGen *output_type = output_types[i]; + if (output_type) ir_ref_inst_gen(output_type, ira->new_irb.current_basic_block); } - for (size_t i = 0; i < source_node->data.asm_expr.input_list.length; i += 1) { - IrInstruction *input_value = input_list[i]; - ir_ref_instruction(input_value, ira->new_irb.current_basic_block); + for (size_t i = 0; i < source_instr->source_node->data.asm_expr.input_list.length; i += 1) { + IrInstGen *input_value = input_list[i]; + ir_ref_inst_gen(input_value, ira->new_irb.current_basic_block); } return &instruction->base; } -static IrInstruction *ir_build_size_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value, bool bit_size) { - IrInstructionSizeOf *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_size_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_value, + bool bit_size) +{ + IrInstSrcSizeOf *instruction = ir_build_instruction(irb, scope, source_node); instruction->type_value = type_value; instruction->bit_size = bit_size; @@ -2423,8 +2985,10 @@ static IrInstruction *ir_build_size_of(IrBuilder *irb, Scope *scope, AstNode *so return &instruction->base; } -static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { - IrInstructionTestNonNull *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_test_non_null_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *value) +{ + IrInstSrcTestNonNull *instruction = ir_build_instruction(irb, scope, source_node); instruction->value = value; ir_ref_instruction(value, irb->current_basic_block); @@ -2432,10 +2996,21 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod return &instruction->base; } -static IrInstruction *ir_build_optional_unwrap_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *base_ptr, bool safety_check_on, bool initializing) +static IrInstGen *ir_build_test_non_null_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value) { + IrInstGenTestNonNull *inst = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + inst->base.value->type = ira->codegen->builtin_types.entry_bool; + inst->value = value; + + ir_ref_inst_gen(value, ira->new_irb.current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_optional_unwrap_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *base_ptr, bool safety_check_on, bool initializing) { - IrInstructionOptionalUnwrapPtr *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcOptionalUnwrapPtr *instruction = ir_build_instruction(irb, scope, source_node); instruction->base_ptr = base_ptr; instruction->safety_check_on = safety_check_on; instruction->initializing = initializing; @@ -2445,113 +3020,198 @@ static IrInstruction *ir_build_optional_unwrap_ptr(IrBuilder *irb, Scope *scope, return &instruction->base; } -static IrInstruction *ir_build_optional_wrap(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *result_ty, - IrInstruction *operand, IrInstruction *result_loc) +static IrInstGen *ir_build_optional_unwrap_ptr_gen(IrAnalyze *ira, IrInst *source_instr, + IrInstGen *base_ptr, bool safety_check_on, bool initializing, ZigType *result_type) { - IrInstructionOptionalWrap *instruction = ir_build_instruction( + IrInstGenOptionalUnwrapPtr *inst = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + inst->base.value->type = result_type; + inst->base_ptr = base_ptr; + inst->safety_check_on = safety_check_on; + inst->initializing = initializing; + + ir_ref_inst_gen(base_ptr, ira->new_irb.current_basic_block); + + return &inst->base; +} + +static IrInstGen *ir_build_optional_wrap(IrAnalyze *ira, IrInst *source_instruction, ZigType *result_ty, + IrInstGen *operand, IrInstGen *result_loc) +{ + IrInstGenOptionalWrap *instruction = ir_build_inst_gen( &ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->base.value->type = result_ty; instruction->operand = operand; instruction->result_loc = result_loc; - ir_ref_instruction(operand, ira->new_irb.current_basic_block); - if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block); + ir_ref_inst_gen(operand, ira->new_irb.current_basic_block); + if (result_loc != nullptr) ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_err_wrap_payload(IrAnalyze *ira, IrInstruction *source_instruction, - ZigType *result_type, IrInstruction *operand, IrInstruction *result_loc) +static IrInstGen *ir_build_err_wrap_payload(IrAnalyze *ira, IrInst *source_instruction, + ZigType *result_type, IrInstGen *operand, IrInstGen *result_loc) { - IrInstructionErrWrapPayload *instruction = ir_build_instruction( + IrInstGenErrWrapPayload *instruction = ir_build_inst_gen( &ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->base.value->type = result_type; instruction->operand = operand; instruction->result_loc = result_loc; - ir_ref_instruction(operand, ira->new_irb.current_basic_block); - if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block); + ir_ref_inst_gen(operand, ira->new_irb.current_basic_block); + if (result_loc != nullptr) ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_err_wrap_code(IrAnalyze *ira, IrInstruction *source_instruction, - ZigType *result_type, IrInstruction *operand, IrInstruction *result_loc) +static IrInstGen *ir_build_err_wrap_code(IrAnalyze *ira, IrInst *source_instruction, + ZigType *result_type, IrInstGen *operand, IrInstGen *result_loc) { - IrInstructionErrWrapCode *instruction = ir_build_instruction( + IrInstGenErrWrapCode *instruction = ir_build_inst_gen( &ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->base.value->type = result_type; instruction->operand = operand; instruction->result_loc = result_loc; - ir_ref_instruction(operand, ira->new_irb.current_basic_block); - if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block); + ir_ref_inst_gen(operand, ira->new_irb.current_basic_block); + if (result_loc != nullptr) ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_clz(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) { - IrInstructionClz *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type = type; - instruction->op = op; - - if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block); - ir_ref_instruction(op, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstruction *ir_build_ctz(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) { - IrInstructionCtz *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type = type; - instruction->op = op; - - if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block); - ir_ref_instruction(op, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstruction *ir_build_pop_count(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) { - IrInstructionPopCount *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type = type; - instruction->op = op; - - if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block); - ir_ref_instruction(op, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstruction *ir_build_bswap(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) { - IrInstructionBswap *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type = type; - instruction->op = op; - - if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block); - ir_ref_instruction(op, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstruction *ir_build_bit_reverse(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) { - IrInstructionBitReverse *instruction = ir_build_instruction(irb, scope, source_node); - instruction->type = type; - instruction->op = op; - - if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block); - ir_ref_instruction(op, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstructionSwitchBr *ir_build_switch_br(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target_value, - IrBasicBlock *else_block, size_t case_count, IrInstructionSwitchBrCase *cases, IrInstruction *is_comptime, - IrInstruction *switch_prongs_void) +static IrInstSrc *ir_build_clz(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, + IrInstSrc *op) { - IrInstructionSwitchBr *instruction = ir_build_instruction(irb, scope, source_node); - instruction->base.value->type = irb->codegen->builtin_types.entry_unreachable; - instruction->base.value->special = ConstValSpecialStatic; + IrInstSrcClz *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type = type; + instruction->op = op; + + ir_ref_instruction(type, irb->current_basic_block); + ir_ref_instruction(op, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstGen *ir_build_clz_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *result_type, IrInstGen *op) { + IrInstGenClz *instruction = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->base.value->type = result_type; + instruction->op = op; + + ir_ref_inst_gen(op, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_ctz(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, + IrInstSrc *op) +{ + IrInstSrcCtz *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type = type; + instruction->op = op; + + ir_ref_instruction(type, irb->current_basic_block); + ir_ref_instruction(op, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstGen *ir_build_ctz_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *result_type, IrInstGen *op) { + IrInstGenCtz *instruction = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->base.value->type = result_type; + instruction->op = op; + + ir_ref_inst_gen(op, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_pop_count(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, + IrInstSrc *op) +{ + IrInstSrcPopCount *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type = type; + instruction->op = op; + + ir_ref_instruction(type, irb->current_basic_block); + ir_ref_instruction(op, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstGen *ir_build_pop_count_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *result_type, + IrInstGen *op) +{ + IrInstGenPopCount *instruction = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->base.value->type = result_type; + instruction->op = op; + + ir_ref_inst_gen(op, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_bswap(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, + IrInstSrc *op) +{ + IrInstSrcBswap *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type = type; + instruction->op = op; + + ir_ref_instruction(type, irb->current_basic_block); + ir_ref_instruction(op, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstGen *ir_build_bswap_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *op_type, + IrInstGen *op) +{ + IrInstGenBswap *instruction = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->base.value->type = op_type; + instruction->op = op; + + ir_ref_inst_gen(op, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_bit_reverse(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, + IrInstSrc *op) +{ + IrInstSrcBitReverse *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type = type; + instruction->op = op; + + ir_ref_instruction(type, irb->current_basic_block); + ir_ref_instruction(op, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstGen *ir_build_bit_reverse_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *int_type, + IrInstGen *op) +{ + IrInstGenBitReverse *instruction = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->base.value->type = int_type; + instruction->op = op; + + ir_ref_inst_gen(op, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrcSwitchBr *ir_build_switch_br_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target_value, IrBasicBlockSrc *else_block, size_t case_count, IrInstSrcSwitchBrCase *cases, + IrInstSrc *is_comptime, IrInstSrc *switch_prongs_void) +{ + IrInstSrcSwitchBr *instruction = ir_build_instruction(irb, scope, source_node); + instruction->base.is_noreturn = true; instruction->target_value = target_value; instruction->else_block = else_block; instruction->case_count = case_count; @@ -2560,9 +3220,9 @@ static IrInstructionSwitchBr *ir_build_switch_br(IrBuilder *irb, Scope *scope, A instruction->switch_prongs_void = switch_prongs_void; ir_ref_instruction(target_value, irb->current_basic_block); - if (is_comptime) ir_ref_instruction(is_comptime, irb->current_basic_block); + ir_ref_instruction(is_comptime, irb->current_basic_block); ir_ref_bb(else_block); - if (switch_prongs_void) ir_ref_instruction(switch_prongs_void, irb->current_basic_block); + ir_ref_instruction(switch_prongs_void, irb->current_basic_block); for (size_t i = 0; i < case_count; i += 1) { ir_ref_instruction(cases[i].value, irb->current_basic_block); @@ -2572,10 +3232,31 @@ static IrInstructionSwitchBr *ir_build_switch_br(IrBuilder *irb, Scope *scope, A return instruction; } -static IrInstruction *ir_build_switch_target(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *target_value_ptr) +static IrInstGenSwitchBr *ir_build_switch_br_gen(IrAnalyze *ira, IrInst *source_instr, + IrInstGen *target_value, IrBasicBlockGen *else_block, size_t case_count, IrInstGenSwitchBrCase *cases) { - IrInstructionSwitchTarget *instruction = ir_build_instruction(irb, scope, source_node); + IrInstGenSwitchBr *instruction = ir_build_inst_noreturn(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->target_value = target_value; + instruction->else_block = else_block; + instruction->case_count = case_count; + instruction->cases = cases; + + ir_ref_inst_gen(target_value, ira->new_irb.current_basic_block); + ir_ref_bb_gen(else_block); + + for (size_t i = 0; i < case_count; i += 1) { + ir_ref_inst_gen(cases[i].value, ira->new_irb.current_basic_block); + ir_ref_bb_gen(cases[i].block); + } + + return instruction; +} + +static IrInstSrc *ir_build_switch_target(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target_value_ptr) +{ + IrInstSrcSwitchTarget *instruction = ir_build_instruction(irb, scope, source_node); instruction->target_value_ptr = target_value_ptr; ir_ref_instruction(target_value_ptr, irb->current_basic_block); @@ -2583,10 +3264,10 @@ static IrInstruction *ir_build_switch_target(IrBuilder *irb, Scope *scope, AstNo return &instruction->base; } -static IrInstruction *ir_build_switch_var(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *target_value_ptr, IrInstruction **prongs_ptr, size_t prongs_len) +static IrInstSrc *ir_build_switch_var(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target_value_ptr, IrInstSrc **prongs_ptr, size_t prongs_len) { - IrInstructionSwitchVar *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSwitchVar *instruction = ir_build_instruction(irb, scope, source_node); instruction->target_value_ptr = target_value_ptr; instruction->prongs_ptr = prongs_ptr; instruction->prongs_len = prongs_len; @@ -2600,10 +3281,10 @@ static IrInstruction *ir_build_switch_var(IrBuilder *irb, Scope *scope, AstNode } // For this instruction the switch_br must be set later. -static IrInstructionSwitchElseVar *ir_build_switch_else_var(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *target_value_ptr) +static IrInstSrcSwitchElseVar *ir_build_switch_else_var(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target_value_ptr) { - IrInstructionSwitchElseVar *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSwitchElseVar *instruction = ir_build_instruction(irb, scope, source_node); instruction->target_value_ptr = target_value_ptr; ir_ref_instruction(target_value_ptr, irb->current_basic_block); @@ -2611,17 +3292,21 @@ static IrInstructionSwitchElseVar *ir_build_switch_else_var(IrBuilder *irb, Scop return instruction; } -static IrInstruction *ir_build_union_tag(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { - IrInstructionUnionTag *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstGen *ir_build_union_tag(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value, + ZigType *tag_type) +{ + IrInstGenUnionTag *instruction = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); instruction->value = value; + instruction->base.value->type = tag_type; - ir_ref_instruction(value, irb->current_basic_block); + ir_ref_inst_gen(value, ira->new_irb.current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_import(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *name) { - IrInstructionImport *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_import(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { + IrInstSrcImport *instruction = ir_build_instruction(irb, scope, source_node); instruction->name = name; ir_ref_instruction(name, irb->current_basic_block); @@ -2629,10 +3314,10 @@ static IrInstruction *ir_build_import(IrBuilder *irb, Scope *scope, AstNode *sou return &instruction->base; } -static IrInstruction *ir_build_ref(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value, +static IrInstSrc *ir_build_ref_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value, bool is_const, bool is_volatile) { - IrInstructionRef *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcRef *instruction = ir_build_instruction(irb, scope, source_node); instruction->value = value; instruction->is_const = is_const; instruction->is_volatile = is_volatile; @@ -2642,23 +3327,23 @@ static IrInstruction *ir_build_ref(IrBuilder *irb, Scope *scope, AstNode *source return &instruction->base; } -static IrInstruction *ir_build_ref_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *result_type, - IrInstruction *operand, IrInstruction *result_loc) +static IrInstGen *ir_build_ref_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *result_type, + IrInstGen *operand, IrInstGen *result_loc) { - IrInstructionRefGen *instruction = ir_build_instruction(&ira->new_irb, + IrInstGenRef *instruction = ir_build_inst_gen(&ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->base.value->type = result_type; instruction->operand = operand; instruction->result_loc = result_loc; - ir_ref_instruction(operand, ira->new_irb.current_basic_block); - if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block); + ir_ref_inst_gen(operand, ira->new_irb.current_basic_block); + if (result_loc != nullptr) ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_compile_err(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *msg) { - IrInstructionCompileErr *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_compile_err(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *msg) { + IrInstSrcCompileErr *instruction = ir_build_instruction(irb, scope, source_node); instruction->msg = msg; ir_ref_instruction(msg, irb->current_basic_block); @@ -2666,10 +3351,10 @@ static IrInstruction *ir_build_compile_err(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_compile_log(IrBuilder *irb, Scope *scope, AstNode *source_node, - size_t msg_count, IrInstruction **msg_list) +static IrInstSrc *ir_build_compile_log(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + size_t msg_count, IrInstSrc **msg_list) { - IrInstructionCompileLog *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcCompileLog *instruction = ir_build_instruction(irb, scope, source_node); instruction->msg_count = msg_count; instruction->msg_list = msg_list; @@ -2680,8 +3365,8 @@ static IrInstruction *ir_build_compile_log(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_err_name(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { - IrInstructionErrName *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_err_name(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { + IrInstSrcErrName *instruction = ir_build_instruction(irb, scope, source_node); instruction->value = value; ir_ref_instruction(value, irb->current_basic_block); @@ -2689,54 +3374,67 @@ static IrInstruction *ir_build_err_name(IrBuilder *irb, Scope *scope, AstNode *s return &instruction->base; } -static IrInstruction *ir_build_c_import(IrBuilder *irb, Scope *scope, AstNode *source_node) { - IrInstructionCImport *instruction = ir_build_instruction(irb, scope, source_node); - return &instruction->base; -} - -static IrInstruction *ir_build_c_include(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *name) { - IrInstructionCInclude *instruction = ir_build_instruction(irb, scope, source_node); - instruction->name = name; - - ir_ref_instruction(name, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstruction *ir_build_c_define(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *name, IrInstruction *value) { - IrInstructionCDefine *instruction = ir_build_instruction(irb, scope, source_node); - instruction->name = name; - instruction->value = value; - - ir_ref_instruction(name, irb->current_basic_block); - ir_ref_instruction(value, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstruction *ir_build_c_undef(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *name) { - IrInstructionCUndef *instruction = ir_build_instruction(irb, scope, source_node); - instruction->name = name; - - ir_ref_instruction(name, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *name) { - IrInstructionEmbedFile *instruction = ir_build_instruction(irb, scope, source_node); - instruction->name = name; - - ir_ref_instruction(name, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *type_value, IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value, - IrInstruction *success_order_value, IrInstruction *failure_order_value, bool is_weak, ResultLoc *result_loc) +static IrInstGen *ir_build_err_name_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value, + ZigType *str_type) { - IrInstructionCmpxchgSrc *instruction = ir_build_instruction(irb, scope, source_node); + IrInstGenErrName *instruction = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->base.value->type = str_type; + instruction->value = value; + + ir_ref_inst_gen(value, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_c_import(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcCImport *instruction = ir_build_instruction(irb, scope, source_node); + return &instruction->base; +} + +static IrInstSrc *ir_build_c_include(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { + IrInstSrcCInclude *instruction = ir_build_instruction(irb, scope, source_node); + instruction->name = name; + + ir_ref_instruction(name, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_c_define(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name, IrInstSrc *value) { + IrInstSrcCDefine *instruction = ir_build_instruction(irb, scope, source_node); + instruction->name = name; + instruction->value = value; + + ir_ref_instruction(name, irb->current_basic_block); + ir_ref_instruction(value, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_c_undef(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { + IrInstSrcCUndef *instruction = ir_build_instruction(irb, scope, source_node); + instruction->name = name; + + ir_ref_instruction(name, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_embed_file(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { + IrInstSrcEmbedFile *instruction = ir_build_instruction(irb, scope, source_node); + instruction->name = name; + + ir_ref_instruction(name, irb->current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_cmpxchg_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *type_value, IrInstSrc *ptr, IrInstSrc *cmp_value, IrInstSrc *new_value, + IrInstSrc *success_order_value, IrInstSrc *failure_order_value, bool is_weak, ResultLoc *result_loc) +{ + IrInstSrcCmpxchg *instruction = ir_build_instruction(irb, scope, source_node); instruction->type_value = type_value; instruction->ptr = ptr; instruction->cmp_value = cmp_value; @@ -2756,11 +3454,11 @@ static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *result_type, - IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value, - AtomicOrder success_order, AtomicOrder failure_order, bool is_weak, IrInstruction *result_loc) +static IrInstGen *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *result_type, + IrInstGen *ptr, IrInstGen *cmp_value, IrInstGen *new_value, + AtomicOrder success_order, AtomicOrder failure_order, bool is_weak, IrInstGen *result_loc) { - IrInstructionCmpxchgGen *instruction = ir_build_instruction(&ira->new_irb, + IrInstGenCmpxchg *instruction = ir_build_inst_gen(&ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->base.value->type = result_type; instruction->ptr = ptr; @@ -2771,26 +3469,35 @@ static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source instruction->is_weak = is_weak; instruction->result_loc = result_loc; - ir_ref_instruction(ptr, ira->new_irb.current_basic_block); - ir_ref_instruction(cmp_value, ira->new_irb.current_basic_block); - ir_ref_instruction(new_value, ira->new_irb.current_basic_block); - if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block); + ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block); + ir_ref_inst_gen(cmp_value, ira->new_irb.current_basic_block); + ir_ref_inst_gen(new_value, ira->new_irb.current_basic_block); + if (result_loc != nullptr) ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_fence(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *order_value, AtomicOrder order) { - IrInstructionFence *instruction = ir_build_instruction(irb, scope, source_node); - instruction->order_value = order_value; +static IrInstSrc *ir_build_fence(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *order) { + IrInstSrcFence *instruction = ir_build_instruction(irb, scope, source_node); instruction->order = order; - ir_ref_instruction(order_value, irb->current_basic_block); + ir_ref_instruction(order, irb->current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_truncate(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *target) { - IrInstructionTruncate *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstGen *ir_build_fence_gen(IrAnalyze *ira, IrInst *source_instr, AtomicOrder order) { + IrInstGenFence *instruction = ir_build_inst_void(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->order = order; + + return &instruction->base; +} + +static IrInstSrc *ir_build_truncate(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *dest_type, IrInstSrc *target) +{ + IrInstSrcTruncate *instruction = ir_build_instruction(irb, scope, source_node); instruction->dest_type = dest_type; instruction->target = target; @@ -2800,8 +3507,23 @@ static IrInstruction *ir_build_truncate(IrBuilder *irb, Scope *scope, AstNode *s return &instruction->base; } -static IrInstruction *ir_build_int_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *target) { - IrInstructionIntCast *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstGen *ir_build_truncate_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *dest_type, + IrInstGen *target) +{ + IrInstGenTruncate *instruction = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->base.value->type = dest_type; + instruction->target = target; + + ir_ref_inst_gen(target, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_int_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, + IrInstSrc *target) +{ + IrInstSrcIntCast *instruction = ir_build_instruction(irb, scope, source_node); instruction->dest_type = dest_type; instruction->target = target; @@ -2811,8 +3533,10 @@ static IrInstruction *ir_build_int_cast(IrBuilder *irb, Scope *scope, AstNode *s return &instruction->base; } -static IrInstruction *ir_build_float_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *target) { - IrInstructionFloatCast *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_float_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, + IrInstSrc *target) +{ + IrInstSrcFloatCast *instruction = ir_build_instruction(irb, scope, source_node); instruction->dest_type = dest_type; instruction->target = target; @@ -2822,8 +3546,10 @@ static IrInstruction *ir_build_float_cast(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_err_set_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *target) { - IrInstructionErrSetCast *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_err_set_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *dest_type, IrInstSrc *target) +{ + IrInstSrcErrSetCast *instruction = ir_build_instruction(irb, scope, source_node); instruction->dest_type = dest_type; instruction->target = target; @@ -2833,10 +3559,10 @@ static IrInstruction *ir_build_err_set_cast(IrBuilder *irb, Scope *scope, AstNod return &instruction->base; } -static IrInstruction *ir_build_to_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target, +static IrInstSrc *ir_build_to_bytes(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *target, ResultLoc *result_loc) { - IrInstructionToBytes *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcToBytes *instruction = ir_build_instruction(irb, scope, source_node); instruction->target = target; instruction->result_loc = result_loc; @@ -2845,10 +3571,10 @@ static IrInstruction *ir_build_to_bytes(IrBuilder *irb, Scope *scope, AstNode *s return &instruction->base; } -static IrInstruction *ir_build_from_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *dest_child_type, IrInstruction *target, ResultLoc *result_loc) +static IrInstSrc *ir_build_from_bytes(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *dest_child_type, IrInstSrc *target, ResultLoc *result_loc) { - IrInstructionFromBytes *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcFromBytes *instruction = ir_build_instruction(irb, scope, source_node); instruction->dest_child_type = dest_child_type; instruction->target = target; instruction->result_loc = result_loc; @@ -2859,8 +3585,10 @@ static IrInstruction *ir_build_from_bytes(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_int_to_float(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *target) { - IrInstructionIntToFloat *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_int_to_float(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *dest_type, IrInstSrc *target) +{ + IrInstSrcIntToFloat *instruction = ir_build_instruction(irb, scope, source_node); instruction->dest_type = dest_type; instruction->target = target; @@ -2870,8 +3598,10 @@ static IrInstruction *ir_build_int_to_float(IrBuilder *irb, Scope *scope, AstNod return &instruction->base; } -static IrInstruction *ir_build_float_to_int(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *target) { - IrInstructionFloatToInt *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_float_to_int(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *dest_type, IrInstSrc *target) +{ + IrInstSrcFloatToInt *instruction = ir_build_instruction(irb, scope, source_node); instruction->dest_type = dest_type; instruction->target = target; @@ -2881,8 +3611,8 @@ static IrInstruction *ir_build_float_to_int(IrBuilder *irb, Scope *scope, AstNod return &instruction->base; } -static IrInstruction *ir_build_bool_to_int(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target) { - IrInstructionBoolToInt *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_bool_to_int(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *target) { + IrInstSrcBoolToInt *instruction = ir_build_instruction(irb, scope, source_node); instruction->target = target; ir_ref_instruction(target, irb->current_basic_block); @@ -2890,8 +3620,10 @@ static IrInstruction *ir_build_bool_to_int(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_int_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *is_signed, IrInstruction *bit_count) { - IrInstructionIntType *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_int_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *is_signed, + IrInstSrc *bit_count) +{ + IrInstSrcIntType *instruction = ir_build_instruction(irb, scope, source_node); instruction->is_signed = is_signed; instruction->bit_count = bit_count; @@ -2901,10 +3633,10 @@ static IrInstruction *ir_build_int_type(IrBuilder *irb, Scope *scope, AstNode *s return &instruction->base; } -static IrInstruction *ir_build_vector_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *len, - IrInstruction *elem_type) +static IrInstSrc *ir_build_vector_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *len, + IrInstSrc *elem_type) { - IrInstructionVectorType *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcVectorType *instruction = ir_build_instruction(irb, scope, source_node); instruction->len = len; instruction->elem_type = elem_type; @@ -2914,18 +3646,16 @@ static IrInstruction *ir_build_vector_type(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_shuffle_vector(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *scalar_type, IrInstruction *a, IrInstruction *b, IrInstruction *mask) +static IrInstSrc *ir_build_shuffle_vector(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *scalar_type, IrInstSrc *a, IrInstSrc *b, IrInstSrc *mask) { - IrInstructionShuffleVector *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcShuffleVector *instruction = ir_build_instruction(irb, scope, source_node); instruction->scalar_type = scalar_type; instruction->a = a; instruction->b = b; instruction->mask = mask; - if (scalar_type != nullptr) { - ir_ref_instruction(scalar_type, irb->current_basic_block); - } + if (scalar_type != nullptr) ir_ref_instruction(scalar_type, irb->current_basic_block); ir_ref_instruction(a, irb->current_basic_block); ir_ref_instruction(b, irb->current_basic_block); ir_ref_instruction(mask, irb->current_basic_block); @@ -2933,10 +3663,26 @@ static IrInstruction *ir_build_shuffle_vector(IrBuilder *irb, Scope *scope, AstN return &instruction->base; } -static IrInstruction *ir_build_splat_src(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *len, IrInstruction *scalar) +static IrInstGen *ir_build_shuffle_vector_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, + ZigType *result_type, IrInstGen *a, IrInstGen *b, IrInstGen *mask) { - IrInstructionSplatSrc *instruction = ir_build_instruction(irb, scope, source_node); + IrInstGenShuffleVector *inst = ir_build_inst_gen(&ira->new_irb, scope, source_node); + inst->base.value->type = result_type; + inst->a = a; + inst->b = b; + inst->mask = mask; + + ir_ref_inst_gen(a, ira->new_irb.current_basic_block); + ir_ref_inst_gen(b, ira->new_irb.current_basic_block); + ir_ref_inst_gen(mask, ira->new_irb.current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_splat_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *len, IrInstSrc *scalar) +{ + IrInstSrcSplat *instruction = ir_build_instruction(irb, scope, source_node); instruction->len = len; instruction->scalar = scalar; @@ -2946,8 +3692,21 @@ static IrInstruction *ir_build_splat_src(IrBuilder *irb, Scope *scope, AstNode * return &instruction->base; } -static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { - IrInstructionBoolNot *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstGen *ir_build_splat_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *result_type, + IrInstGen *scalar) +{ + IrInstGenSplat *instruction = ir_build_inst_gen( + &ira->new_irb, source_instruction->scope, source_instruction->source_node); + instruction->base.value->type = result_type; + instruction->scalar = scalar; + + ir_ref_inst_gen(scalar, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_bool_not(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { + IrInstSrcBoolNot *instruction = ir_build_instruction(irb, scope, source_node); instruction->value = value; ir_ref_instruction(value, irb->current_basic_block); @@ -2955,10 +3714,21 @@ static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *s return &instruction->base; } -static IrInstruction *ir_build_memset(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *dest_ptr, IrInstruction *byte, IrInstruction *count) +static IrInstGen *ir_build_bool_not_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value) { + IrInstGenBoolNot *instruction = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->base.value->type = ira->codegen->builtin_types.entry_bool; + instruction->value = value; + + ir_ref_inst_gen(value, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_memset_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *dest_ptr, IrInstSrc *byte, IrInstSrc *count) { - IrInstructionMemset *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcMemset *instruction = ir_build_instruction(irb, scope, source_node); instruction->dest_ptr = dest_ptr; instruction->byte = byte; instruction->count = count; @@ -2970,10 +3740,26 @@ static IrInstruction *ir_build_memset(IrBuilder *irb, Scope *scope, AstNode *sou return &instruction->base; } -static IrInstruction *ir_build_memcpy(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *dest_ptr, IrInstruction *src_ptr, IrInstruction *count) +static IrInstGen *ir_build_memset_gen(IrAnalyze *ira, IrInst *source_instr, + IrInstGen *dest_ptr, IrInstGen *byte, IrInstGen *count) { - IrInstructionMemcpy *instruction = ir_build_instruction(irb, scope, source_node); + IrInstGenMemset *instruction = ir_build_inst_void(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->dest_ptr = dest_ptr; + instruction->byte = byte; + instruction->count = count; + + ir_ref_inst_gen(dest_ptr, ira->new_irb.current_basic_block); + ir_ref_inst_gen(byte, ira->new_irb.current_basic_block); + ir_ref_inst_gen(count, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_memcpy_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *dest_ptr, IrInstSrc *src_ptr, IrInstSrc *count) +{ + IrInstSrcMemcpy *instruction = ir_build_instruction(irb, scope, source_node); instruction->dest_ptr = dest_ptr; instruction->src_ptr = src_ptr; instruction->count = count; @@ -2985,11 +3771,27 @@ static IrInstruction *ir_build_memcpy(IrBuilder *irb, Scope *scope, AstNode *sou return &instruction->base; } -static IrInstruction *ir_build_slice_src(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *ptr, IrInstruction *start, IrInstruction *end, IrInstruction *sentinel, +static IrInstGen *ir_build_memcpy_gen(IrAnalyze *ira, IrInst *source_instr, + IrInstGen *dest_ptr, IrInstGen *src_ptr, IrInstGen *count) +{ + IrInstGenMemcpy *instruction = ir_build_inst_void(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->dest_ptr = dest_ptr; + instruction->src_ptr = src_ptr; + instruction->count = count; + + ir_ref_inst_gen(dest_ptr, ira->new_irb.current_basic_block); + ir_ref_inst_gen(src_ptr, ira->new_irb.current_basic_block); + ir_ref_inst_gen(count, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_slice_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *ptr, IrInstSrc *start, IrInstSrc *end, IrInstSrc *sentinel, bool safety_check_on, ResultLoc *result_loc) { - IrInstructionSliceSrc *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSlice *instruction = ir_build_instruction(irb, scope, source_node); instruction->ptr = ptr; instruction->start = start; instruction->end = end; @@ -3005,23 +3807,10 @@ static IrInstruction *ir_build_slice_src(IrBuilder *irb, Scope *scope, AstNode * return &instruction->base; } -static IrInstruction *ir_build_splat_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *result_type, - IrInstruction *scalar) +static IrInstGen *ir_build_slice_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *slice_type, + IrInstGen *ptr, IrInstGen *start, IrInstGen *end, bool safety_check_on, IrInstGen *result_loc) { - IrInstructionSplatGen *instruction = ir_build_instruction( - &ira->new_irb, source_instruction->scope, source_instruction->source_node); - instruction->base.value->type = result_type; - instruction->scalar = scalar; - - ir_ref_instruction(scalar, ira->new_irb.current_basic_block); - - return &instruction->base; -} - -static IrInstruction *ir_build_slice_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *slice_type, - IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on, IrInstruction *result_loc) -{ - IrInstructionSliceGen *instruction = ir_build_instruction( + IrInstGenSlice *instruction = ir_build_inst_gen( &ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->base.value->type = slice_type; instruction->ptr = ptr; @@ -3030,16 +3819,16 @@ static IrInstruction *ir_build_slice_gen(IrAnalyze *ira, IrInstruction *source_i instruction->safety_check_on = safety_check_on; instruction->result_loc = result_loc; - ir_ref_instruction(ptr, ira->new_irb.current_basic_block); - ir_ref_instruction(start, ira->new_irb.current_basic_block); - if (end) ir_ref_instruction(end, ira->new_irb.current_basic_block); - ir_ref_instruction(result_loc, ira->new_irb.current_basic_block); + ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block); + ir_ref_inst_gen(start, ira->new_irb.current_basic_block); + if (end) ir_ref_inst_gen(end, ira->new_irb.current_basic_block); + ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_member_count(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *container) { - IrInstructionMemberCount *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_member_count(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *container) { + IrInstSrcMemberCount *instruction = ir_build_instruction(irb, scope, source_node); instruction->container = container; ir_ref_instruction(container, irb->current_basic_block); @@ -3047,10 +3836,10 @@ static IrInstruction *ir_build_member_count(IrBuilder *irb, Scope *scope, AstNod return &instruction->base; } -static IrInstruction *ir_build_member_type(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *container_type, IrInstruction *member_index) +static IrInstSrc *ir_build_member_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *container_type, IrInstSrc *member_index) { - IrInstructionMemberType *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcMemberType *instruction = ir_build_instruction(irb, scope, source_node); instruction->container_type = container_type; instruction->member_index = member_index; @@ -3060,10 +3849,10 @@ static IrInstruction *ir_build_member_type(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_member_name(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *container_type, IrInstruction *member_index) +static IrInstSrc *ir_build_member_name(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *container_type, IrInstSrc *member_index) { - IrInstructionMemberName *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcMemberName *instruction = ir_build_instruction(irb, scope, source_node); instruction->container_type = container_type; instruction->member_index = member_index; @@ -3073,65 +3862,88 @@ static IrInstruction *ir_build_member_name(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_breakpoint(IrBuilder *irb, Scope *scope, AstNode *source_node) { - IrInstructionBreakpoint *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_breakpoint(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcBreakpoint *instruction = ir_build_instruction(irb, scope, source_node); return &instruction->base; } -static IrInstruction *ir_build_return_address(IrBuilder *irb, Scope *scope, AstNode *source_node) { - IrInstructionReturnAddress *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstGen *ir_build_breakpoint_gen(IrAnalyze *ira, IrInst *source_instr) { + IrInstGenBreakpoint *instruction = ir_build_inst_void(&ira->new_irb, + source_instr->scope, source_instr->source_node); return &instruction->base; } -static IrInstruction *ir_build_frame_address(IrBuilder *irb, Scope *scope, AstNode *source_node) { - IrInstructionFrameAddress *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_return_address_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcReturnAddress *instruction = ir_build_instruction(irb, scope, source_node); return &instruction->base; } -static IrInstruction *ir_build_handle(IrBuilder *irb, Scope *scope, AstNode *source_node) { - IrInstructionFrameHandle *instruction = ir_build_instruction(irb, scope, source_node); - return &instruction->base; +static IrInstGen *ir_build_return_address_gen(IrAnalyze *ira, IrInst *source_instr) { + IrInstGenReturnAddress *inst = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); + inst->base.value->type = ira->codegen->builtin_types.entry_usize; + return &inst->base; } -static IrInstruction *ir_build_frame_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *fn) { - IrInstructionFrameType *instruction = ir_build_instruction(irb, scope, source_node); - instruction->fn = fn; +static IrInstSrc *ir_build_frame_address_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcFrameAddress *inst = ir_build_instruction(irb, scope, source_node); + return &inst->base; +} + +static IrInstGen *ir_build_frame_address_gen(IrAnalyze *ira, IrInst *source_instr) { + IrInstGenFrameAddress *inst = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); + inst->base.value->type = ira->codegen->builtin_types.entry_usize; + return &inst->base; +} + +static IrInstSrc *ir_build_handle_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcFrameHandle *inst = ir_build_instruction(irb, scope, source_node); + return &inst->base; +} + +static IrInstGen *ir_build_handle_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *ty) { + IrInstGenFrameHandle *inst = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); + inst->base.value->type = ty; + return &inst->base; +} + +static IrInstSrc *ir_build_frame_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *fn) { + IrInstSrcFrameType *inst = ir_build_instruction(irb, scope, source_node); + inst->fn = fn; ir_ref_instruction(fn, irb->current_basic_block); - return &instruction->base; + return &inst->base; } -static IrInstruction *ir_build_frame_size_src(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *fn) { - IrInstructionFrameSizeSrc *instruction = ir_build_instruction(irb, scope, source_node); - instruction->fn = fn; +static IrInstSrc *ir_build_frame_size_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *fn) { + IrInstSrcFrameSize *inst = ir_build_instruction(irb, scope, source_node); + inst->fn = fn; ir_ref_instruction(fn, irb->current_basic_block); - return &instruction->base; + return &inst->base; } -static IrInstruction *ir_build_frame_size_gen(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *fn) +static IrInstGen *ir_build_frame_size_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *fn) { - IrInstructionFrameSizeGen *instruction = ir_build_instruction(irb, scope, source_node); - instruction->fn = fn; + IrInstGenFrameSize *inst = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); + inst->base.value->type = ira->codegen->builtin_types.entry_usize; + inst->fn = fn; - ir_ref_instruction(fn, irb->current_basic_block); + ir_ref_inst_gen(fn, ira->new_irb.current_basic_block); - return &instruction->base; + return &inst->base; } -static IrInstruction *ir_build_overflow_op(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrOverflowOp op, IrInstruction *type_value, IrInstruction *op1, IrInstruction *op2, - IrInstruction *result_ptr, ZigType *result_ptr_type) +static IrInstSrc *ir_build_overflow_op_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrOverflowOp op, IrInstSrc *type_value, IrInstSrc *op1, IrInstSrc *op2, IrInstSrc *result_ptr) { - IrInstructionOverflowOp *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcOverflowOp *instruction = ir_build_instruction(irb, scope, source_node); instruction->op = op; instruction->type_value = type_value; instruction->op1 = op1; instruction->op2 = op2; instruction->result_ptr = result_ptr; - instruction->result_ptr_type = result_ptr_type; ir_ref_instruction(type_value, irb->current_basic_block); ir_ref_instruction(op1, irb->current_basic_block); @@ -3141,49 +3953,30 @@ static IrInstruction *ir_build_overflow_op(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } +static IrInstGen *ir_build_overflow_op_gen(IrAnalyze *ira, IrInst *source_instr, + IrOverflowOp op, IrInstGen *op1, IrInstGen *op2, IrInstGen *result_ptr, + ZigType *result_ptr_type) +{ + IrInstGenOverflowOp *instruction = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->base.value->type = ira->codegen->builtin_types.entry_bool; + instruction->op = op; + instruction->op1 = op1; + instruction->op2 = op2; + instruction->result_ptr = result_ptr; + instruction->result_ptr_type = result_ptr_type; -//TODO Powi, Pow, minnum, maxnum, maximum, minimum, copysign, -// lround, llround, lrint, llrint -// So far this is only non-complicated type functions. -const char *float_op_to_name(BuiltinFnId op) { - switch (op) { - case BuiltinFnIdSqrt: - return "sqrt"; - case BuiltinFnIdSin: - return "sin"; - case BuiltinFnIdCos: - return "cos"; - case BuiltinFnIdExp: - return "exp"; - case BuiltinFnIdExp2: - return "exp2"; - case BuiltinFnIdLog: - return "log"; - case BuiltinFnIdLog10: - return "log10"; - case BuiltinFnIdLog2: - return "log2"; - case BuiltinFnIdFabs: - return "fabs"; - case BuiltinFnIdFloor: - return "floor"; - case BuiltinFnIdCeil: - return "ceil"; - case BuiltinFnIdTrunc: - return "trunc"; - case BuiltinFnIdNearbyInt: - return "nearbyint"; - case BuiltinFnIdRound: - return "round"; - default: - zig_unreachable(); - } + ir_ref_inst_gen(op1, ira->new_irb.current_basic_block); + ir_ref_inst_gen(op2, ira->new_irb.current_basic_block); + ir_ref_inst_gen(result_ptr, ira->new_irb.current_basic_block); + + return &instruction->base; } -static IrInstruction *ir_build_float_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *operand, +static IrInstSrc *ir_build_float_op_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *operand, BuiltinFnId fn_id) { - IrInstructionFloatOp *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcFloatOp *instruction = ir_build_instruction(irb, scope, source_node); instruction->operand = operand; instruction->fn_id = fn_id; @@ -3192,9 +3985,24 @@ static IrInstruction *ir_build_float_op(IrBuilder *irb, Scope *scope, AstNode *s return &instruction->base; } -static IrInstruction *ir_build_mul_add(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *type_value, IrInstruction *op1, IrInstruction *op2, IrInstruction *op3) { - IrInstructionMulAdd *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstGen *ir_build_float_op_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *operand, + BuiltinFnId fn_id, ZigType *operand_type) +{ + IrInstGenFloatOp *instruction = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->base.value->type = operand_type; + instruction->operand = operand; + instruction->fn_id = fn_id; + + ir_ref_inst_gen(operand, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_mul_add_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *type_value, IrInstSrc *op1, IrInstSrc *op2, IrInstSrc *op3) +{ + IrInstSrcMulAdd *instruction = ir_build_instruction(irb, scope, source_node); instruction->type_value = type_value; instruction->op1 = op1; instruction->op2 = op2; @@ -3208,8 +4016,25 @@ static IrInstruction *ir_build_mul_add(IrBuilder *irb, Scope *scope, AstNode *so return &instruction->base; } -static IrInstruction *ir_build_align_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) { - IrInstructionAlignOf *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstGen *ir_build_mul_add_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *op1, IrInstGen *op2, + IrInstGen *op3, ZigType *expr_type) +{ + IrInstGenMulAdd *instruction = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->base.value->type = expr_type; + instruction->op1 = op1; + instruction->op2 = op2; + instruction->op3 = op3; + + ir_ref_inst_gen(op1, ira->new_irb.current_basic_block); + ir_ref_inst_gen(op2, ira->new_irb.current_basic_block); + ir_ref_inst_gen(op3, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_align_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_value) { + IrInstSrcAlignOf *instruction = ir_build_instruction(irb, scope, source_node); instruction->type_value = type_value; ir_ref_instruction(type_value, irb->current_basic_block); @@ -3217,10 +4042,10 @@ static IrInstruction *ir_build_align_of(IrBuilder *irb, Scope *scope, AstNode *s return &instruction->base; } -static IrInstruction *ir_build_test_err_src(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *base_ptr, bool resolve_err_set, bool base_ptr_is_payload) +static IrInstSrc *ir_build_test_err_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *base_ptr, bool resolve_err_set, bool base_ptr_is_payload) { - IrInstructionTestErrSrc *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcTestErr *instruction = ir_build_instruction(irb, scope, source_node); instruction->base_ptr = base_ptr; instruction->resolve_err_set = resolve_err_set; instruction->base_ptr_is_payload = base_ptr_is_payload; @@ -3230,48 +4055,72 @@ static IrInstruction *ir_build_test_err_src(IrBuilder *irb, Scope *scope, AstNod return &instruction->base; } -static IrInstruction *ir_build_test_err_gen(IrAnalyze *ira, IrInstruction *source_instruction, - IrInstruction *err_union) -{ - IrInstructionTestErrGen *instruction = ir_build_instruction( +static IrInstGen *ir_build_test_err_gen(IrAnalyze *ira, IrInst *source_instruction, IrInstGen *err_union) { + IrInstGenTestErr *instruction = ir_build_inst_gen( &ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->base.value->type = ira->codegen->builtin_types.entry_bool; instruction->err_union = err_union; - ir_ref_instruction(err_union, ira->new_irb.current_basic_block); + ir_ref_inst_gen(err_union, ira->new_irb.current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *err_union_ptr) +static IrInstSrc *ir_build_unwrap_err_code_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *err_union_ptr) { - IrInstructionUnwrapErrCode *instruction = ir_build_instruction(irb, scope, source_node); - instruction->err_union_ptr = err_union_ptr; + IrInstSrcUnwrapErrCode *inst = ir_build_instruction(irb, scope, source_node); + inst->err_union_ptr = err_union_ptr; ir_ref_instruction(err_union_ptr, irb->current_basic_block); - return &instruction->base; + return &inst->base; } -static IrInstruction *ir_build_unwrap_err_payload(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *value, bool safety_check_on, bool initializing) +static IrInstGen *ir_build_unwrap_err_code_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, + IrInstGen *err_union_ptr, ZigType *result_type) { - IrInstructionUnwrapErrPayload *instruction = ir_build_instruction(irb, scope, source_node); - instruction->value = value; - instruction->safety_check_on = safety_check_on; - instruction->initializing = initializing; + IrInstGenUnwrapErrCode *inst = ir_build_inst_gen(&ira->new_irb, scope, source_node); + inst->base.value->type = result_type; + inst->err_union_ptr = err_union_ptr; + + ir_ref_inst_gen(err_union_ptr, ira->new_irb.current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_unwrap_err_payload_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *value, bool safety_check_on, bool initializing) +{ + IrInstSrcUnwrapErrPayload *inst = ir_build_instruction(irb, scope, source_node); + inst->value = value; + inst->safety_check_on = safety_check_on; + inst->initializing = initializing; ir_ref_instruction(value, irb->current_basic_block); - return &instruction->base; + return &inst->base; } -static IrInstruction *ir_build_fn_proto(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction **param_types, IrInstruction *align_value, IrInstruction *callconv_value, - IrInstruction *return_type, bool is_var_args) +static IrInstGen *ir_build_unwrap_err_payload_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, + IrInstGen *value, bool safety_check_on, bool initializing, ZigType *result_type) { - IrInstructionFnProto *instruction = ir_build_instruction(irb, scope, source_node); + IrInstGenUnwrapErrPayload *inst = ir_build_inst_gen(&ira->new_irb, scope, source_node); + inst->base.value->type = result_type; + inst->value = value; + inst->safety_check_on = safety_check_on; + inst->initializing = initializing; + + ir_ref_inst_gen(value, ira->new_irb.current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_fn_proto(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc **param_types, IrInstSrc *align_value, IrInstSrc *callconv_value, + IrInstSrc *return_type, bool is_var_args) +{ + IrInstSrcFnProto *instruction = ir_build_instruction(irb, scope, source_node); instruction->param_types = param_types; instruction->align_value = align_value; instruction->callconv_value = callconv_value; @@ -3291,8 +4140,8 @@ static IrInstruction *ir_build_fn_proto(IrBuilder *irb, Scope *scope, AstNode *s return &instruction->base; } -static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { - IrInstructionTestComptime *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_test_comptime(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { + IrInstSrcTestComptime *instruction = ir_build_instruction(irb, scope, source_node); instruction->value = value; ir_ref_instruction(value, irb->current_basic_block); @@ -3300,10 +4149,10 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo return &instruction->base; } -static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *dest_type, IrInstruction *ptr, bool safety_check_on) +static IrInstSrc *ir_build_ptr_cast_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *dest_type, IrInstSrc *ptr, bool safety_check_on) { - IrInstructionPtrCastSrc *instruction = ir_build_instruction( + IrInstSrcPtrCast *instruction = ir_build_instruction( irb, scope, source_node); instruction->dest_type = dest_type; instruction->ptr = ptr; @@ -3315,39 +4164,24 @@ static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNod return &instruction->base; } -static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction, - ZigType *ptr_type, IrInstruction *ptr, bool safety_check_on) +static IrInstGen *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInst *source_instruction, + ZigType *ptr_type, IrInstGen *ptr, bool safety_check_on) { - IrInstructionPtrCastGen *instruction = ir_build_instruction( + IrInstGenPtrCast *instruction = ir_build_inst_gen( &ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->base.value->type = ptr_type; instruction->ptr = ptr; instruction->safety_check_on = safety_check_on; - ir_ref_instruction(ptr, ira->new_irb.current_basic_block); + ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_load_ptr_gen(IrAnalyze *ira, IrInstruction *source_instruction, - IrInstruction *ptr, ZigType *ty, IrInstruction *result_loc) +static IrInstSrc *ir_build_implicit_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *operand, ResultLocCast *result_loc_cast) { - IrInstructionLoadPtrGen *instruction = ir_build_instruction( - &ira->new_irb, source_instruction->scope, source_instruction->source_node); - instruction->base.value->type = ty; - instruction->ptr = ptr; - instruction->result_loc = result_loc; - - ir_ref_instruction(ptr, ira->new_irb.current_basic_block); - if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block); - - return &instruction->base; -} - -static IrInstruction *ir_build_implicit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *operand, ResultLocCast *result_loc_cast) -{ - IrInstructionImplicitCast *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcImplicitCast *instruction = ir_build_instruction(irb, scope, source_node); instruction->operand = operand; instruction->result_loc_cast = result_loc_cast; @@ -3356,10 +4190,10 @@ static IrInstruction *ir_build_implicit_cast(IrBuilder *irb, Scope *scope, AstNo return &instruction->base; } -static IrInstruction *ir_build_bit_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *operand, ResultLocBitCast *result_loc_bit_cast) +static IrInstSrc *ir_build_bit_cast_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *operand, ResultLocBitCast *result_loc_bit_cast) { - IrInstructionBitCastSrc *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcBitCast *instruction = ir_build_instruction(irb, scope, source_node); instruction->operand = operand; instruction->result_loc_bit_cast = result_loc_bit_cast; @@ -3368,36 +4202,81 @@ static IrInstruction *ir_build_bit_cast_src(IrBuilder *irb, Scope *scope, AstNod return &instruction->base; } -static IrInstruction *ir_build_bit_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction, - IrInstruction *operand, ZigType *ty) +static IrInstGen *ir_build_bit_cast_gen(IrAnalyze *ira, IrInst *source_instruction, + IrInstGen *operand, ZigType *ty) { - IrInstructionBitCastGen *instruction = ir_build_instruction( + IrInstGenBitCast *instruction = ir_build_inst_gen( &ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->base.value->type = ty; instruction->operand = operand; - ir_ref_instruction(operand, ira->new_irb.current_basic_block); + ir_ref_inst_gen(operand, ira->new_irb.current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_widen_or_shorten(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *target) +static IrInstGen *ir_build_widen_or_shorten(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstGen *target, + ZigType *result_type) { - IrInstructionWidenOrShorten *instruction = ir_build_instruction( - irb, scope, source_node); + IrInstGenWidenOrShorten *inst = ir_build_inst_gen(&ira->new_irb, scope, source_node); + inst->base.value->type = result_type; + inst->target = target; + + ir_ref_inst_gen(target, ira->new_irb.current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_int_to_ptr_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *dest_type, IrInstSrc *target) +{ + IrInstSrcIntToPtr *instruction = ir_build_instruction(irb, scope, source_node); + instruction->dest_type = dest_type; instruction->target = target; + ir_ref_instruction(dest_type, irb->current_basic_block); ir_ref_instruction(target, irb->current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_int_to_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *dest_type, IrInstruction *target) +static IrInstGen *ir_build_int_to_ptr_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, + IrInstGen *target, ZigType *ptr_type) { - IrInstructionIntToPtr *instruction = ir_build_instruction( - irb, scope, source_node); + IrInstGenIntToPtr *instruction = ir_build_inst_gen(&ira->new_irb, scope, source_node); + instruction->base.value->type = ptr_type; + instruction->target = target; + + ir_ref_inst_gen(target, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_ptr_to_int_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target) +{ + IrInstSrcPtrToInt *inst = ir_build_instruction(irb, scope, source_node); + inst->target = target; + + ir_ref_instruction(target, irb->current_basic_block); + + return &inst->base; +} + +static IrInstGen *ir_build_ptr_to_int_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *target) { + IrInstGenPtrToInt *inst = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); + inst->base.value->type = ira->codegen->builtin_types.entry_usize; + inst->target = target; + + ir_ref_inst_gen(target, ira->new_irb.current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_int_to_enum_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *dest_type, IrInstSrc *target) +{ + IrInstSrcIntToEnum *instruction = ir_build_instruction(irb, scope, source_node); instruction->dest_type = dest_type; instruction->target = target; @@ -3407,10 +4286,22 @@ static IrInstruction *ir_build_int_to_ptr(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_ptr_to_int(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *target) +static IrInstGen *ir_build_int_to_enum_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, + ZigType *dest_type, IrInstGen *target) { - IrInstructionPtrToInt *instruction = ir_build_instruction( + IrInstGenIntToEnum *instruction = ir_build_inst_gen(&ira->new_irb, scope, source_node); + instruction->base.value->type = dest_type; + instruction->target = target; + + ir_ref_inst_gen(target, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_enum_to_int(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target) +{ + IrInstSrcEnumToInt *instruction = ir_build_instruction( irb, scope, source_node); instruction->target = target; @@ -3419,26 +4310,33 @@ static IrInstruction *ir_build_ptr_to_int(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_int_to_enum(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *dest_type, IrInstruction *target) +static IrInstSrc *ir_build_int_to_err_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target) { - IrInstructionIntToEnum *instruction = ir_build_instruction( - irb, scope, source_node); - instruction->dest_type = dest_type; + IrInstSrcIntToErr *instruction = ir_build_instruction(irb, scope, source_node); instruction->target = target; - if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block); ir_ref_instruction(target, irb->current_basic_block); return &instruction->base; } - - -static IrInstruction *ir_build_enum_to_int(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *target) +static IrInstGen *ir_build_int_to_err_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstGen *target, + ZigType *wanted_type) { - IrInstructionEnumToInt *instruction = ir_build_instruction( + IrInstGenIntToErr *instruction = ir_build_inst_gen(&ira->new_irb, scope, source_node); + instruction->base.value->type = wanted_type; + instruction->target = target; + + ir_ref_inst_gen(target, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_err_to_int_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target) +{ + IrInstSrcErrToInt *instruction = ir_build_instruction( irb, scope, source_node); instruction->target = target; @@ -3447,40 +4345,29 @@ static IrInstruction *ir_build_enum_to_int(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_int_to_err(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *target) +static IrInstGen *ir_build_err_to_int_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstGen *target, + ZigType *wanted_type) { - IrInstructionIntToErr *instruction = ir_build_instruction( - irb, scope, source_node); + IrInstGenErrToInt *instruction = ir_build_inst_gen(&ira->new_irb, scope, source_node); + instruction->base.value->type = wanted_type; instruction->target = target; - ir_ref_instruction(target, irb->current_basic_block); + ir_ref_inst_gen(target, ira->new_irb.current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_err_to_int(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *target) +static IrInstSrc *ir_build_check_switch_prongs(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target_value, IrInstSrcCheckSwitchProngsRange *ranges, size_t range_count, + bool have_else_prong, bool have_underscore_prong) { - IrInstructionErrToInt *instruction = ir_build_instruction( - irb, scope, source_node); - instruction->target = target; - - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstruction *ir_build_check_switch_prongs(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *target_value, IrInstructionCheckSwitchProngsRange *ranges, size_t range_count, - bool have_else_prong) -{ - IrInstructionCheckSwitchProngs *instruction = ir_build_instruction( + IrInstSrcCheckSwitchProngs *instruction = ir_build_instruction( irb, scope, source_node); instruction->target_value = target_value; instruction->ranges = ranges; instruction->range_count = range_count; instruction->have_else_prong = have_else_prong; + instruction->have_underscore_prong = have_underscore_prong; ir_ref_instruction(target_value, irb->current_basic_block); for (size_t i = 0; i < range_count; i += 1) { @@ -3491,10 +4378,10 @@ static IrInstruction *ir_build_check_switch_prongs(IrBuilder *irb, Scope *scope, return &instruction->base; } -static IrInstruction *ir_build_check_statement_is_void(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction* statement_value) +static IrInstSrc *ir_build_check_statement_is_void(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc* statement_value) { - IrInstructionCheckStatementIsVoid *instruction = ir_build_instruction( + IrInstSrcCheckStatementIsVoid *instruction = ir_build_instruction( irb, scope, source_node); instruction->statement_value = statement_value; @@ -3503,11 +4390,10 @@ static IrInstruction *ir_build_check_statement_is_void(IrBuilder *irb, Scope *sc return &instruction->base; } -static IrInstruction *ir_build_type_name(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *type_value) +static IrInstSrc *ir_build_type_name(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *type_value) { - IrInstructionTypeName *instruction = ir_build_instruction( - irb, scope, source_node); + IrInstSrcTypeName *instruction = ir_build_instruction(irb, scope, source_node); instruction->type_value = type_value; ir_ref_instruction(type_value, irb->current_basic_block); @@ -3515,18 +4401,17 @@ static IrInstruction *ir_build_type_name(IrBuilder *irb, Scope *scope, AstNode * return &instruction->base; } -static IrInstruction *ir_build_decl_ref(IrBuilder *irb, Scope *scope, AstNode *source_node, Tld *tld, LVal lval) { - IrInstructionDeclRef *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_decl_ref(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Tld *tld, LVal lval) { + IrInstSrcDeclRef *instruction = ir_build_instruction(irb, scope, source_node); instruction->tld = tld; instruction->lval = lval; return &instruction->base; } -static IrInstruction *ir_build_panic(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *msg) { - IrInstructionPanic *instruction = ir_build_instruction(irb, scope, source_node); - instruction->base.value->special = ConstValSpecialStatic; - instruction->base.value->type = irb->codegen->builtin_types.entry_unreachable; +static IrInstSrc *ir_build_panic_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *msg) { + IrInstSrcPanic *instruction = ir_build_instruction(irb, scope, source_node); + instruction->base.is_noreturn = true; instruction->msg = msg; ir_ref_instruction(msg, irb->current_basic_block); @@ -3534,10 +4419,18 @@ static IrInstruction *ir_build_panic(IrBuilder *irb, Scope *scope, AstNode *sour return &instruction->base; } -static IrInstruction *ir_build_tag_name(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *target) -{ - IrInstructionTagName *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstGen *ir_build_panic_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *msg) { + IrInstGenPanic *instruction = ir_build_inst_noreturn(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->msg = msg; + + ir_ref_inst_gen(msg, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_tag_name_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *target) { + IrInstSrcTagName *instruction = ir_build_instruction(irb, scope, source_node); instruction->target = target; ir_ref_instruction(target, irb->current_basic_block); @@ -3545,10 +4438,23 @@ static IrInstruction *ir_build_tag_name(IrBuilder *irb, Scope *scope, AstNode *s return &instruction->base; } -static IrInstruction *ir_build_tag_type(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *target) +static IrInstGen *ir_build_tag_name_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *target, + ZigType *result_type) { - IrInstructionTagType *instruction = ir_build_instruction(irb, scope, source_node); + IrInstGenTagName *instruction = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->base.value->type = result_type; + instruction->target = target; + + ir_ref_inst_gen(target, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_tag_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *target) +{ + IrInstSrcTagType *instruction = ir_build_instruction(irb, scope, source_node); instruction->target = target; ir_ref_instruction(target, irb->current_basic_block); @@ -3556,27 +4462,40 @@ static IrInstruction *ir_build_tag_type(IrBuilder *irb, Scope *scope, AstNode *s return &instruction->base; } -static IrInstruction *ir_build_field_parent_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *type_value, IrInstruction *field_name, IrInstruction *field_ptr, TypeStructField *field) +static IrInstSrc *ir_build_field_parent_ptr_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *type_value, IrInstSrc *field_name, IrInstSrc *field_ptr) { - IrInstructionFieldParentPtr *instruction = ir_build_instruction( + IrInstSrcFieldParentPtr *inst = ir_build_instruction( irb, scope, source_node); - instruction->type_value = type_value; - instruction->field_name = field_name; - instruction->field_ptr = field_ptr; - instruction->field = field; + inst->type_value = type_value; + inst->field_name = field_name; + inst->field_ptr = field_ptr; ir_ref_instruction(type_value, irb->current_basic_block); ir_ref_instruction(field_name, irb->current_basic_block); ir_ref_instruction(field_ptr, irb->current_basic_block); - return &instruction->base; + return &inst->base; } -static IrInstruction *ir_build_byte_offset_of(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *type_value, IrInstruction *field_name) +static IrInstGen *ir_build_field_parent_ptr_gen(IrAnalyze *ira, IrInst *source_instr, + IrInstGen *field_ptr, TypeStructField *field, ZigType *result_type) { - IrInstructionByteOffsetOf *instruction = ir_build_instruction(irb, scope, source_node); + IrInstGenFieldParentPtr *inst = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + inst->base.value->type = result_type; + inst->field_ptr = field_ptr; + inst->field = field; + + ir_ref_inst_gen(field_ptr, ira->new_irb.current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_byte_offset_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *type_value, IrInstSrc *field_name) +{ + IrInstSrcByteOffsetOf *instruction = ir_build_instruction(irb, scope, source_node); instruction->type_value = type_value; instruction->field_name = field_name; @@ -3586,10 +4505,10 @@ static IrInstruction *ir_build_byte_offset_of(IrBuilder *irb, Scope *scope, AstN return &instruction->base; } -static IrInstruction *ir_build_bit_offset_of(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *type_value, IrInstruction *field_name) +static IrInstSrc *ir_build_bit_offset_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *type_value, IrInstSrc *field_name) { - IrInstructionBitOffsetOf *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcBitOffsetOf *instruction = ir_build_instruction(irb, scope, source_node); instruction->type_value = type_value; instruction->field_name = field_name; @@ -3599,9 +4518,8 @@ static IrInstruction *ir_build_bit_offset_of(IrBuilder *irb, Scope *scope, AstNo return &instruction->base; } -static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *type_value) { - IrInstructionTypeInfo *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_type_info(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_value) { + IrInstSrcTypeInfo *instruction = ir_build_instruction(irb, scope, source_node); instruction->type_value = type_value; ir_ref_instruction(type_value, irb->current_basic_block); @@ -3609,8 +4527,8 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode * return &instruction->base; } -static IrInstruction *ir_build_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_info) { - IrInstructionType *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_info) { + IrInstSrcType *instruction = ir_build_instruction(irb, scope, source_node); instruction->type_info = type_info; ir_ref_instruction(type_info, irb->current_basic_block); @@ -3618,10 +4536,8 @@ static IrInstruction *ir_build_type(IrBuilder *irb, Scope *scope, AstNode *sourc return &instruction->base; } -static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *type_value) -{ - IrInstructionTypeId *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_type_id(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_value) { + IrInstSrcTypeId *instruction = ir_build_instruction(irb, scope, source_node); instruction->type_value = type_value; ir_ref_instruction(type_value, irb->current_basic_block); @@ -3629,10 +4545,10 @@ static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *so return &instruction->base; } -static IrInstruction *ir_build_set_eval_branch_quota(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *new_quota) +static IrInstSrc *ir_build_set_eval_branch_quota(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *new_quota) { - IrInstructionSetEvalBranchQuota *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSetEvalBranchQuota *instruction = ir_build_instruction(irb, scope, source_node); instruction->new_quota = new_quota; ir_ref_instruction(new_quota, irb->current_basic_block); @@ -3640,23 +4556,35 @@ static IrInstruction *ir_build_set_eval_branch_quota(IrBuilder *irb, Scope *scop return &instruction->base; } -static IrInstruction *ir_build_align_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *align_bytes, IrInstruction *target) +static IrInstSrc *ir_build_align_cast_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *align_bytes, IrInstSrc *target) { - IrInstructionAlignCast *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcAlignCast *instruction = ir_build_instruction(irb, scope, source_node); instruction->align_bytes = align_bytes; instruction->target = target; - if (align_bytes) ir_ref_instruction(align_bytes, irb->current_basic_block); + ir_ref_instruction(align_bytes, irb->current_basic_block); ir_ref_instruction(target, irb->current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_resolve_result(IrBuilder *irb, Scope *scope, AstNode *source_node, - ResultLoc *result_loc, IrInstruction *ty) +static IrInstGen *ir_build_align_cast_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstGen *target, + ZigType *result_type) { - IrInstructionResolveResult *instruction = ir_build_instruction(irb, scope, source_node); + IrInstGenAlignCast *instruction = ir_build_inst_gen(&ira->new_irb, scope, source_node); + instruction->base.value->type = result_type; + instruction->target = target; + + ir_ref_inst_gen(target, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_resolve_result(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + ResultLoc *result_loc, IrInstSrc *ty) +{ + IrInstSrcResolveResult *instruction = ir_build_instruction(irb, scope, source_node); instruction->result_loc = result_loc; instruction->ty = ty; @@ -3665,26 +4593,26 @@ static IrInstruction *ir_build_resolve_result(IrBuilder *irb, Scope *scope, AstN return &instruction->base; } -static IrInstruction *ir_build_reset_result(IrBuilder *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_build_reset_result(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ResultLoc *result_loc) { - IrInstructionResetResult *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcResetResult *instruction = ir_build_instruction(irb, scope, source_node); instruction->result_loc = result_loc; instruction->base.is_gen = true; return &instruction->base; } -static IrInstruction *ir_build_opaque_type(IrBuilder *irb, Scope *scope, AstNode *source_node) { - IrInstructionOpaqueType *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_opaque_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcOpaqueType *instruction = ir_build_instruction(irb, scope, source_node); return &instruction->base; } -static IrInstruction *ir_build_set_align_stack(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *align_bytes) +static IrInstSrc *ir_build_set_align_stack(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *align_bytes) { - IrInstructionSetAlignStack *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcSetAlignStack *instruction = ir_build_instruction(irb, scope, source_node); instruction->align_bytes = align_bytes; ir_ref_instruction(align_bytes, irb->current_basic_block); @@ -3692,10 +4620,10 @@ static IrInstruction *ir_build_set_align_stack(IrBuilder *irb, Scope *scope, Ast return &instruction->base; } -static IrInstruction *ir_build_arg_type(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *fn_type, IrInstruction *arg_index, bool allow_var) +static IrInstSrc *ir_build_arg_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *fn_type, IrInstSrc *arg_index, bool allow_var) { - IrInstructionArgType *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcArgType *instruction = ir_build_instruction(irb, scope, source_node); instruction->fn_type = fn_type; instruction->arg_index = arg_index; instruction->allow_var = allow_var; @@ -3706,17 +4634,29 @@ static IrInstruction *ir_build_arg_type(IrBuilder *irb, Scope *scope, AstNode *s return &instruction->base; } -static IrInstruction *ir_build_error_return_trace(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstructionErrorReturnTrace::Optional optional) { - IrInstructionErrorReturnTrace *instruction = ir_build_instruction(irb, scope, source_node); - instruction->optional = optional; +static IrInstSrc *ir_build_error_return_trace_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstErrorReturnTraceOptional optional) +{ + IrInstSrcErrorReturnTrace *inst = ir_build_instruction(irb, scope, source_node); + inst->optional = optional; - return &instruction->base; + return &inst->base; } -static IrInstruction *ir_build_error_union(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *err_set, IrInstruction *payload) +static IrInstGen *ir_build_error_return_trace_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, + IrInstErrorReturnTraceOptional optional, ZigType *result_type) { - IrInstructionErrorUnion *instruction = ir_build_instruction(irb, scope, source_node); + IrInstGenErrorReturnTrace *inst = ir_build_inst_gen(&ira->new_irb, scope, source_node); + inst->base.value->type = result_type; + inst->optional = optional; + + return &inst->base; +} + +static IrInstSrc *ir_build_error_union(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *err_set, IrInstSrc *payload) +{ + IrInstSrcErrorUnion *instruction = ir_build_instruction(irb, scope, source_node); instruction->err_set = err_set; instruction->payload = payload; @@ -3726,85 +4666,130 @@ static IrInstruction *ir_build_error_union(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_atomic_rmw(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *operand_type, IrInstruction *ptr, IrInstruction *op, IrInstruction *operand, - IrInstruction *ordering, AtomicRmwOp resolved_op, AtomicOrder resolved_ordering) +static IrInstSrc *ir_build_atomic_rmw_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *operand_type, IrInstSrc *ptr, IrInstSrc *op, IrInstSrc *operand, + IrInstSrc *ordering) { - IrInstructionAtomicRmw *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcAtomicRmw *instruction = ir_build_instruction(irb, scope, source_node); instruction->operand_type = operand_type; instruction->ptr = ptr; instruction->op = op; instruction->operand = operand; instruction->ordering = ordering; - instruction->resolved_op = resolved_op; - instruction->resolved_ordering = resolved_ordering; - if (operand_type != nullptr) ir_ref_instruction(operand_type, irb->current_basic_block); + ir_ref_instruction(operand_type, irb->current_basic_block); ir_ref_instruction(ptr, irb->current_basic_block); - if (op != nullptr) ir_ref_instruction(op, irb->current_basic_block); + ir_ref_instruction(op, irb->current_basic_block); ir_ref_instruction(operand, irb->current_basic_block); - if (ordering != nullptr) ir_ref_instruction(ordering, irb->current_basic_block); + ir_ref_instruction(ordering, irb->current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_atomic_load(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *operand_type, IrInstruction *ptr, - IrInstruction *ordering, AtomicOrder resolved_ordering) +static IrInstGen *ir_build_atomic_rmw_gen(IrAnalyze *ira, IrInst *source_instr, + IrInstGen *ptr, IrInstGen *operand, AtomicRmwOp op, AtomicOrder ordering, ZigType *operand_type) { - IrInstructionAtomicLoad *instruction = ir_build_instruction(irb, scope, source_node); + IrInstGenAtomicRmw *instruction = ir_build_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); + instruction->base.value->type = operand_type; + instruction->ptr = ptr; + instruction->op = op; + instruction->operand = operand; + instruction->ordering = ordering; + + ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block); + ir_ref_inst_gen(operand, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_atomic_load_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *operand_type, IrInstSrc *ptr, IrInstSrc *ordering) +{ + IrInstSrcAtomicLoad *instruction = ir_build_instruction(irb, scope, source_node); instruction->operand_type = operand_type; instruction->ptr = ptr; instruction->ordering = ordering; - instruction->resolved_ordering = resolved_ordering; - if (operand_type != nullptr) ir_ref_instruction(operand_type, irb->current_basic_block); + ir_ref_instruction(operand_type, irb->current_basic_block); ir_ref_instruction(ptr, irb->current_basic_block); - if (ordering != nullptr) ir_ref_instruction(ordering, irb->current_basic_block); + ir_ref_instruction(ordering, irb->current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_atomic_store(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *operand_type, IrInstruction *ptr, IrInstruction *value, - IrInstruction *ordering, AtomicOrder resolved_ordering) +static IrInstGen *ir_build_atomic_load_gen(IrAnalyze *ira, IrInst *source_instr, + IrInstGen *ptr, AtomicOrder ordering, ZigType *operand_type) { - IrInstructionAtomicStore *instruction = ir_build_instruction(irb, scope, source_node); + IrInstGenAtomicLoad *instruction = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->base.value->type = operand_type; + instruction->ptr = ptr; + instruction->ordering = ordering; + + ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_atomic_store_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *operand_type, IrInstSrc *ptr, IrInstSrc *value, IrInstSrc *ordering) +{ + IrInstSrcAtomicStore *instruction = ir_build_instruction(irb, scope, source_node); instruction->operand_type = operand_type; instruction->ptr = ptr; instruction->value = value; instruction->ordering = ordering; - instruction->resolved_ordering = resolved_ordering; - if (operand_type != nullptr) ir_ref_instruction(operand_type, irb->current_basic_block); + ir_ref_instruction(operand_type, irb->current_basic_block); ir_ref_instruction(ptr, irb->current_basic_block); ir_ref_instruction(value, irb->current_basic_block); - if (ordering != nullptr) ir_ref_instruction(ordering, irb->current_basic_block); + ir_ref_instruction(ordering, irb->current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_save_err_ret_addr(IrBuilder *irb, Scope *scope, AstNode *source_node) { - IrInstructionSaveErrRetAddr *instruction = ir_build_instruction(irb, scope, source_node); - return &instruction->base; -} - -static IrInstruction *ir_build_add_implicit_return_type(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *value, ResultLocReturn *result_loc_ret) +static IrInstGen *ir_build_atomic_store_gen(IrAnalyze *ira, IrInst *source_instr, + IrInstGen *ptr, IrInstGen *value, AtomicOrder ordering) { - IrInstructionAddImplicitReturnType *instruction = ir_build_instruction(irb, scope, source_node); + IrInstGenAtomicStore *instruction = ir_build_inst_void(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->ptr = ptr; instruction->value = value; - instruction->result_loc_ret = result_loc_ret; + instruction->ordering = ordering; + + ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block); + ir_ref_inst_gen(value, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_save_err_ret_addr_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + IrInstSrcSaveErrRetAddr *inst = ir_build_instruction(irb, scope, source_node); + return &inst->base; +} + +static IrInstGen *ir_build_save_err_ret_addr_gen(IrAnalyze *ira, IrInst *source_instr) { + IrInstGenSaveErrRetAddr *inst = ir_build_inst_void(&ira->new_irb, + source_instr->scope, source_instr->source_node); + return &inst->base; +} + +static IrInstSrc *ir_build_add_implicit_return_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *value, ResultLocReturn *result_loc_ret) +{ + IrInstSrcAddImplicitReturnType *inst = ir_build_instruction(irb, scope, source_node); + inst->value = value; + inst->result_loc_ret = result_loc_ret; ir_ref_instruction(value, irb->current_basic_block); - return &instruction->base; + return &inst->base; } -static IrInstruction *ir_build_has_decl(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *container, IrInstruction *name) +static IrInstSrc *ir_build_has_decl(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *container, IrInstSrc *name) { - IrInstructionHasDecl *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcHasDecl *instruction = ir_build_instruction(irb, scope, source_node); instruction->container = container; instruction->name = name; @@ -3814,17 +4799,15 @@ static IrInstruction *ir_build_has_decl(IrBuilder *irb, Scope *scope, AstNode *s return &instruction->base; } -static IrInstruction *ir_build_undeclared_identifier(IrBuilder *irb, Scope *scope, AstNode *source_node, - Buf *name) -{ - IrInstructionUndeclaredIdent *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_undeclared_identifier(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *name) { + IrInstSrcUndeclaredIdent *instruction = ir_build_instruction(irb, scope, source_node); instruction->name = name; return &instruction->base; } -static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) { - IrInstructionCheckRuntimeScope *instruction = ir_build_instruction(irb, scope, source_node); +static IrInstSrc *ir_build_check_runtime_scope(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *scope_is_comptime, IrInstSrc *is_comptime) { + IrInstSrcCheckRuntimeScope *instruction = ir_build_instruction(irb, scope, source_node); instruction->scope_is_comptime = scope_is_comptime; instruction->is_comptime = is_comptime; @@ -3834,10 +4817,10 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, return &instruction->base; } -static IrInstruction *ir_build_union_init_named_field(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *union_type, IrInstruction *field_name, IrInstruction *field_result_loc, IrInstruction *result_loc) +static IrInstSrc *ir_build_union_init_named_field(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *union_type, IrInstSrc *field_name, IrInstSrc *field_result_loc, IrInstSrc *result_loc) { - IrInstructionUnionInitNamedField *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcUnionInitNamedField *instruction = ir_build_instruction(irb, scope, source_node); instruction->union_type = union_type; instruction->field_name = field_name; instruction->field_result_loc = field_result_loc; @@ -3852,79 +4835,79 @@ static IrInstruction *ir_build_union_init_named_field(IrBuilder *irb, Scope *sco } -static IrInstruction *ir_build_vector_to_array(IrAnalyze *ira, IrInstruction *source_instruction, - ZigType *result_type, IrInstruction *vector, IrInstruction *result_loc) +static IrInstGen *ir_build_vector_to_array(IrAnalyze *ira, IrInst *source_instruction, + ZigType *result_type, IrInstGen *vector, IrInstGen *result_loc) { - IrInstructionVectorToArray *instruction = ir_build_instruction(&ira->new_irb, + IrInstGenVectorToArray *instruction = ir_build_inst_gen(&ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->base.value->type = result_type; instruction->vector = vector; instruction->result_loc = result_loc; - ir_ref_instruction(vector, ira->new_irb.current_basic_block); - ir_ref_instruction(result_loc, ira->new_irb.current_basic_block); + ir_ref_inst_gen(vector, ira->new_irb.current_basic_block); + ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruction *source_instruction, - ZigType *result_type, IrInstruction *operand, IrInstruction *result_loc) +static IrInstGen *ir_build_ptr_of_array_to_slice(IrAnalyze *ira, IrInst *source_instruction, + ZigType *result_type, IrInstGen *operand, IrInstGen *result_loc) { - IrInstructionPtrOfArrayToSlice *instruction = ir_build_instruction(&ira->new_irb, + IrInstGenPtrOfArrayToSlice *instruction = ir_build_inst_gen(&ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->base.value->type = result_type; instruction->operand = operand; instruction->result_loc = result_loc; - ir_ref_instruction(operand, ira->new_irb.current_basic_block); - ir_ref_instruction(result_loc, ira->new_irb.current_basic_block); + ir_ref_inst_gen(operand, ira->new_irb.current_basic_block); + ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_array_to_vector(IrAnalyze *ira, IrInstruction *source_instruction, - IrInstruction *array, ZigType *result_type) +static IrInstGen *ir_build_array_to_vector(IrAnalyze *ira, IrInst *source_instruction, + IrInstGen *array, ZigType *result_type) { - IrInstructionArrayToVector *instruction = ir_build_instruction(&ira->new_irb, + IrInstGenArrayToVector *instruction = ir_build_inst_gen(&ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->base.value->type = result_type; instruction->array = array; - ir_ref_instruction(array, ira->new_irb.current_basic_block); + ir_ref_inst_gen(array, ira->new_irb.current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_assert_zero(IrAnalyze *ira, IrInstruction *source_instruction, - IrInstruction *target) +static IrInstGen *ir_build_assert_zero(IrAnalyze *ira, IrInst *source_instruction, + IrInstGen *target) { - IrInstructionAssertZero *instruction = ir_build_instruction(&ira->new_irb, + IrInstGenAssertZero *instruction = ir_build_inst_gen(&ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->base.value->type = ira->codegen->builtin_types.entry_void; instruction->target = target; - ir_ref_instruction(target, ira->new_irb.current_basic_block); + ir_ref_inst_gen(target, ira->new_irb.current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_assert_non_null(IrAnalyze *ira, IrInstruction *source_instruction, - IrInstruction *target) +static IrInstGen *ir_build_assert_non_null(IrAnalyze *ira, IrInst *source_instruction, + IrInstGen *target) { - IrInstructionAssertNonNull *instruction = ir_build_instruction(&ira->new_irb, + IrInstGenAssertNonNull *instruction = ir_build_inst_gen(&ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->base.value->type = ira->codegen->builtin_types.entry_void; instruction->target = target; - ir_ref_instruction(target, ira->new_irb.current_basic_block); + ir_ref_inst_gen(target, ira->new_irb.current_basic_block); return &instruction->base; } -static IrInstruction *ir_build_alloca_src(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *align, const char *name_hint, IrInstruction *is_comptime) +static IrInstSrc *ir_build_alloca_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *align, const char *name_hint, IrInstSrc *is_comptime) { - IrInstructionAllocaSrc *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcAlloca *instruction = ir_build_instruction(irb, scope, source_node); instruction->base.is_gen = true; instruction->align = align; instruction->name_hint = name_hint; @@ -3936,10 +4919,10 @@ static IrInstruction *ir_build_alloca_src(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstructionAllocaGen *ir_build_alloca_gen(IrAnalyze *ira, IrInstruction *source_instruction, +static IrInstGenAlloca *ir_build_alloca_gen(IrAnalyze *ira, IrInst *source_instruction, uint32_t align, const char *name_hint) { - IrInstructionAllocaGen *instruction = ir_create_instruction(&ira->new_irb, + IrInstGenAlloca *instruction = ir_create_inst_gen(&ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->align = align; instruction->name_hint = name_hint; @@ -3947,10 +4930,10 @@ static IrInstructionAllocaGen *ir_build_alloca_gen(IrAnalyze *ira, IrInstruction return instruction; } -static IrInstruction *ir_build_end_expr(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *value, ResultLoc *result_loc) +static IrInstSrc *ir_build_end_expr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *value, ResultLoc *result_loc) { - IrInstructionEndExpr *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcEndExpr *instruction = ir_build_instruction(irb, scope, source_node); instruction->base.is_gen = true; instruction->value = value; instruction->result_loc = result_loc; @@ -3960,29 +4943,41 @@ static IrInstruction *ir_build_end_expr(IrBuilder *irb, Scope *scope, AstNode *s return &instruction->base; } -static IrInstructionSuspendBegin *ir_build_suspend_begin(IrBuilder *irb, Scope *scope, AstNode *source_node) { - IrInstructionSuspendBegin *instruction = ir_build_instruction(irb, scope, source_node); - instruction->base.value->type = irb->codegen->builtin_types.entry_void; - - return instruction; +static IrInstSrcSuspendBegin *ir_build_suspend_begin_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { + return ir_build_instruction(irb, scope, source_node); } -static IrInstruction *ir_build_suspend_finish(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstructionSuspendBegin *begin) +static IrInstGen *ir_build_suspend_begin_gen(IrAnalyze *ira, IrInst *source_instr) { + IrInstGenSuspendBegin *inst = ir_build_inst_void(&ira->new_irb, + source_instr->scope, source_instr->source_node); + return &inst->base; +} + +static IrInstSrc *ir_build_suspend_finish_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrcSuspendBegin *begin) { - IrInstructionSuspendFinish *instruction = ir_build_instruction(irb, scope, source_node); - instruction->base.value->type = irb->codegen->builtin_types.entry_void; - instruction->begin = begin; + IrInstSrcSuspendFinish *inst = ir_build_instruction(irb, scope, source_node); + inst->begin = begin; ir_ref_instruction(&begin->base, irb->current_basic_block); - return &instruction->base; + return &inst->base; } -static IrInstruction *ir_build_await_src(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *frame, ResultLoc *result_loc) +static IrInstGen *ir_build_suspend_finish_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGenSuspendBegin *begin) { + IrInstGenSuspendFinish *inst = ir_build_inst_void(&ira->new_irb, + source_instr->scope, source_instr->source_node); + inst->begin = begin; + + ir_ref_inst_gen(&begin->base, ira->new_irb.current_basic_block); + + return &inst->base; +} + +static IrInstSrc *ir_build_await_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *frame, ResultLoc *result_loc) { - IrInstructionAwaitSrc *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcAwait *instruction = ir_build_instruction(irb, scope, source_node); instruction->frame = frame; instruction->result_loc = result_loc; @@ -3991,24 +4986,23 @@ static IrInstruction *ir_build_await_src(IrBuilder *irb, Scope *scope, AstNode * return &instruction->base; } -static IrInstructionAwaitGen *ir_build_await_gen(IrAnalyze *ira, IrInstruction *source_instruction, - IrInstruction *frame, ZigType *result_type, IrInstruction *result_loc) +static IrInstGenAwait *ir_build_await_gen(IrAnalyze *ira, IrInst *source_instruction, + IrInstGen *frame, ZigType *result_type, IrInstGen *result_loc) { - IrInstructionAwaitGen *instruction = ir_build_instruction(&ira->new_irb, + IrInstGenAwait *instruction = ir_build_inst_gen(&ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->base.value->type = result_type; instruction->frame = frame; instruction->result_loc = result_loc; - ir_ref_instruction(frame, ira->new_irb.current_basic_block); - if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block); + ir_ref_inst_gen(frame, ira->new_irb.current_basic_block); + if (result_loc != nullptr) ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block); return instruction; } -static IrInstruction *ir_build_resume(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *frame) { - IrInstructionResume *instruction = ir_build_instruction(irb, scope, source_node); - instruction->base.value->type = irb->codegen->builtin_types.entry_void; +static IrInstSrc *ir_build_resume_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *frame) { + IrInstSrcResume *instruction = ir_build_instruction(irb, scope, source_node); instruction->frame = frame; ir_ref_instruction(frame, irb->current_basic_block); @@ -4016,12 +5010,20 @@ static IrInstruction *ir_build_resume(IrBuilder *irb, Scope *scope, AstNode *sou return &instruction->base; } -static IrInstructionSpillBegin *ir_build_spill_begin(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *operand, SpillId spill_id) +static IrInstGen *ir_build_resume_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *frame) { + IrInstGenResume *instruction = ir_build_inst_void(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->frame = frame; + + ir_ref_inst_gen(frame, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrcSpillBegin *ir_build_spill_begin_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *operand, SpillId spill_id) { - IrInstructionSpillBegin *instruction = ir_build_instruction(irb, scope, source_node); - instruction->base.value->special = ConstValSpecialStatic; - instruction->base.value->type = irb->codegen->builtin_types.entry_void; + IrInstSrcSpillBegin *instruction = ir_build_instruction(irb, scope, source_node); instruction->operand = operand; instruction->spill_id = spill_id; @@ -4030,10 +5032,23 @@ static IrInstructionSpillBegin *ir_build_spill_begin(IrBuilder *irb, Scope *scop return instruction; } -static IrInstruction *ir_build_spill_end(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstructionSpillBegin *begin) +static IrInstGen *ir_build_spill_begin_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *operand, + SpillId spill_id) { - IrInstructionSpillEnd *instruction = ir_build_instruction(irb, scope, source_node); + IrInstGenSpillBegin *instruction = ir_build_inst_void(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->operand = operand; + instruction->spill_id = spill_id; + + ir_ref_inst_gen(operand, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstSrc *ir_build_spill_end_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrcSpillBegin *begin) +{ + IrInstSrcSpillEnd *instruction = ir_build_instruction(irb, scope, source_node); instruction->begin = begin; ir_ref_instruction(&begin->base, irb->current_basic_block); @@ -4041,22 +5056,35 @@ static IrInstruction *ir_build_spill_end(IrBuilder *irb, Scope *scope, AstNode * return &instruction->base; } -static IrInstruction *ir_build_vector_extract_elem(IrAnalyze *ira, IrInstruction *source_instruction, - IrInstruction *vector, IrInstruction *index) +static IrInstGen *ir_build_spill_end_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGenSpillBegin *begin, + ZigType *result_type) { - IrInstructionVectorExtractElem *instruction = ir_build_instruction( + IrInstGenSpillEnd *instruction = ir_build_inst_gen(&ira->new_irb, + source_instr->scope, source_instr->source_node); + instruction->base.value->type = result_type; + instruction->begin = begin; + + ir_ref_inst_gen(&begin->base, ira->new_irb.current_basic_block); + + return &instruction->base; +} + +static IrInstGen *ir_build_vector_extract_elem(IrAnalyze *ira, IrInst *source_instruction, + IrInstGen *vector, IrInstGen *index) +{ + IrInstGenVectorExtractElem *instruction = ir_build_inst_gen( &ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->base.value->type = vector->value->type->data.vector.elem_type; instruction->vector = vector; instruction->index = index; - ir_ref_instruction(vector, ira->new_irb.current_basic_block); - ir_ref_instruction(index, ira->new_irb.current_basic_block); + ir_ref_inst_gen(vector, ira->new_irb.current_basic_block); + ir_ref_inst_gen(index, ira->new_irb.current_basic_block); return &instruction->base; } -static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { +static void ir_count_defers(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { results[ReturnKindUnconditional] = 0; results[ReturnKindError] = 0; @@ -4093,12 +5121,12 @@ static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_sco } } -static IrInstruction *ir_mark_gen(IrInstruction *instruction) { +static IrInstSrc *ir_mark_gen(IrInstSrc *instruction) { instruction->is_gen = true; return instruction; } -static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, bool gen_error_defers) { +static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, bool gen_error_defers) { Scope *scope = inner_scope; bool is_noreturn = false; while (scope != outer_scope) { @@ -4115,11 +5143,9 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o { AstNode *defer_expr_node = defer_node->data.defer.expr; Scope *defer_expr_scope = defer_node->data.defer.expr_scope; - IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope); - if (defer_expr_value != irb->codegen->invalid_instruction) { - if (defer_expr_value->value->type != nullptr && - defer_expr_value->value->type->id == ZigTypeIdUnreachable) - { + IrInstSrc *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope); + if (defer_expr_value != irb->codegen->invalid_inst_src) { + if (defer_expr_value->is_noreturn) { is_noreturn = true; } else { ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, @@ -4151,13 +5177,17 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o return is_noreturn; } -static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) { +static void ir_set_cursor_at_end_gen(IrBuilderGen *irb, IrBasicBlockGen *basic_block) { assert(basic_block); - irb->current_basic_block = basic_block; } -static void ir_set_cursor_at_end_and_append_block(IrBuilder *irb, IrBasicBlock *basic_block) { +static void ir_set_cursor_at_end(IrBuilderSrc *irb, IrBasicBlockSrc *basic_block) { + assert(basic_block); + irb->current_basic_block = basic_block; +} + +static void ir_set_cursor_at_end_and_append_block(IrBuilderSrc *irb, IrBasicBlockSrc *basic_block) { basic_block->index = irb->exec->basic_block_list.length; irb->exec->basic_block_list.append(basic_block); ir_set_cursor_at_end(irb, basic_block); @@ -4187,7 +5217,7 @@ static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) { return nullptr; } -static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { +static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeReturnExpr); ScopeDeferExpr *scope_defer_expr = get_scope_defer_expr(scope); @@ -4196,7 +5226,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, add_node_error(irb->codegen, node, buf_sprintf("cannot return from defer expression")); scope_defer_expr->reported_err = true; } - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } Scope *outer_scope = irb->exec->begin_scope; @@ -4209,15 +5239,15 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, result_loc_ret->base.id = ResultLocIdReturn; ir_build_reset_result(irb, scope, node, &result_loc_ret->base); - IrInstruction *return_value; + IrInstSrc *return_value; if (expr_node) { // Temporarily set this so that if we return a type it gets the name of the function ZigFn *prev_name_fn = irb->exec->name_fn; irb->exec->name_fn = exec_fn_entry(irb->exec); return_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, &result_loc_ret->base); irb->exec->name_fn = prev_name_fn; - if (return_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + if (return_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; } else { return_value = ir_build_const_void(irb, scope, node); } @@ -4230,22 +5260,22 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, if (!have_err_defers && !irb->codegen->have_err_ret_tracing) { // only generate unconditional defers ir_gen_defers_for_block(irb, scope, outer_scope, false); - IrInstruction *result = ir_build_return(irb, scope, node, return_value); + IrInstSrc *result = ir_build_return_src(irb, scope, node, return_value); result_loc_ret->base.source_instruction = result; return result; } bool should_inline = ir_should_inline(irb->exec, scope); - IrBasicBlock *err_block = ir_create_basic_block(irb, scope, "ErrRetErr"); - IrBasicBlock *ok_block = ir_create_basic_block(irb, scope, "ErrRetOk"); + IrBasicBlockSrc *err_block = ir_create_basic_block(irb, scope, "ErrRetErr"); + IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, scope, "ErrRetOk"); if (!have_err_defers) { ir_gen_defers_for_block(irb, scope, outer_scope, false); } - IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, return_value, false, true); + IrInstSrc *is_err = ir_build_test_err_src(irb, scope, node, return_value, false, true); - IrInstruction *is_comptime; + IrInstSrc *is_comptime; if (should_inline) { is_comptime = ir_build_const_bool(irb, scope, node, should_inline); } else { @@ -4253,14 +5283,14 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, } ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err, err_block, ok_block, is_comptime)); - IrBasicBlock *ret_stmt_block = ir_create_basic_block(irb, scope, "RetStmt"); + IrBasicBlockSrc *ret_stmt_block = ir_create_basic_block(irb, scope, "RetStmt"); ir_set_cursor_at_end_and_append_block(irb, err_block); if (have_err_defers) { ir_gen_defers_for_block(irb, scope, outer_scope, true); } if (irb->codegen->have_err_ret_tracing && !should_inline) { - ir_build_save_err_ret_addr(irb, scope, node); + ir_build_save_err_ret_addr_src(irb, scope, node); } ir_build_br(irb, scope, node, ret_stmt_block, is_comptime); @@ -4271,21 +5301,21 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, ir_build_br(irb, scope, node, ret_stmt_block, is_comptime); ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block); - IrInstruction *result = ir_build_return(irb, scope, node, return_value); + IrInstSrc *result = ir_build_return_src(irb, scope, node, return_value); result_loc_ret->base.source_instruction = result; return result; } case ReturnKindError: { assert(expr_node); - IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); - if (err_union_ptr == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; - IrInstruction *is_err_val = ir_build_test_err_src(irb, scope, node, err_union_ptr, true, false); + IrInstSrc *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); + if (err_union_ptr == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + IrInstSrc *is_err_val = ir_build_test_err_src(irb, scope, node, err_union_ptr, true, false); - IrBasicBlock *return_block = ir_create_basic_block(irb, scope, "ErrRetReturn"); - IrBasicBlock *continue_block = ir_create_basic_block(irb, scope, "ErrRetContinue"); - IrInstruction *is_comptime; + IrBasicBlockSrc *return_block = ir_create_basic_block(irb, scope, "ErrRetReturn"); + IrBasicBlockSrc *continue_block = ir_create_basic_block(irb, scope, "ErrRetContinue"); + IrInstSrc *is_comptime; bool should_inline = ir_should_inline(irb->exec, scope); if (should_inline) { is_comptime = ir_build_const_bool(irb, scope, node, true); @@ -4295,10 +5325,10 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime)); ir_set_cursor_at_end_and_append_block(irb, return_block); - IrInstruction *err_val_ptr = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr); - IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr); + IrInstSrc *err_val_ptr = ir_build_unwrap_err_code_src(irb, scope, node, err_union_ptr); + IrInstSrc *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr); ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, err_val, nullptr)); - IrInstructionSpillBegin *spill_begin = ir_build_spill_begin(irb, scope, node, err_val, + IrInstSrcSpillBegin *spill_begin = ir_build_spill_begin_src(irb, scope, node, err_val, SpillIdRetErrCode); ResultLocReturn *result_loc_ret = allocate(1, "ResultLocReturn"); result_loc_ret->base.id = ResultLocIdReturn; @@ -4306,15 +5336,15 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, ir_build_end_expr(irb, scope, node, err_val, &result_loc_ret->base); if (!ir_gen_defers_for_block(irb, scope, outer_scope, true)) { if (irb->codegen->have_err_ret_tracing && !should_inline) { - ir_build_save_err_ret_addr(irb, scope, node); + ir_build_save_err_ret_addr_src(irb, scope, node); } - err_val = ir_build_spill_end(irb, scope, node, spill_begin); - IrInstruction *ret_inst = ir_build_return(irb, scope, node, err_val); + err_val = ir_build_spill_end_src(irb, scope, node, spill_begin); + IrInstSrc *ret_inst = ir_build_return_src(irb, scope, node, err_val); result_loc_ret->base.source_instruction = ret_inst; } ir_set_cursor_at_end_and_append_block(irb, continue_block); - IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, false, false); + IrInstSrc *unwrapped_ptr = ir_build_unwrap_err_payload_src(irb, scope, node, err_union_ptr, false, false); if (lval == LValPtr) return unwrapped_ptr; else @@ -4325,7 +5355,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, } static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_scope, - Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstruction *is_comptime, + Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime, bool skip_name_check) { ZigVar *variable_entry = allocate(1, "ZigVar"); @@ -4336,7 +5366,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s variable_entry->const_value = create_const_vals(1); if (is_comptime != nullptr) { - is_comptime->ref_count += 1; + is_comptime->base.ref_count += 1; } if (name) { @@ -4386,8 +5416,8 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s // Set name to nullptr to make the variable anonymous (not visible to programmer). // After you call this function var->child_scope has the variable in scope -static ZigVar *ir_create_var(IrBuilder *irb, AstNode *node, Scope *scope, Buf *name, - bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstruction *is_comptime) +static ZigVar *ir_create_var(IrBuilderSrc *irb, AstNode *node, Scope *scope, Buf *name, + bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime) { bool is_underscored = name ? buf_eql_str(name, "_") : false; ZigVar *var = create_local_var(irb->codegen, node, scope, @@ -4409,13 +5439,13 @@ static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) { return result; } -static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode *block_node, LVal lval, +static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *block_node, LVal lval, ResultLoc *result_loc) { assert(block_node->type == NodeTypeBlock); - ZigList incoming_values = {0}; - ZigList incoming_blocks = {0}; + ZigList incoming_values = {0}; + ZigList incoming_blocks = {0}; ScopeBlock *scope_block = create_block_scope(irb->codegen, block_node, parent_scope); @@ -4451,11 +5481,11 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode } bool is_continuation_unreachable = false; - IrInstruction *noreturn_return_value = nullptr; + IrInstSrc *noreturn_return_value = nullptr; for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) { AstNode *statement_node = block_node->data.block.statements.at(i); - IrInstruction *statement_value = ir_gen_node(irb, statement_node, child_scope); + IrInstSrc *statement_value = ir_gen_node(irb, statement_node, child_scope); is_continuation_unreachable = instr_is_unreachable(statement_value); if (is_continuation_unreachable) { // keep the last noreturn statement value around in case we need to return it @@ -4463,15 +5493,15 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode } // This logic must be kept in sync with // [STMT_EXPR_TEST_THING] <--- (search this token) - if (statement_node->type == NodeTypeDefer && statement_value != irb->codegen->invalid_instruction) { + if (statement_node->type == NodeTypeDefer && statement_value != irb->codegen->invalid_inst_src) { // defer starts a new scope child_scope = statement_node->data.defer.child_scope; assert(child_scope); - } else if (statement_value->id == IrInstructionIdDeclVarSrc) { + } else if (statement_value->id == IrInstSrcIdDeclVar) { // variable declarations start a new scope - IrInstructionDeclVarSrc *decl_var_instruction = (IrInstructionDeclVarSrc *)statement_value; + IrInstSrcDeclVar *decl_var_instruction = (IrInstSrcDeclVar *)statement_value; child_scope = decl_var_instruction->var->child_scope; - } else if (statement_value != irb->codegen->invalid_instruction && !is_continuation_unreachable) { + } else if (statement_value != irb->codegen->invalid_inst_src && !is_continuation_unreachable) { // this statement's value must be void ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, statement_node, statement_value)); } @@ -4487,12 +5517,12 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block; } ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block); - IrInstruction *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, + IrInstSrc *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, incoming_blocks.items, incoming_values.items, scope_block->peer_parent); return ir_expr_wrap(irb, parent_scope, phi, result_loc); } else { incoming_blocks.append(irb->current_basic_block); - IrInstruction *else_expr_result = ir_mark_gen(ir_build_const_void(irb, parent_scope, block_node)); + IrInstSrc *else_expr_result = ir_mark_gen(ir_build_const_void(irb, parent_scope, block_node)); if (scope_block->peer_parent != nullptr) { ResultLocPeer *peer_result = create_peer_result(scope_block->peer_parent); @@ -4512,15 +5542,15 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false); } - IrInstruction *result; + IrInstSrc *result; if (block_node->data.block.name != nullptr) { ir_mark_gen(ir_build_br(irb, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime)); ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block); - IrInstruction *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, + IrInstSrc *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, incoming_blocks.items, incoming_values.items, scope_block->peer_parent); result = ir_expr_wrap(irb, parent_scope, phi, result_loc); } else { - IrInstruction *void_inst = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node)); + IrInstSrc *void_inst = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node)); result = ir_lval_wrap(irb, parent_scope, void_inst, lval, result_loc); } if (!is_return_from_fn) @@ -4535,30 +5565,30 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode ir_build_reset_result(irb, parent_scope, block_node, &result_loc_ret->base); ir_mark_gen(ir_build_end_expr(irb, parent_scope, block_node, result, &result_loc_ret->base)); ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false); - return ir_mark_gen(ir_build_return(irb, child_scope, result->source_node, result)); + return ir_mark_gen(ir_build_return_src(irb, child_scope, result->base.source_node, result)); } -static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, Scope *scope, AstNode *node, IrBinOp op_id) { +static IrInstSrc *ir_gen_bin_op_id(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrBinOp op_id) { Scope *inner_scope = scope; if (op_id == IrBinOpArrayCat || op_id == IrBinOpArrayMult) { inner_scope = create_comptime_scope(irb->codegen, node, scope); } - IrInstruction *op1 = ir_gen_node(irb, node->data.bin_op_expr.op1, inner_scope); - IrInstruction *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, inner_scope); + IrInstSrc *op1 = ir_gen_node(irb, node->data.bin_op_expr.op1, inner_scope); + IrInstSrc *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, inner_scope); - if (op1 == irb->codegen->invalid_instruction || op2 == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + if (op1 == irb->codegen->invalid_inst_src || op2 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; return ir_build_bin_op(irb, scope, node, op_id, op1, op2, true); } -static IrInstruction *ir_gen_merge_err_sets(IrBuilder *irb, Scope *scope, AstNode *node) { - IrInstruction *op1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); - IrInstruction *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); +static IrInstSrc *ir_gen_merge_err_sets(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + IrInstSrc *op1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); + IrInstSrc *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); - if (op1 == irb->codegen->invalid_instruction || op2 == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + if (op1 == irb->codegen->invalid_inst_src || op2 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; // TODO only pass type_name when the || operator is the top level AST node in the var decl expr Buf bare_name = BUF_INIT; @@ -4567,10 +5597,10 @@ static IrInstruction *ir_gen_merge_err_sets(IrBuilder *irb, Scope *scope, AstNod return ir_build_merge_err_sets(irb, scope, node, op1, op2, type_name); } -static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node) { - IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr); - if (lvalue == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; +static IrInstSrc *ir_gen_assign(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + IrInstSrc *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr); + if (lvalue == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; ResultLocInstruction *result_loc_inst = allocate(1, "ResultLocInstruction"); result_loc_inst->base.id = ResultLocIdInstruction; @@ -4578,49 +5608,49 @@ static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node) ir_ref_instruction(lvalue, irb->current_basic_block); ir_build_reset_result(irb, scope, node, &result_loc_inst->base); - IrInstruction *rvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op2, scope, LValNone, + IrInstSrc *rvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op2, scope, LValNone, &result_loc_inst->base); - if (rvalue == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + if (rvalue == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; return ir_build_const_void(irb, scope, node); } -static IrInstruction *ir_gen_assign_merge_err_sets(IrBuilder *irb, Scope *scope, AstNode *node) { - IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr); - if (lvalue == irb->codegen->invalid_instruction) +static IrInstSrc *ir_gen_assign_merge_err_sets(IrBuilderSrc *irb, Scope *scope, AstNode *node) { + IrInstSrc *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr); + if (lvalue == irb->codegen->invalid_inst_src) return lvalue; - IrInstruction *op1 = ir_build_load_ptr(irb, scope, node->data.bin_op_expr.op1, lvalue); - IrInstruction *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); - if (op2 == irb->codegen->invalid_instruction) + IrInstSrc *op1 = ir_build_load_ptr(irb, scope, node->data.bin_op_expr.op1, lvalue); + IrInstSrc *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); + if (op2 == irb->codegen->invalid_inst_src) return op2; - IrInstruction *result = ir_build_merge_err_sets(irb, scope, node, op1, op2, nullptr); + IrInstSrc *result = ir_build_merge_err_sets(irb, scope, node, op1, op2, nullptr); ir_build_store_ptr(irb, scope, node, lvalue, result); return ir_build_const_void(irb, scope, node); } -static IrInstruction *ir_gen_assign_op(IrBuilder *irb, Scope *scope, AstNode *node, IrBinOp op_id) { - IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr); - if (lvalue == irb->codegen->invalid_instruction) +static IrInstSrc *ir_gen_assign_op(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrBinOp op_id) { + IrInstSrc *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr); + if (lvalue == irb->codegen->invalid_inst_src) return lvalue; - IrInstruction *op1 = ir_build_load_ptr(irb, scope, node->data.bin_op_expr.op1, lvalue); - IrInstruction *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); - if (op2 == irb->codegen->invalid_instruction) + IrInstSrc *op1 = ir_build_load_ptr(irb, scope, node->data.bin_op_expr.op1, lvalue); + IrInstSrc *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); + if (op2 == irb->codegen->invalid_inst_src) return op2; - IrInstruction *result = ir_build_bin_op(irb, scope, node, op_id, op1, op2, true); + IrInstSrc *result = ir_build_bin_op(irb, scope, node, op_id, op1, op2, true); ir_build_store_ptr(irb, scope, node, lvalue, result); return ir_build_const_void(irb, scope, node); } -static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_bool_or(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeBinOpExpr); - IrInstruction *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); - if (val1 == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; - IrBasicBlock *post_val1_block = irb->current_basic_block; + IrInstSrc *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); + if (val1 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + IrBasicBlockSrc *post_val1_block = irb->current_basic_block; - IrInstruction *is_comptime; + IrInstSrc *is_comptime; if (ir_should_inline(irb->exec, scope)) { is_comptime = ir_build_const_bool(irb, scope, node, true); } else { @@ -4628,41 +5658,41 @@ static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node } // block for when val1 == false - IrBasicBlock *false_block = ir_create_basic_block(irb, scope, "BoolOrFalse"); + IrBasicBlockSrc *false_block = ir_create_basic_block(irb, scope, "BoolOrFalse"); // block for when val1 == true (don't even evaluate the second part) - IrBasicBlock *true_block = ir_create_basic_block(irb, scope, "BoolOrTrue"); + IrBasicBlockSrc *true_block = ir_create_basic_block(irb, scope, "BoolOrTrue"); ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_comptime); ir_set_cursor_at_end_and_append_block(irb, false_block); - IrInstruction *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); - if (val2 == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; - IrBasicBlock *post_val2_block = irb->current_basic_block; + IrInstSrc *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); + if (val2 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + IrBasicBlockSrc *post_val2_block = irb->current_basic_block; ir_build_br(irb, scope, node, true_block, is_comptime); ir_set_cursor_at_end_and_append_block(irb, true_block); - IrInstruction **incoming_values = allocate(2, "IrInstruction *"); + IrInstSrc **incoming_values = allocate(2, "IrInstSrc *"); incoming_values[0] = val1; incoming_values[1] = val2; - IrBasicBlock **incoming_blocks = allocate(2, "IrBasicBlock *"); + IrBasicBlockSrc **incoming_blocks = allocate(2, "IrBasicBlockSrc *"); incoming_blocks[0] = post_val1_block; incoming_blocks[1] = post_val2_block; return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr); } -static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_bool_and(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeBinOpExpr); - IrInstruction *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); - if (val1 == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; - IrBasicBlock *post_val1_block = irb->current_basic_block; + IrInstSrc *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); + if (val1 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + IrBasicBlockSrc *post_val1_block = irb->current_basic_block; - IrInstruction *is_comptime; + IrInstSrc *is_comptime; if (ir_should_inline(irb->exec, scope)) { is_comptime = ir_build_const_bool(irb, scope, node, true); } else { @@ -4670,34 +5700,34 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod } // block for when val1 == true - IrBasicBlock *true_block = ir_create_basic_block(irb, scope, "BoolAndTrue"); + IrBasicBlockSrc *true_block = ir_create_basic_block(irb, scope, "BoolAndTrue"); // block for when val1 == false (don't even evaluate the second part) - IrBasicBlock *false_block = ir_create_basic_block(irb, scope, "BoolAndFalse"); + IrBasicBlockSrc *false_block = ir_create_basic_block(irb, scope, "BoolAndFalse"); ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_comptime); ir_set_cursor_at_end_and_append_block(irb, true_block); - IrInstruction *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); - if (val2 == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; - IrBasicBlock *post_val2_block = irb->current_basic_block; + IrInstSrc *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); + if (val2 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + IrBasicBlockSrc *post_val2_block = irb->current_basic_block; ir_build_br(irb, scope, node, false_block, is_comptime); ir_set_cursor_at_end_and_append_block(irb, false_block); - IrInstruction **incoming_values = allocate(2); + IrInstSrc **incoming_values = allocate(2); incoming_values[0] = val1; incoming_values[1] = val2; - IrBasicBlock **incoming_blocks = allocate(2, "IrBasicBlock *"); + IrBasicBlockSrc **incoming_blocks = allocate(2, "IrBasicBlockSrc *"); incoming_blocks[0] = post_val1_block; incoming_blocks[1] = post_val2_block; return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr); } -static ResultLocPeerParent *ir_build_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst, - IrBasicBlock *end_block, ResultLoc *parent, IrInstruction *is_comptime) +static ResultLocPeerParent *ir_build_result_peers(IrBuilderSrc *irb, IrInstSrc *cond_br_inst, + IrBasicBlockSrc *end_block, ResultLoc *parent, IrInstSrc *is_comptime) { ResultLocPeerParent *peer_parent = allocate(1); peer_parent->base.id = ResultLocIdPeerParent; @@ -4707,17 +5737,17 @@ static ResultLocPeerParent *ir_build_result_peers(IrBuilder *irb, IrInstruction peer_parent->is_comptime = is_comptime; peer_parent->parent = parent; - IrInstruction *popped_inst = irb->current_basic_block->instruction_list.pop(); - ir_assert(popped_inst == cond_br_inst, cond_br_inst); + IrInstSrc *popped_inst = irb->current_basic_block->instruction_list.pop(); + ir_assert(popped_inst == cond_br_inst, &cond_br_inst->base); - ir_build_reset_result(irb, cond_br_inst->scope, cond_br_inst->source_node, &peer_parent->base); + ir_build_reset_result(irb, cond_br_inst->base.scope, cond_br_inst->base.source_node, &peer_parent->base); irb->current_basic_block->instruction_list.append(popped_inst); return peer_parent; } -static ResultLocPeerParent *ir_build_binary_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst, - IrBasicBlock *else_block, IrBasicBlock *end_block, ResultLoc *parent, IrInstruction *is_comptime) +static ResultLocPeerParent *ir_build_binary_result_peers(IrBuilderSrc *irb, IrInstSrc *cond_br_inst, + IrBasicBlockSrc *else_block, IrBasicBlockSrc *end_block, ResultLoc *parent, IrInstSrc *is_comptime) { ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, parent, is_comptime); @@ -4730,7 +5760,7 @@ static ResultLocPeerParent *ir_build_binary_result_peers(IrBuilder *irb, IrInstr return peer_parent; } -static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_orelse(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeBinOpExpr); @@ -4738,73 +5768,73 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode AstNode *op1_node = node->data.bin_op_expr.op1; AstNode *op2_node = node->data.bin_op_expr.op2; - IrInstruction *maybe_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr, nullptr); - if (maybe_ptr == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *maybe_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr, nullptr); + if (maybe_ptr == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - IrInstruction *maybe_val = ir_build_load_ptr(irb, parent_scope, node, maybe_ptr); - IrInstruction *is_non_null = ir_build_test_nonnull(irb, parent_scope, node, maybe_val); + IrInstSrc *maybe_val = ir_build_load_ptr(irb, parent_scope, node, maybe_ptr); + IrInstSrc *is_non_null = ir_build_test_non_null_src(irb, parent_scope, node, maybe_val); - IrInstruction *is_comptime; + IrInstSrc *is_comptime; if (ir_should_inline(irb->exec, parent_scope)) { is_comptime = ir_build_const_bool(irb, parent_scope, node, true); } else { is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_non_null); } - IrBasicBlock *ok_block = ir_create_basic_block(irb, parent_scope, "OptionalNonNull"); - IrBasicBlock *null_block = ir_create_basic_block(irb, parent_scope, "OptionalNull"); - IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "OptionalEnd"); - IrInstruction *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_non_null, ok_block, null_block, is_comptime); + IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, parent_scope, "OptionalNonNull"); + IrBasicBlockSrc *null_block = ir_create_basic_block(irb, parent_scope, "OptionalNull"); + IrBasicBlockSrc *end_block = ir_create_basic_block(irb, parent_scope, "OptionalEnd"); + IrInstSrc *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_non_null, ok_block, null_block, is_comptime); ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, ok_block, end_block, result_loc, is_comptime); ir_set_cursor_at_end_and_append_block(irb, null_block); - IrInstruction *null_result = ir_gen_node_extra(irb, op2_node, parent_scope, LValNone, + IrInstSrc *null_result = ir_gen_node_extra(irb, op2_node, parent_scope, LValNone, &peer_parent->peers.at(0)->base); - if (null_result == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; - IrBasicBlock *after_null_block = irb->current_basic_block; + if (null_result == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + IrBasicBlockSrc *after_null_block = irb->current_basic_block; if (!instr_is_unreachable(null_result)) ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime)); ir_set_cursor_at_end_and_append_block(irb, ok_block); - IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false, false); - IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr); + IrInstSrc *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false, false); + IrInstSrc *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr); ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base); - IrBasicBlock *after_ok_block = irb->current_basic_block; + IrBasicBlockSrc *after_ok_block = irb->current_basic_block; ir_build_br(irb, parent_scope, node, end_block, is_comptime); ir_set_cursor_at_end_and_append_block(irb, end_block); - IrInstruction **incoming_values = allocate(2); + IrInstSrc **incoming_values = allocate(2); incoming_values[0] = null_result; incoming_values[1] = unwrapped_payload; - IrBasicBlock **incoming_blocks = allocate(2, "IrBasicBlock *"); + IrBasicBlockSrc **incoming_blocks = allocate(2, "IrBasicBlockSrc *"); incoming_blocks[0] = after_null_block; incoming_blocks[1] = after_ok_block; - IrInstruction *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); + IrInstSrc *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc); } -static IrInstruction *ir_gen_error_union(IrBuilder *irb, Scope *parent_scope, AstNode *node) { +static IrInstSrc *ir_gen_error_union(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeBinOpExpr); AstNode *op1_node = node->data.bin_op_expr.op1; AstNode *op2_node = node->data.bin_op_expr.op2; - IrInstruction *err_set = ir_gen_node(irb, op1_node, parent_scope); - if (err_set == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *err_set = ir_gen_node(irb, op1_node, parent_scope); + if (err_set == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - IrInstruction *payload = ir_gen_node(irb, op2_node, parent_scope); - if (payload == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *payload = ir_gen_node(irb, op2_node, parent_scope); + if (payload == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; return ir_build_error_union(irb, parent_scope, node, err_set, payload); } -static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { +static IrInstSrc *ir_gen_bin_op(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeBinOpExpr); BinOpType bin_op_type = node->data.bin_op_expr.bin_op; @@ -4897,30 +5927,30 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node, zig_unreachable(); } -static IrInstruction *ir_gen_int_lit(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_int_lit(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeIntLiteral); return ir_build_const_bigint(irb, scope, node, node->data.int_literal.bigint); } -static IrInstruction *ir_gen_float_lit(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_float_lit(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeFloatLiteral); if (node->data.float_literal.overflow) { add_node_error(irb->codegen, node, buf_sprintf("float literal out of range of any type")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } return ir_build_const_bigfloat(irb, scope, node, node->data.float_literal.bigfloat); } -static IrInstruction *ir_gen_char_lit(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_char_lit(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeCharLiteral); return ir_build_const_uint(irb, scope, node, node->data.char_literal.value); } -static IrInstruction *ir_gen_null_literal(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_null_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeNullLiteral); return ir_build_const_null(irb, scope, node); @@ -4938,11 +5968,11 @@ static void populate_invalid_variable_in_scope(CodeGen *g, Scope *scope, AstNode init_tld(&tld_var->base, TldIdVar, var_name, VisibModPub, node, &scope_decls->base); tld_var->base.resolution = TldResolutionInvalid; tld_var->var = add_variable(g, node, &scope_decls->base, var_name, false, - g->invalid_instruction->value, &tld_var->base, g->builtin_types.entry_invalid); + g->invalid_inst_gen->value, &tld_var->base, g->builtin_types.entry_invalid); scope_decls->decl_table.put(var_name, &tld_var->base); } -static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { +static IrInstSrc *ir_gen_symbol(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { Error err; assert(node->type == NodeTypeSymbol); @@ -4950,15 +5980,16 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, if (buf_eql_str(variable_name, "_")) { if (lval == LValPtr) { - IrInstructionConst *const_instruction = ir_build_instruction(irb, scope, node); - const_instruction->base.value->type = get_pointer_to_type(irb->codegen, + IrInstSrcConst *const_instruction = ir_build_instruction(irb, scope, node); + const_instruction->value = create_const_vals(1); + const_instruction->value->type = get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_void, false); - const_instruction->base.value->special = ConstValSpecialStatic; - const_instruction->base.value->data.x_ptr.special = ConstPtrSpecialDiscard; + const_instruction->value->special = ConstValSpecialStatic; + const_instruction->value->data.x_ptr.special = ConstPtrSpecialDiscard; return &const_instruction->base; } else { add_node_error(irb->codegen, node, buf_sprintf("`_` may only be used to assign things to")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } } @@ -4968,13 +5999,13 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, add_node_error(irb->codegen, node, buf_sprintf("primitive integer type '%s' exceeds maximum bit width of 65535", buf_ptr(variable_name))); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } assert(err == ErrorPrimitiveTypeNotFound); } else { - IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_type); + IrInstSrc *value = ir_build_const_type(irb, scope, node, primitive_type); if (lval == LValPtr) { - return ir_build_ref(irb, scope, node, value, false, false); + return ir_build_ref_src(irb, scope, node, value, false, false); } else { return ir_expr_wrap(irb, scope, value, result_loc); } @@ -4983,7 +6014,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, ScopeFnDef *crossed_fndef_scope; ZigVar *var = find_variable(irb->codegen, scope, variable_name, &crossed_fndef_scope); if (var) { - IrInstruction *var_ptr = ir_build_var_ptr_x(irb, scope, node, var, crossed_fndef_scope); + IrInstSrc *var_ptr = ir_build_var_ptr_x(irb, scope, node, var, crossed_fndef_scope); if (lval == LValPtr) { return var_ptr; } else { @@ -4993,7 +6024,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, Tld *tld = find_decl(irb->codegen, scope, variable_name); if (tld) { - IrInstruction *decl_ref = ir_build_decl_ref(irb, scope, node, tld, lval); + IrInstSrc *decl_ref = ir_build_decl_ref(irb, scope, node, tld, lval); if (lval == LValPtr) { return decl_ref; } else { @@ -5004,50 +6035,50 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, if (get_container_scope(node->owner)->any_imports_failed) { // skip the error message since we had a failing import in this file // if an import breaks we don't need redundant undeclared identifier errors - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } return ir_build_undeclared_identifier(irb, scope, node, variable_name); } -static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_array_access(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeArrayAccessExpr); AstNode *array_ref_node = node->data.array_access_expr.array_ref_expr; - IrInstruction *array_ref_instruction = ir_gen_node_extra(irb, array_ref_node, scope, LValPtr, nullptr); - if (array_ref_instruction == irb->codegen->invalid_instruction) + IrInstSrc *array_ref_instruction = ir_gen_node_extra(irb, array_ref_node, scope, LValPtr, nullptr); + if (array_ref_instruction == irb->codegen->invalid_inst_src) return array_ref_instruction; AstNode *subscript_node = node->data.array_access_expr.subscript; - IrInstruction *subscript_instruction = ir_gen_node(irb, subscript_node, scope); - if (subscript_instruction == irb->codegen->invalid_instruction) + IrInstSrc *subscript_instruction = ir_gen_node(irb, subscript_node, scope); + if (subscript_instruction == irb->codegen->invalid_inst_src) return subscript_instruction; - IrInstruction *ptr_instruction = ir_build_elem_ptr(irb, scope, node, array_ref_instruction, + IrInstSrc *ptr_instruction = ir_build_elem_ptr(irb, scope, node, array_ref_instruction, subscript_instruction, true, PtrLenSingle, nullptr); if (lval == LValPtr) return ptr_instruction; - IrInstruction *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction); + IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction); return ir_expr_wrap(irb, scope, load_ptr, result_loc); } -static IrInstruction *ir_gen_field_access(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_field_access(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeFieldAccessExpr); AstNode *container_ref_node = node->data.field_access_expr.struct_expr; Buf *field_name = node->data.field_access_expr.field_name; - IrInstruction *container_ref_instruction = ir_gen_node_extra(irb, container_ref_node, scope, LValPtr, nullptr); - if (container_ref_instruction == irb->codegen->invalid_instruction) + IrInstSrc *container_ref_instruction = ir_gen_node_extra(irb, container_ref_node, scope, LValPtr, nullptr); + if (container_ref_instruction == irb->codegen->invalid_inst_src) return container_ref_instruction; return ir_build_field_ptr(irb, scope, node, container_ref_instruction, field_name, false); } -static IrInstruction *ir_gen_overflow_op(IrBuilder *irb, Scope *scope, AstNode *node, IrOverflowOp op) { +static IrInstSrc *ir_gen_overflow_op(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrOverflowOp op) { assert(node->type == NodeTypeFnCallExpr); AstNode *type_node = node->data.fn_call_expr.params.at(0); @@ -5056,26 +6087,26 @@ static IrInstruction *ir_gen_overflow_op(IrBuilder *irb, Scope *scope, AstNode * AstNode *result_ptr_node = node->data.fn_call_expr.params.at(3); - IrInstruction *type_value = ir_gen_node(irb, type_node, scope); - if (type_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *type_value = ir_gen_node(irb, type_node, scope); + if (type_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - IrInstruction *op1 = ir_gen_node(irb, op1_node, scope); - if (op1 == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *op1 = ir_gen_node(irb, op1_node, scope); + if (op1 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - IrInstruction *op2 = ir_gen_node(irb, op2_node, scope); - if (op2 == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *op2 = ir_gen_node(irb, op2_node, scope); + if (op2 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - IrInstruction *result_ptr = ir_gen_node(irb, result_ptr_node, scope); - if (result_ptr == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *result_ptr = ir_gen_node(irb, result_ptr_node, scope); + if (result_ptr == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - return ir_build_overflow_op(irb, scope, node, op, type_value, op1, op2, result_ptr, nullptr); + return ir_build_overflow_op_src(irb, scope, node, op, type_value, op1, op2, result_ptr); } -static IrInstruction *ir_gen_mul_add(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_mul_add(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeFnCallExpr); AstNode *type_node = node->data.fn_call_expr.params.at(0); @@ -5083,26 +6114,26 @@ static IrInstruction *ir_gen_mul_add(IrBuilder *irb, Scope *scope, AstNode *node AstNode *op2_node = node->data.fn_call_expr.params.at(2); AstNode *op3_node = node->data.fn_call_expr.params.at(3); - IrInstruction *type_value = ir_gen_node(irb, type_node, scope); - if (type_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *type_value = ir_gen_node(irb, type_node, scope); + if (type_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - IrInstruction *op1 = ir_gen_node(irb, op1_node, scope); - if (op1 == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *op1 = ir_gen_node(irb, op1_node, scope); + if (op1 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - IrInstruction *op2 = ir_gen_node(irb, op2_node, scope); - if (op2 == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *op2 = ir_gen_node(irb, op2_node, scope); + if (op2 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - IrInstruction *op3 = ir_gen_node(irb, op3_node, scope); - if (op3 == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *op3 = ir_gen_node(irb, op3_node, scope); + if (op3 == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - return ir_build_mul_add(irb, scope, node, type_value, op1, op2, op3); + return ir_build_mul_add_src(irb, scope, node, type_value, op1, op2, op3); } -static IrInstruction *ir_gen_this(IrBuilder *irb, Scope *orig_scope, AstNode *node) { +static IrInstSrc *ir_gen_this(IrBuilderSrc *irb, Scope *orig_scope, AstNode *node) { for (Scope *it_scope = orig_scope; it_scope != nullptr; it_scope = it_scope->parent) { if (it_scope->id == ScopeIdDecls) { ScopeDecls *decls_scope = (ScopeDecls *)it_scope; @@ -5117,7 +6148,7 @@ static IrInstruction *ir_gen_this(IrBuilder *irb, Scope *orig_scope, AstNode *no zig_unreachable(); } -static IrInstruction *ir_gen_async_call(IrBuilder *irb, Scope *scope, AstNode *await_node, AstNode *call_node, +static IrInstSrc *ir_gen_async_call(IrBuilderSrc *irb, Scope *scope, AstNode *await_node, AstNode *call_node, LVal lval, ResultLoc *result_loc) { size_t arg_offset = 3; @@ -5125,71 +6156,71 @@ static IrInstruction *ir_gen_async_call(IrBuilder *irb, Scope *scope, AstNode *a add_node_error(irb->codegen, call_node, buf_sprintf("expected at least %" ZIG_PRI_usize " arguments, found %" ZIG_PRI_usize, arg_offset, call_node->data.fn_call_expr.params.length)); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } AstNode *bytes_node = call_node->data.fn_call_expr.params.at(0); - IrInstruction *bytes = ir_gen_node(irb, bytes_node, scope); - if (bytes == irb->codegen->invalid_instruction) + IrInstSrc *bytes = ir_gen_node(irb, bytes_node, scope); + if (bytes == irb->codegen->invalid_inst_src) return bytes; AstNode *ret_ptr_node = call_node->data.fn_call_expr.params.at(1); - IrInstruction *ret_ptr = ir_gen_node(irb, ret_ptr_node, scope); - if (ret_ptr == irb->codegen->invalid_instruction) + IrInstSrc *ret_ptr = ir_gen_node(irb, ret_ptr_node, scope); + if (ret_ptr == irb->codegen->invalid_inst_src) return ret_ptr; AstNode *fn_ref_node = call_node->data.fn_call_expr.params.at(2); - IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope); - if (fn_ref == irb->codegen->invalid_instruction) + IrInstSrc *fn_ref = ir_gen_node(irb, fn_ref_node, scope); + if (fn_ref == irb->codegen->invalid_inst_src) return fn_ref; size_t arg_count = call_node->data.fn_call_expr.params.length - arg_offset; - IrInstruction **args = allocate(arg_count); + IrInstSrc **args = allocate(arg_count); for (size_t i = 0; i < arg_count; i += 1) { AstNode *arg_node = call_node->data.fn_call_expr.params.at(i + arg_offset); - IrInstruction *arg = ir_gen_node(irb, arg_node, scope); - if (arg == irb->codegen->invalid_instruction) + IrInstSrc *arg = ir_gen_node(irb, arg_node, scope); + if (arg == irb->codegen->invalid_inst_src) return arg; args[i] = arg; } CallModifier modifier = (await_node == nullptr) ? CallModifierAsync : CallModifierNone; bool is_async_call_builtin = true; - IrInstruction *call = ir_build_call_src(irb, scope, call_node, nullptr, fn_ref, arg_count, args, + IrInstSrc *call = ir_build_call_src(irb, scope, call_node, nullptr, fn_ref, arg_count, args, ret_ptr, modifier, is_async_call_builtin, bytes, result_loc); return ir_lval_wrap(irb, scope, call, lval, result_loc); } -static IrInstruction *ir_gen_fn_call_with_args(IrBuilder *irb, Scope *scope, AstNode *source_node, - AstNode *fn_ref_node, CallModifier modifier, IrInstruction *options, +static IrInstSrc *ir_gen_fn_call_with_args(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + AstNode *fn_ref_node, CallModifier modifier, IrInstSrc *options, AstNode **args_ptr, size_t args_len, LVal lval, ResultLoc *result_loc) { - IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope); - if (fn_ref == irb->codegen->invalid_instruction) + IrInstSrc *fn_ref = ir_gen_node(irb, fn_ref_node, scope); + if (fn_ref == irb->codegen->invalid_inst_src) return fn_ref; - IrInstruction *fn_type = ir_build_typeof(irb, scope, source_node, fn_ref); + IrInstSrc *fn_type = ir_build_typeof(irb, scope, source_node, fn_ref); - IrInstruction **args = allocate(args_len); + IrInstSrc **args = allocate(args_len); for (size_t i = 0; i < args_len; i += 1) { AstNode *arg_node = args_ptr[i]; - IrInstruction *arg_index = ir_build_const_usize(irb, scope, arg_node, i); - IrInstruction *arg_type = ir_build_arg_type(irb, scope, source_node, fn_type, arg_index, true); + IrInstSrc *arg_index = ir_build_const_usize(irb, scope, arg_node, i); + IrInstSrc *arg_type = ir_build_arg_type(irb, scope, source_node, fn_type, arg_index, true); ResultLoc *no_result = no_result_loc(); ir_build_reset_result(irb, scope, source_node, no_result); ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, arg_type, no_result); - IrInstruction *arg = ir_gen_node_extra(irb, arg_node, scope, LValNone, &result_loc_cast->base); - if (arg == irb->codegen->invalid_instruction) + IrInstSrc *arg = ir_gen_node_extra(irb, arg_node, scope, LValNone, &result_loc_cast->base); + if (arg == irb->codegen->invalid_inst_src) return arg; args[i] = ir_build_implicit_cast(irb, scope, arg_node, arg, result_loc_cast); } - IrInstruction *fn_call; + IrInstSrc *fn_call; if (options != nullptr) { - fn_call = ir_build_call_src_args(irb, scope, source_node, options, fn_ref, args, args_len, result_loc); + fn_call = ir_build_call_args(irb, scope, source_node, options, fn_ref, args, args_len, result_loc); } else { fn_call = ir_build_call_src(irb, scope, source_node, nullptr, fn_ref, args_len, args, nullptr, modifier, false, nullptr, result_loc); @@ -5197,7 +6228,7 @@ static IrInstruction *ir_gen_fn_call_with_args(IrBuilder *irb, Scope *scope, Ast return ir_lval_wrap(irb, scope, fn_call, lval, result_loc); } -static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeFnCallExpr); @@ -5209,7 +6240,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo if (!entry) { add_node_error(irb->codegen, node, buf_sprintf("invalid builtin function: '%s'", buf_ptr(name))); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } BuiltinFnEntry *builtin_fn = entry->value; @@ -5219,7 +6250,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo add_node_error(irb->codegen, node, buf_sprintf("expected %" ZIG_PRI_usize " arguments, found %" ZIG_PRI_usize, builtin_fn->param_count, actual_param_count)); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } switch (builtin_fn->id) { @@ -5230,197 +6261,197 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo Scope *sub_scope = create_typeof_scope(irb->codegen, node, scope); AstNode *arg_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg = ir_gen_node(irb, arg_node, sub_scope); - if (arg == irb->codegen->invalid_instruction) + IrInstSrc *arg = ir_gen_node(irb, arg_node, sub_scope); + if (arg == irb->codegen->invalid_inst_src) return arg; - IrInstruction *type_of = ir_build_typeof(irb, scope, node, arg); + IrInstSrc *type_of = ir_build_typeof(irb, scope, node, arg); return ir_lval_wrap(irb, scope, type_of, lval, result_loc); } case BuiltinFnIdSetCold: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *set_cold = ir_build_set_cold(irb, scope, node, arg0_value); + IrInstSrc *set_cold = ir_build_set_cold(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, set_cold, lval, result_loc); } case BuiltinFnIdSetRuntimeSafety: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *set_safety = ir_build_set_runtime_safety(irb, scope, node, arg0_value); + IrInstSrc *set_safety = ir_build_set_runtime_safety(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, set_safety, lval, result_loc); } case BuiltinFnIdSetFloatMode: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *set_float_mode = ir_build_set_float_mode(irb, scope, node, arg0_value); + IrInstSrc *set_float_mode = ir_build_set_float_mode(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, set_float_mode, lval, result_loc); } case BuiltinFnIdSizeof: case BuiltinFnIdBitSizeof: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *size_of = ir_build_size_of(irb, scope, node, arg0_value, builtin_fn->id == BuiltinFnIdBitSizeof); + IrInstSrc *size_of = ir_build_size_of(irb, scope, node, arg0_value, builtin_fn->id == BuiltinFnIdBitSizeof); return ir_lval_wrap(irb, scope, size_of, lval, result_loc); } case BuiltinFnIdImport: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *import = ir_build_import(irb, scope, node, arg0_value); + IrInstSrc *import = ir_build_import(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, import, lval, result_loc); } case BuiltinFnIdCImport: { - IrInstruction *c_import = ir_build_c_import(irb, scope, node); + IrInstSrc *c_import = ir_build_c_import(irb, scope, node); return ir_lval_wrap(irb, scope, c_import, lval, result_loc); } case BuiltinFnIdCInclude: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; if (!exec_c_import_buf(irb->exec)) { add_node_error(irb->codegen, node, buf_sprintf("C include valid only inside C import block")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } - IrInstruction *c_include = ir_build_c_include(irb, scope, node, arg0_value); + IrInstSrc *c_include = ir_build_c_include(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, c_include, lval, result_loc); } case BuiltinFnIdCDefine: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; if (!exec_c_import_buf(irb->exec)) { add_node_error(irb->codegen, node, buf_sprintf("C define valid only inside C import block")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } - IrInstruction *c_define = ir_build_c_define(irb, scope, node, arg0_value, arg1_value); + IrInstSrc *c_define = ir_build_c_define(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, c_define, lval, result_loc); } case BuiltinFnIdCUndef: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; if (!exec_c_import_buf(irb->exec)) { add_node_error(irb->codegen, node, buf_sprintf("C undef valid only inside C import block")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } - IrInstruction *c_undef = ir_build_c_undef(irb, scope, node, arg0_value); + IrInstSrc *c_undef = ir_build_c_undef(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, c_undef, lval, result_loc); } case BuiltinFnIdCompileErr: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *compile_err = ir_build_compile_err(irb, scope, node, arg0_value); + IrInstSrc *compile_err = ir_build_compile_err(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, compile_err, lval, result_loc); } case BuiltinFnIdCompileLog: { - IrInstruction **args = allocate(actual_param_count); + IrInstSrc **args = allocate(actual_param_count); for (size_t i = 0; i < actual_param_count; i += 1) { AstNode *arg_node = node->data.fn_call_expr.params.at(i); args[i] = ir_gen_node(irb, arg_node, scope); - if (args[i] == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + if (args[i] == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; } - IrInstruction *compile_log = ir_build_compile_log(irb, scope, node, actual_param_count, args); + IrInstSrc *compile_log = ir_build_compile_log(irb, scope, node, actual_param_count, args); return ir_lval_wrap(irb, scope, compile_log, lval, result_loc); } case BuiltinFnIdErrName: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *err_name = ir_build_err_name(irb, scope, node, arg0_value); + IrInstSrc *err_name = ir_build_err_name(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, err_name, lval, result_loc); } case BuiltinFnIdEmbedFile: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *embed_file = ir_build_embed_file(irb, scope, node, arg0_value); + IrInstSrc *embed_file = ir_build_embed_file(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, embed_file, lval, result_loc); } case BuiltinFnIdCmpxchgWeak: case BuiltinFnIdCmpxchgStrong: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_instruction) + IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_inst_src) return arg2_value; AstNode *arg3_node = node->data.fn_call_expr.params.at(3); - IrInstruction *arg3_value = ir_gen_node(irb, arg3_node, scope); - if (arg3_value == irb->codegen->invalid_instruction) + IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); + if (arg3_value == irb->codegen->invalid_inst_src) return arg3_value; AstNode *arg4_node = node->data.fn_call_expr.params.at(4); - IrInstruction *arg4_value = ir_gen_node(irb, arg4_node, scope); - if (arg4_value == irb->codegen->invalid_instruction) + IrInstSrc *arg4_value = ir_gen_node(irb, arg4_node, scope); + if (arg4_value == irb->codegen->invalid_inst_src) return arg4_value; AstNode *arg5_node = node->data.fn_call_expr.params.at(5); - IrInstruction *arg5_value = ir_gen_node(irb, arg5_node, scope); - if (arg5_value == irb->codegen->invalid_instruction) + IrInstSrc *arg5_value = ir_gen_node(irb, arg5_node, scope); + if (arg5_value == irb->codegen->invalid_inst_src) return arg5_value; - IrInstruction *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value, + IrInstSrc *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value, arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak), result_loc); return ir_lval_wrap(irb, scope, cmpxchg, lval, result_loc); @@ -5428,86 +6459,86 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo case BuiltinFnIdFence: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *fence = ir_build_fence(irb, scope, node, arg0_value, AtomicOrderUnordered); + IrInstSrc *fence = ir_build_fence(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, fence, lval, result_loc); } case BuiltinFnIdDivExact: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivExact, arg0_value, arg1_value, true); + IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivExact, arg0_value, arg1_value, true); return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); } case BuiltinFnIdDivTrunc: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivTrunc, arg0_value, arg1_value, true); + IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivTrunc, arg0_value, arg1_value, true); return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); } case BuiltinFnIdDivFloor: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivFloor, arg0_value, arg1_value, true); + IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivFloor, arg0_value, arg1_value, true); return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); } case BuiltinFnIdRem: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemRem, arg0_value, arg1_value, true); + IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemRem, arg0_value, arg1_value, true); return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); } case BuiltinFnIdMod: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemMod, arg0_value, arg1_value, true); + IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemMod, arg0_value, arg1_value, true); return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); } case BuiltinFnIdSqrt: @@ -5526,406 +6557,406 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo case BuiltinFnIdRound: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *inst = ir_build_float_op(irb, scope, node, arg0_value, builtin_fn->id); + IrInstSrc *inst = ir_build_float_op_src(irb, scope, node, arg0_value, builtin_fn->id); return ir_lval_wrap(irb, scope, inst, lval, result_loc); } case BuiltinFnIdTruncate: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *truncate = ir_build_truncate(irb, scope, node, arg0_value, arg1_value); + IrInstSrc *truncate = ir_build_truncate(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, truncate, lval, result_loc); } case BuiltinFnIdIntCast: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *result = ir_build_int_cast(irb, scope, node, arg0_value, arg1_value); + IrInstSrc *result = ir_build_int_cast(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, result, lval, result_loc); } case BuiltinFnIdFloatCast: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *result = ir_build_float_cast(irb, scope, node, arg0_value, arg1_value); + IrInstSrc *result = ir_build_float_cast(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, result, lval, result_loc); } case BuiltinFnIdErrSetCast: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *result = ir_build_err_set_cast(irb, scope, node, arg0_value, arg1_value); + IrInstSrc *result = ir_build_err_set_cast(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, result, lval, result_loc); } case BuiltinFnIdFromBytes: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *result = ir_build_from_bytes(irb, scope, node, arg0_value, arg1_value, result_loc); + IrInstSrc *result = ir_build_from_bytes(irb, scope, node, arg0_value, arg1_value, result_loc); return ir_lval_wrap(irb, scope, result, lval, result_loc); } case BuiltinFnIdToBytes: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *result = ir_build_to_bytes(irb, scope, node, arg0_value, result_loc); + IrInstSrc *result = ir_build_to_bytes(irb, scope, node, arg0_value, result_loc); return ir_lval_wrap(irb, scope, result, lval, result_loc); } case BuiltinFnIdIntToFloat: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *result = ir_build_int_to_float(irb, scope, node, arg0_value, arg1_value); + IrInstSrc *result = ir_build_int_to_float(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, result, lval, result_loc); } case BuiltinFnIdFloatToInt: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *result = ir_build_float_to_int(irb, scope, node, arg0_value, arg1_value); + IrInstSrc *result = ir_build_float_to_int(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, result, lval, result_loc); } case BuiltinFnIdErrToInt: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *result = ir_build_err_to_int(irb, scope, node, arg0_value); + IrInstSrc *result = ir_build_err_to_int_src(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, result, lval, result_loc); } case BuiltinFnIdIntToErr: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *result = ir_build_int_to_err(irb, scope, node, arg0_value); + IrInstSrc *result = ir_build_int_to_err_src(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, result, lval, result_loc); } case BuiltinFnIdBoolToInt: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *result = ir_build_bool_to_int(irb, scope, node, arg0_value); + IrInstSrc *result = ir_build_bool_to_int(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, result, lval, result_loc); } case BuiltinFnIdIntType: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *int_type = ir_build_int_type(irb, scope, node, arg0_value, arg1_value); + IrInstSrc *int_type = ir_build_int_type(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, int_type, lval, result_loc); } case BuiltinFnIdVectorType: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *vector_type = ir_build_vector_type(irb, scope, node, arg0_value, arg1_value); + IrInstSrc *vector_type = ir_build_vector_type(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, vector_type, lval, result_loc); } case BuiltinFnIdShuffle: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_instruction) + IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_inst_src) return arg2_value; AstNode *arg3_node = node->data.fn_call_expr.params.at(3); - IrInstruction *arg3_value = ir_gen_node(irb, arg3_node, scope); - if (arg3_value == irb->codegen->invalid_instruction) + IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); + if (arg3_value == irb->codegen->invalid_inst_src) return arg3_value; - IrInstruction *shuffle_vector = ir_build_shuffle_vector(irb, scope, node, + IrInstSrc *shuffle_vector = ir_build_shuffle_vector(irb, scope, node, arg0_value, arg1_value, arg2_value, arg3_value); return ir_lval_wrap(irb, scope, shuffle_vector, lval, result_loc); } case BuiltinFnIdSplat: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *splat = ir_build_splat_src(irb, scope, node, + IrInstSrc *splat = ir_build_splat_src(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, splat, lval, result_loc); } case BuiltinFnIdMemcpy: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_instruction) + IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_inst_src) return arg2_value; - IrInstruction *ir_memcpy = ir_build_memcpy(irb, scope, node, arg0_value, arg1_value, arg2_value); + IrInstSrc *ir_memcpy = ir_build_memcpy_src(irb, scope, node, arg0_value, arg1_value, arg2_value); return ir_lval_wrap(irb, scope, ir_memcpy, lval, result_loc); } case BuiltinFnIdMemset: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_instruction) + IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_inst_src) return arg2_value; - IrInstruction *ir_memset = ir_build_memset(irb, scope, node, arg0_value, arg1_value, arg2_value); + IrInstSrc *ir_memset = ir_build_memset_src(irb, scope, node, arg0_value, arg1_value, arg2_value); return ir_lval_wrap(irb, scope, ir_memset, lval, result_loc); } case BuiltinFnIdMemberCount: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *member_count = ir_build_member_count(irb, scope, node, arg0_value); + IrInstSrc *member_count = ir_build_member_count(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, member_count, lval, result_loc); } case BuiltinFnIdMemberType: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *member_type = ir_build_member_type(irb, scope, node, arg0_value, arg1_value); + IrInstSrc *member_type = ir_build_member_type(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, member_type, lval, result_loc); } case BuiltinFnIdMemberName: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *member_name = ir_build_member_name(irb, scope, node, arg0_value, arg1_value); + IrInstSrc *member_name = ir_build_member_name(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, member_name, lval, result_loc); } case BuiltinFnIdField: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node_extra(irb, arg0_node, scope, LValPtr, nullptr); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node_extra(irb, arg0_node, scope, LValPtr, nullptr); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *ptr_instruction = ir_build_field_ptr_instruction(irb, scope, node, + IrInstSrc *ptr_instruction = ir_build_field_ptr_instruction(irb, scope, node, arg0_value, arg1_value, false); if (lval == LValPtr) return ptr_instruction; - IrInstruction *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction); + IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction); return ir_expr_wrap(irb, scope, load_ptr, result_loc); } case BuiltinFnIdHasField: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *type_info = ir_build_has_field(irb, scope, node, arg0_value, arg1_value); + IrInstSrc *type_info = ir_build_has_field(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, type_info, lval, result_loc); } case BuiltinFnIdTypeInfo: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *type_info = ir_build_type_info(irb, scope, node, arg0_value); + IrInstSrc *type_info = ir_build_type_info(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, type_info, lval, result_loc); } case BuiltinFnIdType: { AstNode *arg_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg = ir_gen_node(irb, arg_node, scope); - if (arg == irb->codegen->invalid_instruction) + IrInstSrc *arg = ir_gen_node(irb, arg_node, scope); + if (arg == irb->codegen->invalid_inst_src) return arg; - IrInstruction *type = ir_build_type(irb, scope, node, arg); + IrInstSrc *type = ir_build_type(irb, scope, node, arg); return ir_lval_wrap(irb, scope, type, lval, result_loc); } case BuiltinFnIdBreakpoint: return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval, result_loc); case BuiltinFnIdReturnAddress: - return ir_lval_wrap(irb, scope, ir_build_return_address(irb, scope, node), lval, result_loc); + return ir_lval_wrap(irb, scope, ir_build_return_address_src(irb, scope, node), lval, result_loc); case BuiltinFnIdFrameAddress: - return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval, result_loc); + return ir_lval_wrap(irb, scope, ir_build_frame_address_src(irb, scope, node), lval, result_loc); case BuiltinFnIdFrameHandle: if (!irb->exec->fn_entry) { add_node_error(irb->codegen, node, buf_sprintf("@frame() called outside of function definition")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } - return ir_lval_wrap(irb, scope, ir_build_handle(irb, scope, node), lval, result_loc); + return ir_lval_wrap(irb, scope, ir_build_handle_src(irb, scope, node), lval, result_loc); case BuiltinFnIdFrameType: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *frame_type = ir_build_frame_type(irb, scope, node, arg0_value); + IrInstSrc *frame_type = ir_build_frame_type(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, frame_type, lval, result_loc); } case BuiltinFnIdFrameSize: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *frame_size = ir_build_frame_size_src(irb, scope, node, arg0_value); + IrInstSrc *frame_size = ir_build_frame_size_src(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, frame_size, lval, result_loc); } case BuiltinFnIdAlignOf: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *align_of = ir_build_align_of(irb, scope, node, arg0_value); + IrInstSrc *align_of = ir_build_align_of(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, align_of, lval, result_loc); } case BuiltinFnIdAddWithOverflow: @@ -5941,43 +6972,43 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo case BuiltinFnIdTypeName: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *type_name = ir_build_type_name(irb, scope, node, arg0_value); + IrInstSrc *type_name = ir_build_type_name(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, type_name, lval, result_loc); } case BuiltinFnIdPanic: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *panic = ir_build_panic(irb, scope, node, arg0_value); + IrInstSrc *panic = ir_build_panic_src(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, panic, lval, result_loc); } case BuiltinFnIdPtrCast: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value, true); + IrInstSrc *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value, true); return ir_lval_wrap(irb, scope, ptr_cast, lval, result_loc); } case BuiltinFnIdBitCast: { AstNode *dest_type_node = node->data.fn_call_expr.params.at(0); - IrInstruction *dest_type = ir_gen_node(irb, dest_type_node, scope); - if (dest_type == irb->codegen->invalid_instruction) + IrInstSrc *dest_type = ir_gen_node(irb, dest_type_node, scope); + if (dest_type == irb->codegen->invalid_inst_src) return dest_type; ResultLocBitCast *result_loc_bit_cast = allocate(1); @@ -5989,126 +7020,126 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo ir_build_reset_result(irb, scope, node, &result_loc_bit_cast->base); AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node_extra(irb, arg1_node, scope, LValNone, + IrInstSrc *arg1_value = ir_gen_node_extra(irb, arg1_node, scope, LValNone, &result_loc_bit_cast->base); - if (arg1_value == irb->codegen->invalid_instruction) + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *bitcast = ir_build_bit_cast_src(irb, scope, arg1_node, arg1_value, result_loc_bit_cast); + IrInstSrc *bitcast = ir_build_bit_cast_src(irb, scope, arg1_node, arg1_value, result_loc_bit_cast); return ir_lval_wrap(irb, scope, bitcast, lval, result_loc); } case BuiltinFnIdAs: { AstNode *dest_type_node = node->data.fn_call_expr.params.at(0); - IrInstruction *dest_type = ir_gen_node(irb, dest_type_node, scope); - if (dest_type == irb->codegen->invalid_instruction) + IrInstSrc *dest_type = ir_gen_node(irb, dest_type_node, scope); + if (dest_type == irb->codegen->invalid_inst_src) return dest_type; ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, dest_type, result_loc); AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node_extra(irb, arg1_node, scope, LValNone, + IrInstSrc *arg1_value = ir_gen_node_extra(irb, arg1_node, scope, LValNone, &result_loc_cast->base); - if (arg1_value == irb->codegen->invalid_instruction) + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *result = ir_build_implicit_cast(irb, scope, node, arg1_value, result_loc_cast); + IrInstSrc *result = ir_build_implicit_cast(irb, scope, node, arg1_value, result_loc_cast); return ir_lval_wrap(irb, scope, result, lval, result_loc); } case BuiltinFnIdIntToPtr: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *int_to_ptr = ir_build_int_to_ptr(irb, scope, node, arg0_value, arg1_value); + IrInstSrc *int_to_ptr = ir_build_int_to_ptr_src(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, int_to_ptr, lval, result_loc); } case BuiltinFnIdPtrToInt: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *ptr_to_int = ir_build_ptr_to_int(irb, scope, node, arg0_value); + IrInstSrc *ptr_to_int = ir_build_ptr_to_int_src(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, ptr_to_int, lval, result_loc); } case BuiltinFnIdTagName: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *actual_tag = ir_build_union_tag(irb, scope, node, arg0_value); - IrInstruction *tag_name = ir_build_tag_name(irb, scope, node, actual_tag); + IrInstSrc *tag_name = ir_build_tag_name_src(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, tag_name, lval, result_loc); } case BuiltinFnIdTagType: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *tag_type = ir_build_tag_type(irb, scope, node, arg0_value); + IrInstSrc *tag_type = ir_build_tag_type(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, tag_type, lval, result_loc); } case BuiltinFnIdFieldParentPtr: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_instruction) + IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_inst_src) return arg2_value; - IrInstruction *field_parent_ptr = ir_build_field_parent_ptr(irb, scope, node, arg0_value, arg1_value, arg2_value, nullptr); + IrInstSrc *field_parent_ptr = ir_build_field_parent_ptr_src(irb, scope, node, + arg0_value, arg1_value, arg2_value); return ir_lval_wrap(irb, scope, field_parent_ptr, lval, result_loc); } case BuiltinFnIdByteOffsetOf: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *offset_of = ir_build_byte_offset_of(irb, scope, node, arg0_value, arg1_value); + IrInstSrc *offset_of = ir_build_byte_offset_of(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, offset_of, lval, result_loc); } case BuiltinFnIdBitOffsetOf: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *offset_of = ir_build_bit_offset_of(irb, scope, node, arg0_value, arg1_value); + IrInstSrc *offset_of = ir_build_bit_offset_of(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, offset_of, lval, result_loc); } case BuiltinFnIdNewStackCall: @@ -6117,45 +7148,45 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo add_node_error(irb->codegen, node, buf_sprintf("expected at least 2 arguments, found %" ZIG_PRI_usize, node->data.fn_call_expr.params.length)); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } AstNode *new_stack_node = node->data.fn_call_expr.params.at(0); - IrInstruction *new_stack = ir_gen_node(irb, new_stack_node, scope); - if (new_stack == irb->codegen->invalid_instruction) + IrInstSrc *new_stack = ir_gen_node(irb, new_stack_node, scope); + if (new_stack == irb->codegen->invalid_inst_src) return new_stack; AstNode *fn_ref_node = node->data.fn_call_expr.params.at(1); - IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope); - if (fn_ref == irb->codegen->invalid_instruction) + IrInstSrc *fn_ref = ir_gen_node(irb, fn_ref_node, scope); + if (fn_ref == irb->codegen->invalid_inst_src) return fn_ref; size_t arg_count = node->data.fn_call_expr.params.length - 2; - IrInstruction **args = allocate(arg_count); + IrInstSrc **args = allocate(arg_count); for (size_t i = 0; i < arg_count; i += 1) { AstNode *arg_node = node->data.fn_call_expr.params.at(i + 2); args[i] = ir_gen_node(irb, arg_node, scope); - if (args[i] == irb->codegen->invalid_instruction) + if (args[i] == irb->codegen->invalid_inst_src) return args[i]; } - IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, + IrInstSrc *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, nullptr, CallModifierNone, false, new_stack, result_loc); return ir_lval_wrap(irb, scope, call, lval, result_loc); } case BuiltinFnIdCall: { // Cast the options parameter to the options type ZigType *options_type = get_builtin_type(irb->codegen, "CallOptions"); - IrInstruction *options_type_inst = ir_build_const_type(irb, scope, node, options_type); + IrInstSrc *options_type_inst = ir_build_const_type(irb, scope, node, options_type); ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, options_type_inst, no_result_loc()); AstNode *options_node = node->data.fn_call_expr.params.at(0); - IrInstruction *options_inner = ir_gen_node_extra(irb, options_node, scope, + IrInstSrc *options_inner = ir_gen_node_extra(irb, options_node, scope, LValNone, &result_loc_cast->base); - if (options_inner == irb->codegen->invalid_instruction) + if (options_inner == irb->codegen->invalid_inst_src) return options_inner; - IrInstruction *options = ir_build_implicit_cast(irb, scope, options_node, options_inner, result_loc_cast); + IrInstSrc *options = ir_build_implicit_cast(irb, scope, options_node, options_inner, result_loc_cast); AstNode *fn_ref_node = node->data.fn_call_expr.params.at(1); AstNode *args_node = node->data.fn_call_expr.params.at(2); @@ -6171,18 +7202,18 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo } else { exec_add_error_node(irb->codegen, irb->exec, args_node, buf_sprintf("TODO: @call with anon struct literal")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } } else { - IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope); - if (fn_ref == irb->codegen->invalid_instruction) + IrInstSrc *fn_ref = ir_gen_node(irb, fn_ref_node, scope); + if (fn_ref == irb->codegen->invalid_inst_src) return fn_ref; - IrInstruction *args = ir_gen_node(irb, args_node, scope); - if (args == irb->codegen->invalid_instruction) + IrInstSrc *args = ir_gen_node(irb, args_node, scope); + if (args == irb->codegen->invalid_inst_src) return args; - IrInstruction *call = ir_build_call_extra(irb, scope, node, options, fn_ref, args, result_loc); + IrInstSrc *call = ir_build_call_extra(irb, scope, node, options, fn_ref, args, result_loc); return ir_lval_wrap(irb, scope, call, lval, result_loc); } } @@ -6191,237 +7222,233 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo case BuiltinFnIdTypeId: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *type_id = ir_build_type_id(irb, scope, node, arg0_value); + IrInstSrc *type_id = ir_build_type_id(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, type_id, lval, result_loc); } case BuiltinFnIdShlExact: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftLeftExact, arg0_value, arg1_value, true); + IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftLeftExact, arg0_value, arg1_value, true); return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); } case BuiltinFnIdShrExact: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftRightExact, arg0_value, arg1_value, true); + IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftRightExact, arg0_value, arg1_value, true); return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); } case BuiltinFnIdSetEvalBranchQuota: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *set_eval_branch_quota = ir_build_set_eval_branch_quota(irb, scope, node, arg0_value); + IrInstSrc *set_eval_branch_quota = ir_build_set_eval_branch_quota(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, set_eval_branch_quota, lval, result_loc); } case BuiltinFnIdAlignCast: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *align_cast = ir_build_align_cast(irb, scope, node, arg0_value, arg1_value); + IrInstSrc *align_cast = ir_build_align_cast_src(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, align_cast, lval, result_loc); } case BuiltinFnIdOpaqueType: { - IrInstruction *opaque_type = ir_build_opaque_type(irb, scope, node); + IrInstSrc *opaque_type = ir_build_opaque_type(irb, scope, node); return ir_lval_wrap(irb, scope, opaque_type, lval, result_loc); } case BuiltinFnIdThis: { - IrInstruction *this_inst = ir_gen_this(irb, scope, node); + IrInstSrc *this_inst = ir_gen_this(irb, scope, node); return ir_lval_wrap(irb, scope, this_inst, lval, result_loc); } case BuiltinFnIdSetAlignStack: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *set_align_stack = ir_build_set_align_stack(irb, scope, node, arg0_value); + IrInstSrc *set_align_stack = ir_build_set_align_stack(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, set_align_stack, lval, result_loc); } case BuiltinFnIdArgType: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *arg_type = ir_build_arg_type(irb, scope, node, arg0_value, arg1_value, false); + IrInstSrc *arg_type = ir_build_arg_type(irb, scope, node, arg0_value, arg1_value, false); return ir_lval_wrap(irb, scope, arg_type, lval, result_loc); } case BuiltinFnIdExport: { // Cast the options parameter to the options type ZigType *options_type = get_builtin_type(irb->codegen, "ExportOptions"); - IrInstruction *options_type_inst = ir_build_const_type(irb, scope, node, options_type); + IrInstSrc *options_type_inst = ir_build_const_type(irb, scope, node, options_type); ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, options_type_inst, no_result_loc()); AstNode *target_node = node->data.fn_call_expr.params.at(0); - IrInstruction *target_value = ir_gen_node(irb, target_node, scope); - if (target_value == irb->codegen->invalid_instruction) + IrInstSrc *target_value = ir_gen_node(irb, target_node, scope); + if (target_value == irb->codegen->invalid_inst_src) return target_value; AstNode *options_node = node->data.fn_call_expr.params.at(1); - IrInstruction *options_value = ir_gen_node_extra(irb, options_node, + IrInstSrc *options_value = ir_gen_node_extra(irb, options_node, scope, LValNone, &result_loc_cast->base); - if (options_value == irb->codegen->invalid_instruction) + if (options_value == irb->codegen->invalid_inst_src) return options_value; - IrInstruction *casted_options_value = ir_build_implicit_cast( + IrInstSrc *casted_options_value = ir_build_implicit_cast( irb, scope, options_node, options_value, result_loc_cast); - IrInstruction *ir_export = ir_build_export(irb, scope, node, target_value, casted_options_value); + IrInstSrc *ir_export = ir_build_export(irb, scope, node, target_value, casted_options_value); return ir_lval_wrap(irb, scope, ir_export, lval, result_loc); } case BuiltinFnIdErrorReturnTrace: { - IrInstruction *error_return_trace = ir_build_error_return_trace(irb, scope, node, IrInstructionErrorReturnTrace::Null); + IrInstSrc *error_return_trace = ir_build_error_return_trace_src(irb, scope, node, + IrInstErrorReturnTraceNull); return ir_lval_wrap(irb, scope, error_return_trace, lval, result_loc); } case BuiltinFnIdAtomicRmw: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_instruction) + IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_inst_src) return arg2_value; AstNode *arg3_node = node->data.fn_call_expr.params.at(3); - IrInstruction *arg3_value = ir_gen_node(irb, arg3_node, scope); - if (arg3_value == irb->codegen->invalid_instruction) + IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); + if (arg3_value == irb->codegen->invalid_inst_src) return arg3_value; AstNode *arg4_node = node->data.fn_call_expr.params.at(4); - IrInstruction *arg4_value = ir_gen_node(irb, arg4_node, scope); - if (arg4_value == irb->codegen->invalid_instruction) + IrInstSrc *arg4_value = ir_gen_node(irb, arg4_node, scope); + if (arg4_value == irb->codegen->invalid_inst_src) return arg4_value; - IrInstruction *inst = ir_build_atomic_rmw(irb, scope, node, arg0_value, arg1_value, arg2_value, arg3_value, - arg4_value, - // these 2 values don't mean anything since we passed non-null values for other args - AtomicRmwOp_xchg, AtomicOrderMonotonic); + IrInstSrc *inst = ir_build_atomic_rmw_src(irb, scope, node, + arg0_value, arg1_value, arg2_value, arg3_value, arg4_value); return ir_lval_wrap(irb, scope, inst, lval, result_loc); } case BuiltinFnIdAtomicLoad: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_instruction) + IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_inst_src) return arg2_value; - IrInstruction *inst = ir_build_atomic_load(irb, scope, node, arg0_value, arg1_value, arg2_value, - // this value does not mean anything since we passed non-null values for other arg - AtomicOrderMonotonic); + IrInstSrc *inst = ir_build_atomic_load_src(irb, scope, node, arg0_value, arg1_value, arg2_value); return ir_lval_wrap(irb, scope, inst, lval, result_loc); } case BuiltinFnIdAtomicStore: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_instruction) + IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_inst_src) return arg2_value; AstNode *arg3_node = node->data.fn_call_expr.params.at(3); - IrInstruction *arg3_value = ir_gen_node(irb, arg3_node, scope); - if (arg3_value == irb->codegen->invalid_instruction) + IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); + if (arg3_value == irb->codegen->invalid_inst_src) return arg3_value; - IrInstruction *inst = ir_build_atomic_store(irb, scope, node, arg0_value, arg1_value, arg2_value, arg3_value, - // this value does not mean anything since we passed non-null values for other arg - AtomicOrderMonotonic); + IrInstSrc *inst = ir_build_atomic_store_src(irb, scope, node, arg0_value, arg1_value, + arg2_value, arg3_value); return ir_lval_wrap(irb, scope, inst, lval, result_loc); } case BuiltinFnIdIntToEnum: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *result = ir_build_int_to_enum(irb, scope, node, arg0_value, arg1_value); + IrInstSrc *result = ir_build_int_to_enum_src(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, result, lval, result_loc); } case BuiltinFnIdEnumToInt: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; - IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value); + IrInstSrc *result = ir_build_enum_to_int(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, result, lval, result_loc); } case BuiltinFnIdCtz: @@ -6431,16 +7458,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo case BuiltinFnIdBitReverse: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *result; + IrInstSrc *result; switch (builtin_fn->id) { case BuiltinFnIdCtz: result = ir_build_ctz(irb, scope, node, arg0_value, arg1_value); @@ -6465,28 +7492,28 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo case BuiltinFnIdHasDecl: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) + IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_inst_src) return arg0_value; AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) + IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_inst_src) return arg1_value; - IrInstruction *has_decl = ir_build_has_decl(irb, scope, node, arg0_value, arg1_value); + IrInstSrc *has_decl = ir_build_has_decl(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, has_decl, lval, result_loc); } case BuiltinFnIdUnionInit: { AstNode *union_type_node = node->data.fn_call_expr.params.at(0); - IrInstruction *union_type_inst = ir_gen_node(irb, union_type_node, scope); - if (union_type_inst == irb->codegen->invalid_instruction) + IrInstSrc *union_type_inst = ir_gen_node(irb, union_type_node, scope); + if (union_type_inst == irb->codegen->invalid_inst_src) return union_type_inst; AstNode *name_node = node->data.fn_call_expr.params.at(1); - IrInstruction *name_inst = ir_gen_node(irb, name_node, scope); - if (name_inst == irb->codegen->invalid_instruction) + IrInstSrc *name_inst = ir_gen_node(irb, name_node, scope); + if (name_inst == irb->codegen->invalid_inst_src) return name_inst; AstNode *init_node = node->data.fn_call_expr.params.at(2); @@ -6498,7 +7525,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo zig_unreachable(); } -static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeFnCallExpr); @@ -6511,16 +7538,16 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node nullptr, node->data.fn_call_expr.params.items, node->data.fn_call_expr.params.length, lval, result_loc); } -static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_if_bool_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeIfBoolExpr); - IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope); - if (condition == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope); + if (condition == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - IrInstruction *is_comptime; + IrInstSrc *is_comptime; if (ir_should_inline(irb->exec, scope)) { is_comptime = ir_build_const_bool(irb, scope, node, true); } else { @@ -6530,11 +7557,11 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode AstNode *then_node = node->data.if_bool_expr.then_block; AstNode *else_node = node->data.if_bool_expr.else_node; - IrBasicBlock *then_block = ir_create_basic_block(irb, scope, "Then"); - IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "Else"); - IrBasicBlock *endif_block = ir_create_basic_block(irb, scope, "EndIf"); + IrBasicBlockSrc *then_block = ir_create_basic_block(irb, scope, "Then"); + IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "Else"); + IrBasicBlockSrc *endif_block = ir_create_basic_block(irb, scope, "EndIf"); - IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, condition, + IrInstSrc *cond_br_inst = ir_build_cond_br(irb, scope, node, condition, then_block, else_block, is_comptime); ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block, result_loc, is_comptime); @@ -6542,70 +7569,70 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode ir_set_cursor_at_end_and_append_block(irb, then_block); Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); - IrInstruction *then_expr_result = ir_gen_node_extra(irb, then_node, subexpr_scope, lval, + IrInstSrc *then_expr_result = ir_gen_node_extra(irb, then_node, subexpr_scope, lval, &peer_parent->peers.at(0)->base); - if (then_expr_result == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; - IrBasicBlock *after_then_block = irb->current_basic_block; + if (then_expr_result == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + IrBasicBlockSrc *after_then_block = irb->current_basic_block; if (!instr_is_unreachable(then_expr_result)) ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); ir_set_cursor_at_end_and_append_block(irb, else_block); - IrInstruction *else_expr_result; + IrInstSrc *else_expr_result; if (else_node) { else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base); - if (else_expr_result == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + if (else_expr_result == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; } else { else_expr_result = ir_build_const_void(irb, scope, node); ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); } - IrBasicBlock *after_else_block = irb->current_basic_block; + IrBasicBlockSrc *after_else_block = irb->current_basic_block; if (!instr_is_unreachable(else_expr_result)) ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); ir_set_cursor_at_end_and_append_block(irb, endif_block); - IrInstruction **incoming_values = allocate(2); + IrInstSrc **incoming_values = allocate(2); incoming_values[0] = then_expr_result; incoming_values[1] = else_expr_result; - IrBasicBlock **incoming_blocks = allocate(2, "IrBasicBlock *"); + IrBasicBlockSrc **incoming_blocks = allocate(2, "IrBasicBlockSrc *"); incoming_blocks[0] = after_then_block; incoming_blocks[1] = after_else_block; - IrInstruction *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent); + IrInstSrc *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent); return ir_expr_wrap(irb, scope, phi, result_loc); } -static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) { +static IrInstSrc *ir_gen_prefix_op_id_lval(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) { assert(node->type == NodeTypePrefixOpExpr); AstNode *expr_node = node->data.prefix_op_expr.primary_expr; - IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval, nullptr); - if (value == irb->codegen->invalid_instruction) + IrInstSrc *value = ir_gen_node_extra(irb, expr_node, scope, lval, nullptr); + if (value == irb->codegen->invalid_inst_src) return value; return ir_build_un_op(irb, scope, node, op_id, value); } -static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id) { +static IrInstSrc *ir_gen_prefix_op_id(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrUnOp op_id) { return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValNone); } -static IrInstruction *ir_expr_wrap(IrBuilder *irb, Scope *scope, IrInstruction *inst, ResultLoc *result_loc) { - if (inst == irb->codegen->invalid_instruction) return inst; - ir_build_end_expr(irb, scope, inst->source_node, inst, result_loc); +static IrInstSrc *ir_expr_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc) { + if (inst == irb->codegen->invalid_inst_src) return inst; + ir_build_end_expr(irb, scope, inst->base.source_node, inst, result_loc); return inst; } -static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval, +static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value, LVal lval, ResultLoc *result_loc) { // This logic must be kept in sync with // [STMT_EXPR_TEST_THING] <--- (search this token) - if (value == irb->codegen->invalid_instruction || + if (value == irb->codegen->invalid_inst_src || instr_is_unreachable(value) || - value->source_node->type == NodeTypeDefer || - value->id == IrInstructionIdDeclVarSrc) + value->base.source_node->type == NodeTypeDefer || + value->id == IrInstSrcIdDeclVar) { return value; } @@ -6613,7 +7640,7 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction * if (lval == LValPtr) { // We needed a pointer to a value, but we got a value. So we create // an instruction which just makes a pointer of it. - return ir_build_ref(irb, scope, value->source_node, value, false, false); + return ir_build_ref_src(irb, scope, value->base.source_node, value, false, false); } else if (result_loc != nullptr) { return ir_expr_wrap(irb, scope, value, result_loc); } else { @@ -6636,7 +7663,7 @@ static PtrLen star_token_to_ptr_len(TokenId token_id) { } } -static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_pointer_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypePointerType); PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id); @@ -6648,26 +7675,26 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode AstNode *expr_node = node->data.pointer_type.op_expr; AstNode *align_expr = node->data.pointer_type.align_expr; - IrInstruction *sentinel; + IrInstSrc *sentinel; if (sentinel_expr != nullptr) { sentinel = ir_gen_node(irb, sentinel_expr, scope); - if (sentinel == irb->codegen->invalid_instruction) + if (sentinel == irb->codegen->invalid_inst_src) return sentinel; } else { sentinel = nullptr; } - IrInstruction *align_value; + IrInstSrc *align_value; if (align_expr != nullptr) { align_value = ir_gen_node(irb, align_expr, scope); - if (align_value == irb->codegen->invalid_instruction) + if (align_value == irb->codegen->invalid_inst_src) return align_value; } else { align_value = nullptr; } - IrInstruction *child_type = ir_gen_node(irb, expr_node, scope); - if (child_type == irb->codegen->invalid_instruction) + IrInstSrc *child_type = ir_gen_node(irb, expr_node, scope); + if (child_type == irb->codegen->invalid_inst_src) return child_type; uint32_t bit_offset_start = 0; @@ -6677,7 +7704,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode bigint_append_buf(val_buf, node->data.pointer_type.bit_offset_start, 10); exec_add_error_node(irb->codegen, irb->exec, node, buf_sprintf("value %s too large for u32 bit offset", buf_ptr(val_buf))); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } bit_offset_start = bigint_as_u32(node->data.pointer_type.bit_offset_start); } @@ -6689,7 +7716,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode bigint_append_buf(val_buf, node->data.pointer_type.host_int_bytes, 10); exec_add_error_node(irb->codegen, irb->exec, node, buf_sprintf("value %s too large for u32 byte count", buf_ptr(val_buf))); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } host_int_bytes = bigint_as_u32(node->data.pointer_type.host_int_bytes); } @@ -6697,43 +7724,43 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode if (host_int_bytes != 0 && bit_offset_start >= host_int_bytes * 8) { exec_add_error_node(irb->codegen, irb->exec, node, buf_sprintf("bit offset starts after end of host integer")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } return ir_build_ptr_type(irb, scope, node, child_type, is_const, is_volatile, ptr_len, sentinel, align_value, bit_offset_start, host_int_bytes, is_allow_zero); } -static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node, +static IrInstSrc *ir_gen_catch_unreachable(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, AstNode *expr_node, LVal lval, ResultLoc *result_loc) { - IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); - if (err_union_ptr == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); + if (err_union_ptr == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, scope, source_node, err_union_ptr, true, false); - if (payload_ptr == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, scope, source_node, err_union_ptr, true, false); + if (payload_ptr == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; if (lval == LValPtr) return payload_ptr; - IrInstruction *load_ptr = ir_build_load_ptr(irb, scope, source_node, payload_ptr); + IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, source_node, payload_ptr); return ir_expr_wrap(irb, scope, load_ptr, result_loc); } -static IrInstruction *ir_gen_bool_not(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_bool_not(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypePrefixOpExpr); AstNode *expr_node = node->data.prefix_op_expr.primary_expr; - IrInstruction *value = ir_gen_node(irb, expr_node, scope); - if (value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *value = ir_gen_node(irb, expr_node, scope); + if (value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; return ir_build_bool_not(irb, scope, node, value); } -static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_prefix_op_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypePrefixOpExpr); @@ -6761,12 +7788,12 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod zig_unreachable(); } -static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *union_type, IrInstruction *field_name, AstNode *expr_node, +static IrInstSrc *ir_gen_union_init_expr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *union_type, IrInstSrc *field_name, AstNode *expr_node, LVal lval, ResultLoc *parent_result_loc) { - IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, source_node, parent_result_loc, union_type); - IrInstruction *field_ptr = ir_build_field_ptr_instruction(irb, scope, source_node, container_ptr, + IrInstSrc *container_ptr = ir_build_resolve_result(irb, scope, source_node, parent_result_loc, union_type); + IrInstSrc *field_ptr = ir_build_field_ptr_instruction(irb, scope, source_node, container_ptr, field_name, true); ResultLocInstruction *result_loc_inst = allocate(1); @@ -6775,18 +7802,18 @@ static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNo ir_ref_instruction(field_ptr, irb->current_basic_block); ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); - IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, + IrInstSrc *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, &result_loc_inst->base); - if (expr_value == irb->codegen->invalid_instruction) + if (expr_value == irb->codegen->invalid_inst_src) return expr_value; - IrInstruction *init_union = ir_build_union_init_named_field(irb, scope, source_node, union_type, + IrInstSrc *init_union = ir_build_union_init_named_field(irb, scope, source_node, union_type, field_name, field_ptr, container_ptr); return ir_lval_wrap(irb, scope, init_union, lval, parent_result_loc); } -static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_container_init_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *parent_result_loc) { assert(node->type == NodeTypeContainerInitExpr); @@ -6798,42 +7825,42 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A ResultLoc *child_result_loc; AstNode *init_array_type_source_node; if (container_init_expr->type != nullptr) { - IrInstruction *container_type; + IrInstSrc *container_type; if (container_init_expr->type->type == NodeTypeInferredArrayType) { if (kind == ContainerInitKindStruct) { add_node_error(irb->codegen, container_init_expr->type, buf_sprintf("initializing array with struct syntax")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } - IrInstruction *sentinel; + IrInstSrc *sentinel; if (container_init_expr->type->data.inferred_array_type.sentinel != nullptr) { sentinel = ir_gen_node(irb, container_init_expr->type->data.inferred_array_type.sentinel, scope); - if (sentinel == irb->codegen->invalid_instruction) + if (sentinel == irb->codegen->invalid_inst_src) return sentinel; } else { sentinel = nullptr; } - IrInstruction *elem_type = ir_gen_node(irb, + IrInstSrc *elem_type = ir_gen_node(irb, container_init_expr->type->data.inferred_array_type.child_type, scope); - if (elem_type == irb->codegen->invalid_instruction) + if (elem_type == irb->codegen->invalid_inst_src) return elem_type; size_t item_count = container_init_expr->entries.length; - IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count); + IrInstSrc *item_count_inst = ir_build_const_usize(irb, scope, node, item_count); container_type = ir_build_array_type(irb, scope, node, item_count_inst, sentinel, elem_type); } else { container_type = ir_gen_node(irb, container_init_expr->type, scope); - if (container_type == irb->codegen->invalid_instruction) + if (container_type == irb->codegen->invalid_inst_src) return container_type; } result_loc_cast = ir_build_cast_result_loc(irb, container_type, parent_result_loc); child_result_loc = &result_loc_cast->base; - init_array_type_source_node = container_type->source_node; + init_array_type_source_node = container_type->base.source_node; } else { child_result_loc = parent_result_loc; if (parent_result_loc->source_instruction != nullptr) { - init_array_type_source_node = parent_result_loc->source_instruction->source_node; + init_array_type_source_node = parent_result_loc->source_instruction->base.source_node; } else { init_array_type_source_node = node; } @@ -6841,11 +7868,11 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A switch (kind) { case ContainerInitKindStruct: { - IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc, + IrInstSrc *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc, nullptr); size_t field_count = container_init_expr->entries.length; - IrInstructionContainerInitFieldsField *fields = allocate(field_count); + IrInstSrcContainerInitFieldsField *fields = allocate(field_count); for (size_t i = 0; i < field_count; i += 1) { AstNode *entry_node = container_init_expr->entries.at(i); assert(entry_node->type == NodeTypeStructValueField); @@ -6853,7 +7880,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A Buf *name = entry_node->data.struct_val_field.name; AstNode *expr_node = entry_node->data.struct_val_field.expr; - IrInstruction *field_ptr = ir_build_field_ptr(irb, scope, entry_node, container_ptr, name, true); + IrInstSrc *field_ptr = ir_build_field_ptr(irb, scope, entry_node, container_ptr, name, true); ResultLocInstruction *result_loc_inst = allocate(1); result_loc_inst->base.id = ResultLocIdInstruction; result_loc_inst->base.source_instruction = field_ptr; @@ -6861,16 +7888,16 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A ir_ref_instruction(field_ptr, irb->current_basic_block); ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); - IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, + IrInstSrc *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, &result_loc_inst->base); - if (expr_value == irb->codegen->invalid_instruction) + if (expr_value == irb->codegen->invalid_inst_src) return expr_value; fields[i].name = name; fields[i].source_node = entry_node; fields[i].result_loc = field_ptr; } - IrInstruction *result = ir_build_container_init_fields(irb, scope, node, field_count, + IrInstSrc *result = ir_build_container_init_fields(irb, scope, node, field_count, fields, container_ptr); if (result_loc_cast != nullptr) { @@ -6881,15 +7908,15 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A case ContainerInitKindArray: { size_t item_count = container_init_expr->entries.length; - IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc, + IrInstSrc *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc, nullptr); - IrInstruction **result_locs = allocate(item_count); + IrInstSrc **result_locs = allocate(item_count); for (size_t i = 0; i < item_count; i += 1) { AstNode *expr_node = container_init_expr->entries.at(i); - IrInstruction *elem_index = ir_build_const_usize(irb, scope, expr_node, i); - IrInstruction *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr, + IrInstSrc *elem_index = ir_build_const_usize(irb, scope, expr_node, i); + IrInstSrc *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr, elem_index, false, PtrLenSingle, init_array_type_source_node); ResultLocInstruction *result_loc_inst = allocate(1); result_loc_inst->base.id = ResultLocIdInstruction; @@ -6898,14 +7925,14 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A ir_ref_instruction(elem_ptr, irb->current_basic_block); ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); - IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, + IrInstSrc *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, &result_loc_inst->base); - if (expr_value == irb->codegen->invalid_instruction) + if (expr_value == irb->codegen->invalid_inst_src) return expr_value; result_locs[i] = elem_ptr; } - IrInstruction *result = ir_build_container_init_list(irb, scope, node, item_count, + IrInstSrc *result = ir_build_container_init_list(irb, scope, node, item_count, result_locs, container_ptr, init_array_type_source_node); if (result_loc_cast != nullptr) { result = ir_build_implicit_cast(irb, scope, node, result, result_loc_cast); @@ -6916,19 +7943,19 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A zig_unreachable(); } -static ResultLocVar *ir_build_var_result_loc(IrBuilder *irb, IrInstruction *alloca, ZigVar *var) { +static ResultLocVar *ir_build_var_result_loc(IrBuilderSrc *irb, IrInstSrc *alloca, ZigVar *var) { ResultLocVar *result_loc_var = allocate(1); result_loc_var->base.id = ResultLocIdVar; result_loc_var->base.source_instruction = alloca; result_loc_var->base.allow_write_through_const = true; result_loc_var->var = var; - ir_build_reset_result(irb, alloca->scope, alloca->source_node, &result_loc_var->base); + ir_build_reset_result(irb, alloca->base.scope, alloca->base.source_node, &result_loc_var->base); return result_loc_var; } -static ResultLocCast *ir_build_cast_result_loc(IrBuilder *irb, IrInstruction *dest_type, +static ResultLocCast *ir_build_cast_result_loc(IrBuilderSrc *irb, IrInstSrc *dest_type, ResultLoc *parent_result_loc) { ResultLocCast *result_loc_cast = allocate(1); @@ -6938,37 +7965,37 @@ static ResultLocCast *ir_build_cast_result_loc(IrBuilder *irb, IrInstruction *de ir_ref_instruction(dest_type, irb->current_basic_block); result_loc_cast->parent = parent_result_loc; - ir_build_reset_result(irb, dest_type->scope, dest_type->source_node, &result_loc_cast->base); + ir_build_reset_result(irb, dest_type->base.scope, dest_type->base.source_node, &result_loc_cast->base); return result_loc_cast; } -static void build_decl_var_and_init(IrBuilder *irb, Scope *scope, AstNode *source_node, ZigVar *var, - IrInstruction *init, const char *name_hint, IrInstruction *is_comptime) +static void build_decl_var_and_init(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var, + IrInstSrc *init, const char *name_hint, IrInstSrc *is_comptime) { - IrInstruction *alloca = ir_build_alloca_src(irb, scope, source_node, nullptr, name_hint, is_comptime); + IrInstSrc *alloca = ir_build_alloca_src(irb, scope, source_node, nullptr, name_hint, is_comptime); ResultLocVar *var_result_loc = ir_build_var_result_loc(irb, alloca, var); ir_build_end_expr(irb, scope, source_node, init, &var_result_loc->base); ir_build_var_decl_src(irb, scope, source_node, var, nullptr, alloca); } -static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_var_decl(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeVariableDeclaration); AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration; if (buf_eql_str(variable_declaration->symbol, "_")) { add_node_error(irb->codegen, node, buf_sprintf("`_` is not a declarable symbol")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } // Used for the type expr and the align expr Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope); - IrInstruction *type_instruction; + IrInstSrc *type_instruction; if (variable_declaration->type != nullptr) { type_instruction = ir_gen_node(irb, variable_declaration->type, comptime_scope); - if (type_instruction == irb->codegen->invalid_instruction) + if (type_instruction == irb->codegen->invalid_inst_src) return type_instruction; } else { type_instruction = nullptr; @@ -6979,22 +8006,22 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod bool is_extern = variable_declaration->is_extern; bool is_comptime_scalar = ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime; - IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, is_comptime_scalar); + IrInstSrc *is_comptime = ir_build_const_bool(irb, scope, node, is_comptime_scalar); ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol, is_const, is_const, is_shadowable, is_comptime); - // we detect IrInstructionIdDeclVarSrc in gen_block to make sure the next node + // we detect IrInstSrcDeclVar in gen_block to make sure the next node // is inside var->child_scope if (!is_extern && !variable_declaration->expr) { var->var_type = irb->codegen->builtin_types.entry_invalid; add_node_error(irb->codegen, node, buf_sprintf("variables must be initialized")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } - IrInstruction *align_value = nullptr; + IrInstSrc *align_value = nullptr; if (variable_declaration->align_expr != nullptr) { align_value = ir_gen_node(irb, variable_declaration->align_expr, comptime_scope); - if (align_value == irb->codegen->invalid_instruction) + if (align_value == irb->codegen->invalid_inst_src) return align_value; } @@ -7006,7 +8033,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod // Parser should ensure that this never happens assert(variable_declaration->threadlocal_tok == nullptr); - IrInstruction *alloca = ir_build_alloca_src(irb, scope, node, align_value, + IrInstSrc *alloca = ir_build_alloca_src(irb, scope, node, align_value, buf_ptr(variable_declaration->symbol), is_comptime); // Create a result location for the initialization expression. @@ -7024,19 +8051,19 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod Scope *init_scope = is_comptime_scalar ? create_comptime_scope(irb->codegen, variable_declaration->expr, scope) : scope; - // Temporarily set the name of the IrExecutable to the VariableDeclaration + // Temporarily set the name of the IrExecutableSrc to the VariableDeclaration // so that the struct or enum from the init expression inherits the name. Buf *old_exec_name = irb->exec->name; irb->exec->name = variable_declaration->symbol; - IrInstruction *init_value = ir_gen_node_extra(irb, variable_declaration->expr, init_scope, + IrInstSrc *init_value = ir_gen_node_extra(irb, variable_declaration->expr, init_scope, LValNone, init_result_loc); irb->exec->name = old_exec_name; - if (init_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + if (init_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; if (result_loc_cast != nullptr) { - IrInstruction *implicit_cast = ir_build_implicit_cast(irb, scope, init_value->source_node, + IrInstSrc *implicit_cast = ir_build_implicit_cast(irb, scope, init_value->base.source_node, init_value, result_loc_cast); ir_build_end_expr(irb, scope, node, implicit_cast, &result_loc_var->base); } @@ -7044,7 +8071,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod return ir_build_var_decl_src(irb, scope, node, var, align_value, alloca); } -static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeWhileExpr); @@ -7052,15 +8079,15 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n AstNode *continue_expr_node = node->data.while_expr.continue_expr; AstNode *else_node = node->data.while_expr.else_node; - IrBasicBlock *cond_block = ir_create_basic_block(irb, scope, "WhileCond"); - IrBasicBlock *body_block = ir_create_basic_block(irb, scope, "WhileBody"); - IrBasicBlock *continue_block = continue_expr_node ? + IrBasicBlockSrc *cond_block = ir_create_basic_block(irb, scope, "WhileCond"); + IrBasicBlockSrc *body_block = ir_create_basic_block(irb, scope, "WhileBody"); + IrBasicBlockSrc *continue_block = continue_expr_node ? ir_create_basic_block(irb, scope, "WhileContinue") : cond_block; - IrBasicBlock *end_block = ir_create_basic_block(irb, scope, "WhileEnd"); - IrBasicBlock *else_block = else_node ? + IrBasicBlockSrc *end_block = ir_create_basic_block(irb, scope, "WhileEnd"); + IrBasicBlockSrc *else_block = else_node ? ir_create_basic_block(irb, scope, "WhileElse") : end_block; - IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, + IrInstSrc *is_comptime = ir_build_const_bool(irb, scope, node, ir_should_inline(irb->exec, scope) || node->data.while_expr.is_inline); ir_build_br(irb, scope, node, cond_block, is_comptime); @@ -7081,15 +8108,15 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n } else { payload_scope = subexpr_scope; } - IrInstruction *err_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, + IrInstSrc *err_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, LValPtr, nullptr); - if (err_val_ptr == irb->codegen->invalid_instruction) + if (err_val_ptr == irb->codegen->invalid_inst_src) return err_val_ptr; - IrInstruction *is_err = ir_build_test_err_src(irb, scope, node->data.while_expr.condition, err_val_ptr, + IrInstSrc *is_err = ir_build_test_err_src(irb, scope, node->data.while_expr.condition, err_val_ptr, true, false); - IrBasicBlock *after_cond_block = irb->current_basic_block; - IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); - IrInstruction *cond_br_inst; + IrBasicBlockSrc *after_cond_block = irb->current_basic_block; + IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); + IrInstSrc *cond_br_inst; if (!instr_is_unreachable(is_err)) { cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_err, else_block, body_block, is_comptime); @@ -7104,15 +8131,15 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n ir_set_cursor_at_end_and_append_block(irb, body_block); if (var_symbol) { - IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, payload_scope, symbol_node, + IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, payload_scope, symbol_node, err_val_ptr, false, false); - IrInstruction *var_ptr = node->data.while_expr.var_is_ptr ? - ir_build_ref(irb, payload_scope, symbol_node, payload_ptr, true, false) : payload_ptr; + IrInstSrc *var_ptr = node->data.while_expr.var_is_ptr ? + ir_build_ref_src(irb, payload_scope, symbol_node, payload_ptr, true, false) : payload_ptr; ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, var_ptr); } - ZigList incoming_values = {0}; - ZigList incoming_blocks = {0}; + ZigList incoming_values = {0}; + ZigList incoming_blocks = {0}; ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, payload_scope); loop_scope->break_block = end_block; @@ -7126,8 +8153,8 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n // Note the body block of the loop is not the place that lval and result_loc are used - // it's actually in break statements, handled similarly to return statements. // That is why we set those values in loop_scope above and not in this ir_gen_node call. - IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); - if (body_result == irb->codegen->invalid_instruction) + IrInstSrc *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); + if (body_result == irb->codegen->invalid_inst_src) return body_result; if (!instr_is_unreachable(body_result)) { @@ -7137,8 +8164,8 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n if (continue_expr_node) { ir_set_cursor_at_end_and_append_block(irb, continue_block); - IrInstruction *expr_result = ir_gen_node(irb, continue_expr_node, payload_scope); - if (expr_result == irb->codegen->invalid_instruction) + IrInstSrc *expr_result = ir_gen_node(irb, continue_expr_node, payload_scope); + if (expr_result == irb->codegen->invalid_inst_src) return expr_result; if (!instr_is_unreachable(expr_result)) { ir_mark_gen(ir_build_check_statement_is_void(irb, payload_scope, continue_expr_node, expr_result)); @@ -7154,7 +8181,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n ZigVar *err_var = ir_create_var(irb, err_symbol_node, scope, err_symbol, true, false, false, is_comptime); Scope *err_scope = err_var->child_scope; - IrInstruction *err_ptr = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr); + IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, err_scope, err_symbol_node, err_val_ptr); ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, err_ptr); if (peer_parent->peers.length != 0) { @@ -7162,12 +8189,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n } ResultLocPeer *peer_result = create_peer_result(peer_parent); peer_parent->peers.append(peer_result); - IrInstruction *else_result = ir_gen_node_extra(irb, else_node, err_scope, lval, &peer_result->base); - if (else_result == irb->codegen->invalid_instruction) + IrInstSrc *else_result = ir_gen_node_extra(irb, else_node, err_scope, lval, &peer_result->base); + if (else_result == irb->codegen->invalid_inst_src) return else_result; if (!instr_is_unreachable(else_result)) ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime)); - IrBasicBlock *after_else_block = irb->current_basic_block; + IrBasicBlockSrc *after_else_block = irb->current_basic_block; ir_set_cursor_at_end_and_append_block(irb, end_block); if (else_result) { incoming_blocks.append(after_else_block); @@ -7180,7 +8207,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n peer_parent->peers.last()->next_bb = end_block; } - IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, + IrInstSrc *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items, peer_parent); return ir_expr_wrap(irb, scope, phi, result_loc); } else if (var_symbol != nullptr) { @@ -7192,15 +8219,15 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n ZigVar *payload_var = ir_create_var(irb, symbol_node, subexpr_scope, var_symbol, true, false, false, is_comptime); Scope *child_scope = payload_var->child_scope; - IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, + IrInstSrc *maybe_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, LValPtr, nullptr); - if (maybe_val_ptr == irb->codegen->invalid_instruction) + if (maybe_val_ptr == irb->codegen->invalid_inst_src) return maybe_val_ptr; - IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, maybe_val_ptr); - IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node->data.while_expr.condition, maybe_val); - IrBasicBlock *after_cond_block = irb->current_basic_block; - IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); - IrInstruction *cond_br_inst; + IrInstSrc *maybe_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, maybe_val_ptr); + IrInstSrc *is_non_null = ir_build_test_non_null_src(irb, scope, node->data.while_expr.condition, maybe_val); + IrBasicBlockSrc *after_cond_block = irb->current_basic_block; + IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); + IrInstSrc *cond_br_inst; if (!instr_is_unreachable(is_non_null)) { cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_non_null, body_block, else_block, is_comptime); @@ -7214,13 +8241,13 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n is_comptime); ir_set_cursor_at_end_and_append_block(irb, body_block); - IrInstruction *payload_ptr = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false, false); - IrInstruction *var_ptr = node->data.while_expr.var_is_ptr ? - ir_build_ref(irb, child_scope, symbol_node, payload_ptr, true, false) : payload_ptr; + IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false, false); + IrInstSrc *var_ptr = node->data.while_expr.var_is_ptr ? + ir_build_ref_src(irb, child_scope, symbol_node, payload_ptr, true, false) : payload_ptr; ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, var_ptr); - ZigList incoming_values = {0}; - ZigList incoming_blocks = {0}; + ZigList incoming_values = {0}; + ZigList incoming_blocks = {0}; ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, child_scope); loop_scope->break_block = end_block; @@ -7234,8 +8261,8 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n // Note the body block of the loop is not the place that lval and result_loc are used - // it's actually in break statements, handled similarly to return statements. // That is why we set those values in loop_scope above and not in this ir_gen_node call. - IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); - if (body_result == irb->codegen->invalid_instruction) + IrInstSrc *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); + if (body_result == irb->codegen->invalid_inst_src) return body_result; if (!instr_is_unreachable(body_result)) { @@ -7245,8 +8272,8 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n if (continue_expr_node) { ir_set_cursor_at_end_and_append_block(irb, continue_block); - IrInstruction *expr_result = ir_gen_node(irb, continue_expr_node, child_scope); - if (expr_result == irb->codegen->invalid_instruction) + IrInstSrc *expr_result = ir_gen_node(irb, continue_expr_node, child_scope); + if (expr_result == irb->codegen->invalid_inst_src) return expr_result; if (!instr_is_unreachable(expr_result)) { ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, continue_expr_node, expr_result)); @@ -7254,7 +8281,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n } } - IrInstruction *else_result = nullptr; + IrInstSrc *else_result = nullptr; if (else_node) { ir_set_cursor_at_end_and_append_block(irb, else_block); @@ -7264,12 +8291,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n ResultLocPeer *peer_result = create_peer_result(peer_parent); peer_parent->peers.append(peer_result); else_result = ir_gen_node_extra(irb, else_node, scope, lval, &peer_result->base); - if (else_result == irb->codegen->invalid_instruction) + if (else_result == irb->codegen->invalid_inst_src) return else_result; if (!instr_is_unreachable(else_result)) ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime)); } - IrBasicBlock *after_else_block = irb->current_basic_block; + IrBasicBlockSrc *after_else_block = irb->current_basic_block; ir_set_cursor_at_end_and_append_block(irb, end_block); if (else_result) { incoming_blocks.append(after_else_block); @@ -7282,17 +8309,17 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n peer_parent->peers.last()->next_bb = end_block; } - IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, + IrInstSrc *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items, peer_parent); return ir_expr_wrap(irb, scope, phi, result_loc); } else { ir_set_cursor_at_end_and_append_block(irb, cond_block); - IrInstruction *cond_val = ir_gen_node(irb, node->data.while_expr.condition, scope); - if (cond_val == irb->codegen->invalid_instruction) + IrInstSrc *cond_val = ir_gen_node(irb, node->data.while_expr.condition, scope); + if (cond_val == irb->codegen->invalid_inst_src) return cond_val; - IrBasicBlock *after_cond_block = irb->current_basic_block; - IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); - IrInstruction *cond_br_inst; + IrBasicBlockSrc *after_cond_block = irb->current_basic_block; + IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); + IrInstSrc *cond_br_inst; if (!instr_is_unreachable(cond_val)) { cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, cond_val, body_block, else_block, is_comptime); @@ -7306,8 +8333,8 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n is_comptime); ir_set_cursor_at_end_and_append_block(irb, body_block); - ZigList incoming_values = {0}; - ZigList incoming_blocks = {0}; + ZigList incoming_values = {0}; + ZigList incoming_blocks = {0}; Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); @@ -7323,8 +8350,8 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n // Note the body block of the loop is not the place that lval and result_loc are used - // it's actually in break statements, handled similarly to return statements. // That is why we set those values in loop_scope above and not in this ir_gen_node call. - IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); - if (body_result == irb->codegen->invalid_instruction) + IrInstSrc *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); + if (body_result == irb->codegen->invalid_inst_src) return body_result; if (!instr_is_unreachable(body_result)) { @@ -7334,8 +8361,8 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n if (continue_expr_node) { ir_set_cursor_at_end_and_append_block(irb, continue_block); - IrInstruction *expr_result = ir_gen_node(irb, continue_expr_node, subexpr_scope); - if (expr_result == irb->codegen->invalid_instruction) + IrInstSrc *expr_result = ir_gen_node(irb, continue_expr_node, subexpr_scope); + if (expr_result == irb->codegen->invalid_inst_src) return expr_result; if (!instr_is_unreachable(expr_result)) { ir_mark_gen(ir_build_check_statement_is_void(irb, scope, continue_expr_node, expr_result)); @@ -7343,7 +8370,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n } } - IrInstruction *else_result = nullptr; + IrInstSrc *else_result = nullptr; if (else_node) { ir_set_cursor_at_end_and_append_block(irb, else_block); @@ -7354,12 +8381,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n peer_parent->peers.append(peer_result); else_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_result->base); - if (else_result == irb->codegen->invalid_instruction) + if (else_result == irb->codegen->invalid_inst_src) return else_result; if (!instr_is_unreachable(else_result)) ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime)); } - IrBasicBlock *after_else_block = irb->current_basic_block; + IrBasicBlockSrc *after_else_block = irb->current_basic_block; ir_set_cursor_at_end_and_append_block(irb, end_block); if (else_result) { incoming_blocks.append(after_else_block); @@ -7372,13 +8399,13 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n peer_parent->peers.last()->next_bb = end_block; } - IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, + IrInstSrc *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items, peer_parent); return ir_expr_wrap(irb, scope, phi, result_loc); } } -static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_for_expr(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeForExpr); @@ -7391,17 +8418,17 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo if (!elem_node) { add_node_error(irb->codegen, node, buf_sprintf("for loop expression missing element parameter")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } assert(elem_node->type == NodeTypeSymbol); ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, parent_scope); - IrInstruction *array_val_ptr = ir_gen_node_extra(irb, array_node, &spill_scope->base, LValPtr, nullptr); - if (array_val_ptr == irb->codegen->invalid_instruction) + IrInstSrc *array_val_ptr = ir_gen_node_extra(irb, array_node, &spill_scope->base, LValPtr, nullptr); + if (array_val_ptr == irb->codegen->invalid_inst_src) return array_val_ptr; - IrInstruction *is_comptime = ir_build_const_bool(irb, parent_scope, node, + IrInstSrc *is_comptime = ir_build_const_bool(irb, parent_scope, node, ir_should_inline(irb->exec, parent_scope) || node->data.for_expr.is_inline); AstNode *index_var_source_node; @@ -7418,50 +8445,50 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo index_var_name = "i"; } - IrInstruction *zero = ir_build_const_usize(irb, parent_scope, node, 0); + IrInstSrc *zero = ir_build_const_usize(irb, parent_scope, node, 0); build_decl_var_and_init(irb, parent_scope, index_var_source_node, index_var, zero, index_var_name, is_comptime); parent_scope = index_var->child_scope; - IrInstruction *one = ir_build_const_usize(irb, parent_scope, node, 1); - IrInstruction *index_ptr = ir_build_var_ptr(irb, parent_scope, node, index_var); + IrInstSrc *one = ir_build_const_usize(irb, parent_scope, node, 1); + IrInstSrc *index_ptr = ir_build_var_ptr(irb, parent_scope, node, index_var); - IrBasicBlock *cond_block = ir_create_basic_block(irb, parent_scope, "ForCond"); - IrBasicBlock *body_block = ir_create_basic_block(irb, parent_scope, "ForBody"); - IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "ForEnd"); - IrBasicBlock *else_block = else_node ? ir_create_basic_block(irb, parent_scope, "ForElse") : end_block; - IrBasicBlock *continue_block = ir_create_basic_block(irb, parent_scope, "ForContinue"); + IrBasicBlockSrc *cond_block = ir_create_basic_block(irb, parent_scope, "ForCond"); + IrBasicBlockSrc *body_block = ir_create_basic_block(irb, parent_scope, "ForBody"); + IrBasicBlockSrc *end_block = ir_create_basic_block(irb, parent_scope, "ForEnd"); + IrBasicBlockSrc *else_block = else_node ? ir_create_basic_block(irb, parent_scope, "ForElse") : end_block; + IrBasicBlockSrc *continue_block = ir_create_basic_block(irb, parent_scope, "ForContinue"); Buf *len_field_name = buf_create_from_str("len"); - IrInstruction *len_ref = ir_build_field_ptr(irb, parent_scope, node, array_val_ptr, len_field_name, false); - IrInstruction *len_val = ir_build_load_ptr(irb, &spill_scope->base, node, len_ref); + IrInstSrc *len_ref = ir_build_field_ptr(irb, parent_scope, node, array_val_ptr, len_field_name, false); + IrInstSrc *len_val = ir_build_load_ptr(irb, &spill_scope->base, node, len_ref); ir_build_br(irb, parent_scope, node, cond_block, is_comptime); ir_set_cursor_at_end_and_append_block(irb, cond_block); - IrInstruction *index_val = ir_build_load_ptr(irb, &spill_scope->base, node, index_ptr); - IrInstruction *cond = ir_build_bin_op(irb, parent_scope, node, IrBinOpCmpLessThan, index_val, len_val, false); - IrBasicBlock *after_cond_block = irb->current_basic_block; - IrInstruction *void_else_value = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, parent_scope, node)); - IrInstruction *cond_br_inst = ir_mark_gen(ir_build_cond_br(irb, parent_scope, node, cond, + IrInstSrc *index_val = ir_build_load_ptr(irb, &spill_scope->base, node, index_ptr); + IrInstSrc *cond = ir_build_bin_op(irb, parent_scope, node, IrBinOpCmpLessThan, index_val, len_val, false); + IrBasicBlockSrc *after_cond_block = irb->current_basic_block; + IrInstSrc *void_else_value = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, parent_scope, node)); + IrInstSrc *cond_br_inst = ir_mark_gen(ir_build_cond_br(irb, parent_scope, node, cond, body_block, else_block, is_comptime)); ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, is_comptime); ir_set_cursor_at_end_and_append_block(irb, body_block); Scope *elem_ptr_scope = node->data.for_expr.elem_is_ptr ? parent_scope : &spill_scope->base; - IrInstruction *elem_ptr = ir_build_elem_ptr(irb, elem_ptr_scope, node, array_val_ptr, index_val, false, + IrInstSrc *elem_ptr = ir_build_elem_ptr(irb, elem_ptr_scope, node, array_val_ptr, index_val, false, PtrLenSingle, nullptr); // TODO make it an error to write to element variable or i variable. Buf *elem_var_name = elem_node->data.symbol_expr.symbol; ZigVar *elem_var = ir_create_var(irb, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime); Scope *child_scope = elem_var->child_scope; - IrInstruction *var_ptr = node->data.for_expr.elem_is_ptr ? - ir_build_ref(irb, &spill_scope->base, elem_node, elem_ptr, true, false) : elem_ptr; + IrInstSrc *var_ptr = node->data.for_expr.elem_is_ptr ? + ir_build_ref_src(irb, &spill_scope->base, elem_node, elem_ptr, true, false) : elem_ptr; ir_build_var_decl_src(irb, parent_scope, elem_node, elem_var, nullptr, var_ptr); - ZigList incoming_values = {0}; - ZigList incoming_blocks = {0}; + ZigList incoming_values = {0}; + ZigList incoming_blocks = {0}; ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, child_scope); loop_scope->break_block = end_block; loop_scope->continue_block = continue_block; @@ -7475,9 +8502,9 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo // Note the body block of the loop is not the place that lval and result_loc are used - // it's actually in break statements, handled similarly to return statements. // That is why we set those values in loop_scope above and not in this ir_gen_node call. - IrInstruction *body_result = ir_gen_node(irb, body_node, &loop_scope->base); - if (body_result == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *body_result = ir_gen_node(irb, body_node, &loop_scope->base); + if (body_result == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; if (!instr_is_unreachable(body_result)) { ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.for_expr.body, body_result)); @@ -7485,11 +8512,11 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo } ir_set_cursor_at_end_and_append_block(irb, continue_block); - IrInstruction *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false); + IrInstSrc *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false); ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val)->allow_write_through_const = true; ir_build_br(irb, child_scope, node, cond_block, is_comptime); - IrInstruction *else_result = nullptr; + IrInstSrc *else_result = nullptr; if (else_node) { ir_set_cursor_at_end_and_append_block(irb, else_block); @@ -7499,12 +8526,12 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo ResultLocPeer *peer_result = create_peer_result(peer_parent); peer_parent->peers.append(peer_result); else_result = ir_gen_node_extra(irb, else_node, parent_scope, LValNone, &peer_result->base); - if (else_result == irb->codegen->invalid_instruction) + if (else_result == irb->codegen->invalid_inst_src) return else_result; if (!instr_is_unreachable(else_result)) ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime)); } - IrBasicBlock *after_else_block = irb->current_basic_block; + IrBasicBlockSrc *after_else_block = irb->current_basic_block; ir_set_cursor_at_end_and_append_block(irb, end_block); if (else_result) { @@ -7518,29 +8545,29 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo peer_parent->peers.last()->next_bb = end_block; } - IrInstruction *phi = ir_build_phi(irb, parent_scope, node, incoming_blocks.length, + IrInstSrc *phi = ir_build_phi(irb, parent_scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items, peer_parent); return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc); } -static IrInstruction *ir_gen_bool_literal(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_bool_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeBoolLiteral); return ir_build_const_bool(irb, scope, node, node->data.bool_literal.value); } -static IrInstruction *ir_gen_enum_literal(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_enum_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeEnumLiteral); Buf *name = &node->data.enum_literal.identifier->data.str_lit.str; return ir_build_const_enum_literal(irb, scope, node, name); } -static IrInstruction *ir_gen_string_literal(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_string_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeStringLiteral); return ir_build_const_str_lit(irb, scope, node, node->data.string_literal.buf); } -static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_array_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeArrayType); AstNode *size_node = node->data.array_type.size; @@ -7553,10 +8580,10 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope); - IrInstruction *sentinel; + IrInstSrc *sentinel; if (sentinel_expr != nullptr) { sentinel = ir_gen_node(irb, sentinel_expr, comptime_scope); - if (sentinel == irb->codegen->invalid_instruction) + if (sentinel == irb->codegen->invalid_inst_src) return sentinel; } else { sentinel = nullptr; @@ -7565,42 +8592,42 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n if (size_node) { if (is_const) { add_node_error(irb->codegen, node, buf_create_from_str("const qualifier invalid on array type")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } if (is_volatile) { add_node_error(irb->codegen, node, buf_create_from_str("volatile qualifier invalid on array type")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } if (is_allow_zero) { add_node_error(irb->codegen, node, buf_create_from_str("allowzero qualifier invalid on array type")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } if (align_expr != nullptr) { add_node_error(irb->codegen, node, buf_create_from_str("align qualifier invalid on array type")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } - IrInstruction *size_value = ir_gen_node(irb, size_node, comptime_scope); - if (size_value == irb->codegen->invalid_instruction) + IrInstSrc *size_value = ir_gen_node(irb, size_node, comptime_scope); + if (size_value == irb->codegen->invalid_inst_src) return size_value; - IrInstruction *child_type = ir_gen_node(irb, child_type_node, comptime_scope); - if (child_type == irb->codegen->invalid_instruction) + IrInstSrc *child_type = ir_gen_node(irb, child_type_node, comptime_scope); + if (child_type == irb->codegen->invalid_inst_src) return child_type; return ir_build_array_type(irb, scope, node, size_value, sentinel, child_type); } else { - IrInstruction *align_value; + IrInstSrc *align_value; if (align_expr != nullptr) { align_value = ir_gen_node(irb, align_expr, comptime_scope); - if (align_value == irb->codegen->invalid_instruction) + if (align_value == irb->codegen->invalid_inst_src) return align_value; } else { align_value = nullptr; } - IrInstruction *child_type = ir_gen_node(irb, child_type_node, comptime_scope); - if (child_type == irb->codegen->invalid_instruction) + IrInstSrc *child_type = ir_gen_node(irb, child_type_node, comptime_scope); + if (child_type == irb->codegen->invalid_inst_src) return child_type; return ir_build_slice_type(irb, scope, node, child_type, is_const, is_volatile, sentinel, @@ -7608,15 +8635,15 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n } } -static IrInstruction *ir_gen_anyframe_type(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_anyframe_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeAnyFrameType); AstNode *payload_type_node = node->data.anyframe_type.payload_type; - IrInstruction *payload_type_value = nullptr; + IrInstSrc *payload_type_value = nullptr; if (payload_type_node != nullptr) { payload_type_value = ir_gen_node(irb, payload_type_node, scope); - if (payload_type_value == irb->codegen->invalid_instruction) + if (payload_type_value == irb->codegen->invalid_inst_src) return payload_type_value; } @@ -7624,7 +8651,7 @@ static IrInstruction *ir_gen_anyframe_type(IrBuilder *irb, Scope *scope, AstNode return ir_build_anyframe_type(irb, scope, node, payload_type_value); } -static IrInstruction *ir_gen_undefined_literal(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_undefined_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeUndefinedLiteral); return ir_build_const_undefined(irb, scope, node); } @@ -7741,13 +8768,13 @@ static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok, Buf *src_ return SIZE_MAX; } -static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_asm_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeAsmExpr); AstNodeAsmExpr *asm_expr = &node->data.asm_expr; - IrInstruction *asm_template = ir_gen_node(irb, asm_expr->asm_template, scope); - if (asm_template == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *asm_template = ir_gen_node(irb, asm_expr->asm_template, scope); + if (asm_template == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; bool is_volatile = asm_expr->volatile_token != nullptr; bool in_fn_scope = (scope_fn_entry(scope) != nullptr); @@ -7756,7 +8783,7 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod if (is_volatile) { add_token_error(irb->codegen, node->owner, asm_expr->volatile_token, buf_sprintf("volatile is meaningless on global assembly")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } if (asm_expr->output_list.length != 0 || asm_expr->input_list.length != 0 || @@ -7764,34 +8791,34 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod { add_node_error(irb->codegen, node, buf_sprintf("global assembly cannot have inputs, outputs, or clobbers")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } return ir_build_asm_src(irb, scope, node, asm_template, nullptr, nullptr, nullptr, 0, is_volatile, true); } - IrInstruction **input_list = allocate(asm_expr->input_list.length); - IrInstruction **output_types = allocate(asm_expr->output_list.length); + IrInstSrc **input_list = allocate(asm_expr->input_list.length); + IrInstSrc **output_types = allocate(asm_expr->output_list.length); ZigVar **output_vars = allocate(asm_expr->output_list.length); size_t return_count = 0; if (!is_volatile && asm_expr->output_list.length == 0) { add_node_error(irb->codegen, node, buf_sprintf("assembly expression with no output must be marked volatile")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } for (size_t i = 0; i < asm_expr->output_list.length; i += 1) { AsmOutput *asm_output = asm_expr->output_list.at(i); if (asm_output->return_type) { return_count += 1; - IrInstruction *return_type = ir_gen_node(irb, asm_output->return_type, scope); - if (return_type == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *return_type = ir_gen_node(irb, asm_output->return_type, scope); + if (return_type == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; if (return_count > 1) { add_node_error(irb->codegen, node, buf_sprintf("inline assembly allows up to one output value")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } output_types[i] = return_type; } else { @@ -7804,7 +8831,7 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod } else { add_node_error(irb->codegen, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name))); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } } @@ -7814,14 +8841,14 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod buf_sprintf("invalid modifier starting output constraint for '%s': '%c', only '=' is supported." " Compiler TODO: see https://github.com/ziglang/zig/issues/215", buf_ptr(asm_output->asm_symbolic_name), modifier)); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } } for (size_t i = 0; i < asm_expr->input_list.length; i += 1) { AsmInput *asm_input = asm_expr->input_list.at(i); - IrInstruction *input_value = ir_gen_node(irb, asm_input->expr, scope); - if (input_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *input_value = ir_gen_node(irb, asm_input->expr, scope); + if (input_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; input_list[i] = input_value; } @@ -7830,7 +8857,7 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod output_vars, return_count, is_volatile, false); } -static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_if_optional_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeIfOptional); @@ -7841,24 +8868,24 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN AstNode *else_node = node->data.test_expr.else_node; bool var_is_ptr = node->data.test_expr.var_is_ptr; - IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); - if (maybe_val_ptr == irb->codegen->invalid_instruction) + IrInstSrc *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); + if (maybe_val_ptr == irb->codegen->invalid_inst_src) return maybe_val_ptr; - IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node, maybe_val_ptr); - IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, maybe_val); + IrInstSrc *maybe_val = ir_build_load_ptr(irb, scope, node, maybe_val_ptr); + IrInstSrc *is_non_null = ir_build_test_non_null_src(irb, scope, node, maybe_val); - IrBasicBlock *then_block = ir_create_basic_block(irb, scope, "OptionalThen"); - IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "OptionalElse"); - IrBasicBlock *endif_block = ir_create_basic_block(irb, scope, "OptionalEndIf"); + IrBasicBlockSrc *then_block = ir_create_basic_block(irb, scope, "OptionalThen"); + IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "OptionalElse"); + IrBasicBlockSrc *endif_block = ir_create_basic_block(irb, scope, "OptionalEndIf"); - IrInstruction *is_comptime; + IrInstSrc *is_comptime; if (ir_should_inline(irb->exec, scope)) { is_comptime = ir_build_const_bool(irb, scope, node, true); } else { is_comptime = ir_build_test_comptime(irb, scope, node, is_non_null); } - IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, is_non_null, + IrInstSrc *cond_br_inst = ir_build_cond_br(irb, scope, node, is_non_null, then_block, else_block, is_comptime); ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block, @@ -7874,48 +8901,48 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN ZigVar *var = ir_create_var(irb, node, subexpr_scope, var_symbol, is_const, is_const, is_shadowable, is_comptime); - IrInstruction *payload_ptr = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false, false); - IrInstruction *var_ptr = var_is_ptr ? ir_build_ref(irb, subexpr_scope, node, payload_ptr, true, false) : payload_ptr; + IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false, false); + IrInstSrc *var_ptr = var_is_ptr ? ir_build_ref_src(irb, subexpr_scope, node, payload_ptr, true, false) : payload_ptr; ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, var_ptr); var_scope = var->child_scope; } else { var_scope = subexpr_scope; } - IrInstruction *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval, + IrInstSrc *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval, &peer_parent->peers.at(0)->base); - if (then_expr_result == irb->codegen->invalid_instruction) + if (then_expr_result == irb->codegen->invalid_inst_src) return then_expr_result; - IrBasicBlock *after_then_block = irb->current_basic_block; + IrBasicBlockSrc *after_then_block = irb->current_basic_block; if (!instr_is_unreachable(then_expr_result)) ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); ir_set_cursor_at_end_and_append_block(irb, else_block); - IrInstruction *else_expr_result; + IrInstSrc *else_expr_result; if (else_node) { else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base); - if (else_expr_result == irb->codegen->invalid_instruction) + if (else_expr_result == irb->codegen->invalid_inst_src) return else_expr_result; } else { else_expr_result = ir_build_const_void(irb, scope, node); ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); } - IrBasicBlock *after_else_block = irb->current_basic_block; + IrBasicBlockSrc *after_else_block = irb->current_basic_block; if (!instr_is_unreachable(else_expr_result)) ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); ir_set_cursor_at_end_and_append_block(irb, endif_block); - IrInstruction **incoming_values = allocate(2); + IrInstSrc **incoming_values = allocate(2); incoming_values[0] = then_expr_result; incoming_values[1] = else_expr_result; - IrBasicBlock **incoming_blocks = allocate(2, "IrBasicBlock *"); + IrBasicBlockSrc **incoming_blocks = allocate(2, "IrBasicBlockSrc *"); incoming_blocks[0] = after_then_block; incoming_blocks[1] = after_else_block; - IrInstruction *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent); + IrInstSrc *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent); return ir_expr_wrap(irb, scope, phi, result_loc); } -static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_if_err_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeIfErrorExpr); @@ -7928,20 +8955,20 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * Buf *var_symbol = node->data.if_err_expr.var_symbol; Buf *err_symbol = node->data.if_err_expr.err_symbol; - IrInstruction *err_val_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr, nullptr); - if (err_val_ptr == irb->codegen->invalid_instruction) + IrInstSrc *err_val_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr, nullptr); + if (err_val_ptr == irb->codegen->invalid_inst_src) return err_val_ptr; - IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr); - IrInstruction *is_err = ir_build_test_err_src(irb, scope, node, err_val_ptr, true, false); + IrInstSrc *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr); + IrInstSrc *is_err = ir_build_test_err_src(irb, scope, node, err_val_ptr, true, false); - IrBasicBlock *ok_block = ir_create_basic_block(irb, scope, "TryOk"); - IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "TryElse"); - IrBasicBlock *endif_block = ir_create_basic_block(irb, scope, "TryEnd"); + IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, scope, "TryOk"); + IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "TryElse"); + IrBasicBlockSrc *endif_block = ir_create_basic_block(irb, scope, "TryEnd"); bool force_comptime = ir_should_inline(irb->exec, scope); - IrInstruction *is_comptime = force_comptime ? ir_build_const_bool(irb, scope, node, true) : ir_build_test_comptime(irb, scope, node, is_err); - IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime); + IrInstSrc *is_comptime = force_comptime ? ir_build_const_bool(irb, scope, node, true) : ir_build_test_comptime(irb, scope, node, is_err); + IrInstSrc *cond_br_inst = ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime); ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block, result_loc, is_comptime); @@ -7952,29 +8979,29 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * Scope *var_scope; if (var_symbol) { bool is_shadowable = false; - IrInstruction *var_is_comptime = force_comptime ? ir_build_const_bool(irb, subexpr_scope, node, true) : ir_build_test_comptime(irb, subexpr_scope, node, err_val); + IrInstSrc *var_is_comptime = force_comptime ? ir_build_const_bool(irb, subexpr_scope, node, true) : ir_build_test_comptime(irb, subexpr_scope, node, err_val); ZigVar *var = ir_create_var(irb, node, subexpr_scope, var_symbol, var_is_const, var_is_const, is_shadowable, var_is_comptime); - IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false, false); - IrInstruction *var_ptr = var_is_ptr ? - ir_build_ref(irb, subexpr_scope, node, payload_ptr, true, false) : payload_ptr; + IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, subexpr_scope, node, err_val_ptr, false, false); + IrInstSrc *var_ptr = var_is_ptr ? + ir_build_ref_src(irb, subexpr_scope, node, payload_ptr, true, false) : payload_ptr; ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, var_ptr); var_scope = var->child_scope; } else { var_scope = subexpr_scope; } - IrInstruction *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval, + IrInstSrc *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval, &peer_parent->peers.at(0)->base); - if (then_expr_result == irb->codegen->invalid_instruction) + if (then_expr_result == irb->codegen->invalid_inst_src) return then_expr_result; - IrBasicBlock *after_then_block = irb->current_basic_block; + IrBasicBlockSrc *after_then_block = irb->current_basic_block; if (!instr_is_unreachable(then_expr_result)) ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); ir_set_cursor_at_end_and_append_block(irb, else_block); - IrInstruction *else_expr_result; + IrInstSrc *else_expr_result; if (else_node) { Scope *err_var_scope; if (err_symbol) { @@ -7983,40 +9010,40 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * ZigVar *var = ir_create_var(irb, node, subexpr_scope, err_symbol, is_const, is_const, is_shadowable, is_comptime); - IrInstruction *err_ptr = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr); + IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, subexpr_scope, node, err_val_ptr); ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, err_ptr); err_var_scope = var->child_scope; } else { err_var_scope = subexpr_scope; } else_expr_result = ir_gen_node_extra(irb, else_node, err_var_scope, lval, &peer_parent->peers.at(1)->base); - if (else_expr_result == irb->codegen->invalid_instruction) + if (else_expr_result == irb->codegen->invalid_inst_src) return else_expr_result; } else { else_expr_result = ir_build_const_void(irb, scope, node); ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); } - IrBasicBlock *after_else_block = irb->current_basic_block; + IrBasicBlockSrc *after_else_block = irb->current_basic_block; if (!instr_is_unreachable(else_expr_result)) ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); ir_set_cursor_at_end_and_append_block(irb, endif_block); - IrInstruction **incoming_values = allocate(2); + IrInstSrc **incoming_values = allocate(2); incoming_values[0] = then_expr_result; incoming_values[1] = else_expr_result; - IrBasicBlock **incoming_blocks = allocate(2, "IrBasicBlock *"); + IrBasicBlockSrc **incoming_blocks = allocate(2, "IrBasicBlockSrc *"); incoming_blocks[0] = after_then_block; incoming_blocks[1] = after_else_block; - IrInstruction *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent); + IrInstSrc *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent); return ir_expr_wrap(irb, scope, phi, result_loc); } -static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node, - IrBasicBlock *end_block, IrInstruction *is_comptime, IrInstruction *var_is_comptime, - IrInstruction *target_value_ptr, IrInstruction **prong_values, size_t prong_values_len, - ZigList *incoming_blocks, ZigList *incoming_values, - IrInstructionSwitchElseVar **out_switch_else_var, LVal lval, ResultLoc *result_loc) +static bool ir_gen_switch_prong_expr(IrBuilderSrc *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node, + IrBasicBlockSrc *end_block, IrInstSrc *is_comptime, IrInstSrc *var_is_comptime, + IrInstSrc *target_value_ptr, IrInstSrc **prong_values, size_t prong_values_len, + ZigList *incoming_blocks, ZigList *incoming_values, + IrInstSrcSwitchElseVar **out_switch_else_var, LVal lval, ResultLoc *result_loc) { assert(switch_node->type == NodeTypeSwitchExpr); assert(prong_node->type == NodeTypeSwitchProng); @@ -8034,28 +9061,28 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit ZigVar *var = ir_create_var(irb, var_symbol_node, scope, var_name, is_const, is_const, is_shadowable, var_is_comptime); child_scope = var->child_scope; - IrInstruction *var_ptr; + IrInstSrc *var_ptr; if (out_switch_else_var != nullptr) { - IrInstructionSwitchElseVar *switch_else_var = ir_build_switch_else_var(irb, scope, var_symbol_node, + IrInstSrcSwitchElseVar *switch_else_var = ir_build_switch_else_var(irb, scope, var_symbol_node, target_value_ptr); *out_switch_else_var = switch_else_var; - IrInstruction *payload_ptr = &switch_else_var->base; - var_ptr = var_is_ptr ? ir_build_ref(irb, scope, var_symbol_node, payload_ptr, true, false) : payload_ptr; + IrInstSrc *payload_ptr = &switch_else_var->base; + var_ptr = var_is_ptr ? ir_build_ref_src(irb, scope, var_symbol_node, payload_ptr, true, false) : payload_ptr; } else if (prong_values != nullptr) { - IrInstruction *payload_ptr = ir_build_switch_var(irb, scope, var_symbol_node, target_value_ptr, + IrInstSrc *payload_ptr = ir_build_switch_var(irb, scope, var_symbol_node, target_value_ptr, prong_values, prong_values_len); - var_ptr = var_is_ptr ? ir_build_ref(irb, scope, var_symbol_node, payload_ptr, true, false) : payload_ptr; + var_ptr = var_is_ptr ? ir_build_ref_src(irb, scope, var_symbol_node, payload_ptr, true, false) : payload_ptr; } else { var_ptr = var_is_ptr ? - ir_build_ref(irb, scope, var_symbol_node, target_value_ptr, true, false) : target_value_ptr; + ir_build_ref_src(irb, scope, var_symbol_node, target_value_ptr, true, false) : target_value_ptr; } ir_build_var_decl_src(irb, scope, var_symbol_node, var, nullptr, var_ptr); } else { child_scope = scope; } - IrInstruction *expr_result = ir_gen_node_extra(irb, expr_node, child_scope, lval, result_loc); - if (expr_result == irb->codegen->invalid_instruction) + IrInstSrc *expr_result = ir_gen_node_extra(irb, expr_node, child_scope, lval, result_loc); + if (expr_result == irb->codegen->invalid_inst_src) return false; if (!instr_is_unreachable(expr_result)) ir_mark_gen(ir_build_br(irb, scope, switch_node, end_block, is_comptime)); @@ -8064,25 +9091,25 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit return true; } -static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_switch_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeSwitchExpr); AstNode *target_node = node->data.switch_expr.expr; - IrInstruction *target_value_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr, nullptr); - if (target_value_ptr == irb->codegen->invalid_instruction) + IrInstSrc *target_value_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr, nullptr); + if (target_value_ptr == irb->codegen->invalid_inst_src) return target_value_ptr; - IrInstruction *target_value = ir_build_switch_target(irb, scope, node, target_value_ptr); + IrInstSrc *target_value = ir_build_switch_target(irb, scope, node, target_value_ptr); - IrBasicBlock *else_block = ir_create_basic_block(irb, scope, "SwitchElse"); - IrBasicBlock *end_block = ir_create_basic_block(irb, scope, "SwitchEnd"); + IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "SwitchElse"); + IrBasicBlockSrc *end_block = ir_create_basic_block(irb, scope, "SwitchEnd"); size_t prong_count = node->data.switch_expr.prongs.length; - ZigList cases = {0}; + ZigList cases = {0}; - IrInstruction *is_comptime; - IrInstruction *var_is_comptime; + IrInstSrc *is_comptime; + IrInstSrc *var_is_comptime; if (ir_should_inline(irb->exec, scope)) { is_comptime = ir_build_const_bool(irb, scope, node, true); var_is_comptime = is_comptime; @@ -8091,11 +9118,11 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * var_is_comptime = ir_build_test_comptime(irb, scope, node, target_value_ptr); } - ZigList incoming_values = {0}; - ZigList incoming_blocks = {0}; - ZigList check_ranges = {0}; + ZigList incoming_values = {0}; + ZigList incoming_blocks = {0}; + ZigList check_ranges = {0}; - IrInstructionSwitchElseVar *switch_else_var = nullptr; + IrInstSrcSwitchElseVar *switch_else_var = nullptr; ResultLocPeerParent *peer_parent = allocate(1); peer_parent->base.id = ResultLocIdPeerParent; @@ -8110,37 +9137,14 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope); AstNode *else_prong = nullptr; + AstNode *underscore_prong = nullptr; for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) { AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i); size_t prong_item_count = prong_node->data.switch_prong.items.length; - if (prong_item_count == 0) { - ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); - if (else_prong) { - ErrorMsg *msg = add_node_error(irb->codegen, prong_node, - buf_sprintf("multiple else prongs in switch expression")); - add_error_note(irb->codegen, msg, else_prong, - buf_sprintf("previous else prong is here")); - return irb->codegen->invalid_instruction; - } - else_prong = prong_node; - - IrBasicBlock *prev_block = irb->current_basic_block; - if (peer_parent->peers.length > 0) { - peer_parent->peers.last()->next_bb = else_block; - } - peer_parent->peers.append(this_peer_result_loc); - ir_set_cursor_at_end_and_append_block(irb, else_block); - if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, - is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values, - &switch_else_var, LValNone, &this_peer_result_loc->base)) - { - return irb->codegen->invalid_instruction; - } - ir_set_cursor_at_end(irb, prev_block); - } else if (prong_node->data.switch_prong.any_items_are_range) { + if (prong_node->data.switch_prong.any_items_are_range) { ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); - IrInstruction *ok_bit = nullptr; + IrInstSrc *ok_bit = nullptr; AstNode *last_item_node = nullptr; for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) { AstNode *item_node = prong_node->data.switch_prong.items.at(item_i); @@ -8149,23 +9153,23 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * AstNode *start_node = item_node->data.switch_range.start; AstNode *end_node = item_node->data.switch_range.end; - IrInstruction *start_value = ir_gen_node(irb, start_node, comptime_scope); - if (start_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *start_value = ir_gen_node(irb, start_node, comptime_scope); + if (start_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - IrInstruction *end_value = ir_gen_node(irb, end_node, comptime_scope); - if (end_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *end_value = ir_gen_node(irb, end_node, comptime_scope); + if (end_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - IrInstructionCheckSwitchProngsRange *check_range = check_ranges.add_one(); + IrInstSrcCheckSwitchProngsRange *check_range = check_ranges.add_one(); check_range->start = start_value; check_range->end = end_value; - IrInstruction *lower_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpGreaterOrEq, + IrInstSrc *lower_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpGreaterOrEq, target_value, start_value, false); - IrInstruction *upper_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpLessOrEq, + IrInstSrc *upper_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpLessOrEq, target_value, end_value, false); - IrInstruction *both_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolAnd, + IrInstSrc *both_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolAnd, lower_range_ok, upper_range_ok, false); if (ok_bit) { ok_bit = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolOr, both_ok, ok_bit, false); @@ -8173,15 +9177,15 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * ok_bit = both_ok; } } else { - IrInstruction *item_value = ir_gen_node(irb, item_node, comptime_scope); - if (item_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *item_value = ir_gen_node(irb, item_node, comptime_scope); + if (item_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - IrInstructionCheckSwitchProngsRange *check_range = check_ranges.add_one(); + IrInstSrcCheckSwitchProngsRange *check_range = check_ranges.add_one(); check_range->start = item_value; check_range->end = item_value; - IrInstruction *cmp_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpEq, + IrInstSrc *cmp_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpEq, item_value, target_value, false); if (ok_bit) { ok_bit = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolOr, cmp_ok, ok_bit, false); @@ -8191,12 +9195,12 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * } } - IrBasicBlock *range_block_yes = ir_create_basic_block(irb, scope, "SwitchRangeYes"); - IrBasicBlock *range_block_no = ir_create_basic_block(irb, scope, "SwitchRangeNo"); + IrBasicBlockSrc *range_block_yes = ir_create_basic_block(irb, scope, "SwitchRangeYes"); + IrBasicBlockSrc *range_block_no = ir_create_basic_block(irb, scope, "SwitchRangeNo"); assert(ok_bit); assert(last_item_node); - IrInstruction *br_inst = ir_mark_gen(ir_build_cond_br(irb, scope, last_item_node, ok_bit, + IrInstSrc *br_inst = ir_mark_gen(ir_build_cond_br(irb, scope, last_item_node, ok_bit, range_block_yes, range_block_no, is_comptime)); if (peer_parent->base.source_instruction == nullptr) { peer_parent->base.source_instruction = br_inst; @@ -8211,10 +9215,60 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base)) { - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } ir_set_cursor_at_end_and_append_block(irb, range_block_no); + } else { + if (prong_item_count == 0) { + if (else_prong) { + ErrorMsg *msg = add_node_error(irb->codegen, prong_node, + buf_sprintf("multiple else prongs in switch expression")); + add_error_note(irb->codegen, msg, else_prong, + buf_sprintf("previous else prong is here")); + return irb->codegen->invalid_inst_src; + } + else_prong = prong_node; + } else if (prong_item_count == 1 && + prong_node->data.switch_prong.items.at(0)->type == NodeTypeSymbol && + buf_eql_str(prong_node->data.switch_prong.items.at(0)->data.symbol_expr.symbol, "_")) { + if (underscore_prong) { + ErrorMsg *msg = add_node_error(irb->codegen, prong_node, + buf_sprintf("multiple '_' prongs in switch expression")); + add_error_note(irb->codegen, msg, underscore_prong, + buf_sprintf("previous '_' prong is here")); + return irb->codegen->invalid_inst_src; + } + underscore_prong = prong_node; + } else { + continue; + } + if (underscore_prong && else_prong) { + ErrorMsg *msg = add_node_error(irb->codegen, prong_node, + buf_sprintf("else and '_' prong in switch expression")); + if (underscore_prong == prong_node) + add_error_note(irb->codegen, msg, else_prong, + buf_sprintf("else prong is here")); + else + add_error_note(irb->codegen, msg, underscore_prong, + buf_sprintf("'_' prong is here")); + return irb->codegen->invalid_inst_src; + } + ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); + + IrBasicBlockSrc *prev_block = irb->current_basic_block; + if (peer_parent->peers.length > 0) { + peer_parent->peers.last()->next_bb = else_block; + } + peer_parent->peers.append(this_peer_result_loc); + ir_set_cursor_at_end_and_append_block(irb, else_block); + if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, + is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values, + &switch_else_var, LValNone, &this_peer_result_loc->base)) + { + return irb->codegen->invalid_inst_src; + } + ir_set_cursor_at_end(irb, prev_block); } } @@ -8226,32 +9280,34 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * continue; if (prong_node->data.switch_prong.any_items_are_range) continue; + if (underscore_prong == prong_node) + continue; ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); - IrBasicBlock *prong_block = ir_create_basic_block(irb, scope, "SwitchProng"); - IrInstruction **items = allocate(prong_item_count); + IrBasicBlockSrc *prong_block = ir_create_basic_block(irb, scope, "SwitchProng"); + IrInstSrc **items = allocate(prong_item_count); for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) { AstNode *item_node = prong_node->data.switch_prong.items.at(item_i); assert(item_node->type != NodeTypeSwitchRange); - IrInstruction *item_value = ir_gen_node(irb, item_node, comptime_scope); - if (item_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *item_value = ir_gen_node(irb, item_node, comptime_scope); + if (item_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - IrInstructionCheckSwitchProngsRange *check_range = check_ranges.add_one(); + IrInstSrcCheckSwitchProngsRange *check_range = check_ranges.add_one(); check_range->start = item_value; check_range->end = item_value; - IrInstructionSwitchBrCase *this_case = cases.add_one(); + IrInstSrcSwitchBrCase *this_case = cases.add_one(); this_case->value = item_value; this_case->block = prong_block; items[item_i] = item_value; } - IrBasicBlock *prev_block = irb->current_basic_block; + IrBasicBlockSrc *prev_block = irb->current_basic_block; if (peer_parent->peers.length > 0) { peer_parent->peers.last()->next_bb = prong_block; } @@ -8261,21 +9317,21 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * is_comptime, var_is_comptime, target_value_ptr, items, prong_item_count, &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base)) { - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } ir_set_cursor_at_end(irb, prev_block); } - IrInstruction *switch_prongs_void = ir_build_check_switch_prongs(irb, scope, node, target_value, - check_ranges.items, check_ranges.length, else_prong != nullptr); + IrInstSrc *switch_prongs_void = ir_build_check_switch_prongs(irb, scope, node, target_value, + check_ranges.items, check_ranges.length, else_prong != nullptr, underscore_prong != nullptr); - IrInstruction *br_instruction; + IrInstSrc *br_instruction; if (cases.length == 0) { br_instruction = ir_build_br(irb, scope, node, else_block, is_comptime); } else { - IrInstructionSwitchBr *switch_br = ir_build_switch_br(irb, scope, node, target_value, else_block, + IrInstSrcSwitchBr *switch_br = ir_build_switch_br_src(irb, scope, node, target_value, else_block, cases.length, cases.items, is_comptime, switch_prongs_void); if (switch_else_var != nullptr) { switch_else_var->switch_br = switch_br; @@ -8289,7 +9345,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * peer_parent->peers.at(i)->base.source_instruction = peer_parent->base.source_instruction; } - if (!else_prong) { + if (!else_prong && !underscore_prong) { if (peer_parent->peers.length != 0) { peer_parent->peers.last()->next_bb = else_block; } @@ -8303,7 +9359,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * ir_set_cursor_at_end_and_append_block(irb, end_block); assert(incoming_blocks.length == incoming_values.length); - IrInstruction *result_instruction; + IrInstSrc *result_instruction; if (incoming_blocks.length == 0) { result_instruction = ir_build_const_void(irb, scope, node); } else { @@ -8313,7 +9369,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * return ir_lval_wrap(irb, scope, result_instruction, lval, result_loc); } -static IrInstruction *ir_gen_comptime(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval) { +static IrInstSrc *ir_gen_comptime(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval) { assert(node->type == NodeTypeCompTime); Scope *child_scope = create_comptime_scope(irb->codegen, node, parent_scope); @@ -8321,28 +9377,28 @@ static IrInstruction *ir_gen_comptime(IrBuilder *irb, Scope *parent_scope, AstNo return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr); } -static IrInstruction *ir_gen_return_from_block(IrBuilder *irb, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) { - IrInstruction *is_comptime; +static IrInstSrc *ir_gen_return_from_block(IrBuilderSrc *irb, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) { + IrInstSrc *is_comptime; if (ir_should_inline(irb->exec, break_scope)) { is_comptime = ir_build_const_bool(irb, break_scope, node, true); } else { is_comptime = block_scope->is_comptime; } - IrInstruction *result_value; + IrInstSrc *result_value; if (node->data.break_expr.expr) { ResultLocPeer *peer_result = create_peer_result(block_scope->peer_parent); block_scope->peer_parent->peers.append(peer_result); result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope, block_scope->lval, &peer_result->base); - if (result_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + if (result_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; } else { result_value = ir_build_const_void(irb, break_scope, node); } - IrBasicBlock *dest_block = block_scope->end_block; + IrBasicBlockSrc *dest_block = block_scope->end_block; ir_gen_defers_for_block(irb, break_scope, dest_block->scope, false); block_scope->incoming_blocks->append(irb->current_basic_block); @@ -8350,7 +9406,7 @@ static IrInstruction *ir_gen_return_from_block(IrBuilder *irb, Scope *break_scop return ir_build_br(irb, break_scope, node, dest_block, is_comptime); } -static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode *node) { +static IrInstSrc *ir_gen_break(IrBuilderSrc *irb, Scope *break_scope, AstNode *node) { assert(node->type == NodeTypeBreak); // Search up the scope. We'll find one of these things first: @@ -8365,14 +9421,14 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode * if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) { if (node->data.break_expr.name != nullptr) { add_node_error(irb->codegen, node, buf_sprintf("label not found: '%s'", buf_ptr(node->data.break_expr.name))); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } else { add_node_error(irb->codegen, node, buf_sprintf("break expression outside loop")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } } else if (search_scope->id == ScopeIdDeferExpr) { add_node_error(irb->codegen, node, buf_sprintf("cannot break out of defer expression")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } else if (search_scope->id == ScopeIdLoop) { ScopeLoop *this_loop_scope = (ScopeLoop *)search_scope; if (node->data.break_expr.name == nullptr || @@ -8391,32 +9447,32 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode * } } else if (search_scope->id == ScopeIdSuspend) { add_node_error(irb->codegen, node, buf_sprintf("cannot break out of suspend block")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } search_scope = search_scope->parent; } - IrInstruction *is_comptime; + IrInstSrc *is_comptime; if (ir_should_inline(irb->exec, break_scope)) { is_comptime = ir_build_const_bool(irb, break_scope, node, true); } else { is_comptime = loop_scope->is_comptime; } - IrInstruction *result_value; + IrInstSrc *result_value; if (node->data.break_expr.expr) { ResultLocPeer *peer_result = create_peer_result(loop_scope->peer_parent); loop_scope->peer_parent->peers.append(peer_result); result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope, loop_scope->lval, &peer_result->base); - if (result_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + if (result_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; } else { result_value = ir_build_const_void(irb, break_scope, node); } - IrBasicBlock *dest_block = loop_scope->break_block; + IrBasicBlockSrc *dest_block = loop_scope->break_block; ir_gen_defers_for_block(irb, break_scope, dest_block->scope, false); loop_scope->incoming_blocks->append(irb->current_basic_block); @@ -8424,7 +9480,7 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode * return ir_build_br(irb, break_scope, node, dest_block, is_comptime); } -static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, AstNode *node) { +static IrInstSrc *ir_gen_continue(IrBuilderSrc *irb, Scope *continue_scope, AstNode *node) { assert(node->type == NodeTypeContinue); // Search up the scope. We'll find one of these things first: @@ -8440,14 +9496,14 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, Ast if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) { if (node->data.continue_expr.name != nullptr) { add_node_error(irb->codegen, node, buf_sprintf("labeled loop not found: '%s'", buf_ptr(node->data.continue_expr.name))); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } else { add_node_error(irb->codegen, node, buf_sprintf("continue expression outside loop")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } } else if (search_scope->id == ScopeIdDeferExpr) { add_node_error(irb->codegen, node, buf_sprintf("cannot continue out of defer expression")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } else if (search_scope->id == ScopeIdLoop) { ScopeLoop *this_loop_scope = (ScopeLoop *)search_scope; if (node->data.continue_expr.name == nullptr || @@ -8463,7 +9519,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, Ast search_scope = search_scope->parent; } - IrInstruction *is_comptime; + IrInstSrc *is_comptime; if (ir_should_inline(irb->exec, continue_scope)) { is_comptime = ir_build_const_bool(irb, continue_scope, node, true); } else { @@ -8475,17 +9531,17 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, Ast ir_mark_gen(ir_build_check_runtime_scope(irb, continue_scope, node, scope_runtime->is_comptime, is_comptime)); } - IrBasicBlock *dest_block = loop_scope->continue_block; + IrBasicBlockSrc *dest_block = loop_scope->continue_block; ir_gen_defers_for_block(irb, continue_scope, dest_block->scope, false); return ir_mark_gen(ir_build_br(irb, continue_scope, node, dest_block, is_comptime)); } -static IrInstruction *ir_gen_error_type(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_error_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeErrorType); return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_global_error_set); } -static IrInstruction *ir_gen_defer(IrBuilder *irb, Scope *parent_scope, AstNode *node) { +static IrInstSrc *ir_gen_defer(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeDefer); ScopeDefer *defer_child_scope = create_defer_scope(irb->codegen, node, parent_scope); @@ -8497,7 +9553,7 @@ static IrInstruction *ir_gen_defer(IrBuilder *irb, Scope *parent_scope, AstNode return ir_build_const_void(irb, parent_scope, node); } -static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { +static IrInstSrc *ir_gen_slice(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeSliceExpr); AstNodeSliceExpr *slice_expr = &node->data.slice_expr; @@ -8506,38 +9562,38 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node, AstNode *end_node = slice_expr->end; AstNode *sentinel_node = slice_expr->sentinel; - IrInstruction *ptr_value = ir_gen_node_extra(irb, array_node, scope, LValPtr, nullptr); - if (ptr_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *ptr_value = ir_gen_node_extra(irb, array_node, scope, LValPtr, nullptr); + if (ptr_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - IrInstruction *start_value = ir_gen_node(irb, start_node, scope); - if (start_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *start_value = ir_gen_node(irb, start_node, scope); + if (start_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - IrInstruction *end_value; + IrInstSrc *end_value; if (end_node) { end_value = ir_gen_node(irb, end_node, scope); - if (end_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + if (end_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; } else { end_value = nullptr; } - IrInstruction *sentinel_value; + IrInstSrc *sentinel_value; if (sentinel_node) { sentinel_value = ir_gen_node(irb, sentinel_node, scope); - if (sentinel_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + if (sentinel_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; } else { sentinel_value = nullptr; } - IrInstruction *slice = ir_build_slice_src(irb, scope, node, ptr_value, start_value, end_value, + IrInstSrc *slice = ir_build_slice_src(irb, scope, node, ptr_value, start_value, end_value, sentinel_value, true, result_loc); return ir_lval_wrap(irb, scope, slice, lval, result_loc); } -static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_catch(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeCatchExpr); @@ -8551,29 +9607,29 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode assert(var_node->type == NodeTypeSymbol); Buf *var_name = var_node->data.symbol_expr.symbol; add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name))); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } return ir_gen_catch_unreachable(irb, parent_scope, node, op1_node, lval, result_loc); } - IrInstruction *err_union_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr, nullptr); - if (err_union_ptr == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *err_union_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr, nullptr); + if (err_union_ptr == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - IrInstruction *is_err = ir_build_test_err_src(irb, parent_scope, node, err_union_ptr, true, false); + IrInstSrc *is_err = ir_build_test_err_src(irb, parent_scope, node, err_union_ptr, true, false); - IrInstruction *is_comptime; + IrInstSrc *is_comptime; if (ir_should_inline(irb->exec, parent_scope)) { is_comptime = ir_build_const_bool(irb, parent_scope, node, true); } else { is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_err); } - IrBasicBlock *ok_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrOk"); - IrBasicBlock *err_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrError"); - IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrEnd"); - IrInstruction *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_err, err_block, ok_block, is_comptime); + IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrOk"); + IrBasicBlockSrc *err_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrError"); + IrBasicBlockSrc *end_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrEnd"); + IrInstSrc *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_err, err_block, ok_block, is_comptime); ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, ok_block, end_block, result_loc, is_comptime); @@ -8589,33 +9645,33 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode ZigVar *var = ir_create_var(irb, node, subexpr_scope, var_name, is_const, is_const, is_shadowable, is_comptime); err_scope = var->child_scope; - IrInstruction *err_ptr = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr); + IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, err_scope, node, err_union_ptr); ir_build_var_decl_src(irb, err_scope, var_node, var, nullptr, err_ptr); } else { err_scope = subexpr_scope; } - IrInstruction *err_result = ir_gen_node_extra(irb, op2_node, err_scope, LValNone, &peer_parent->peers.at(0)->base); - if (err_result == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; - IrBasicBlock *after_err_block = irb->current_basic_block; + IrInstSrc *err_result = ir_gen_node_extra(irb, op2_node, err_scope, LValNone, &peer_parent->peers.at(0)->base); + if (err_result == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + IrBasicBlockSrc *after_err_block = irb->current_basic_block; if (!instr_is_unreachable(err_result)) ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime)); ir_set_cursor_at_end_and_append_block(irb, ok_block); - IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, parent_scope, node, err_union_ptr, false, false); - IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr); + IrInstSrc *unwrapped_ptr = ir_build_unwrap_err_payload_src(irb, parent_scope, node, err_union_ptr, false, false); + IrInstSrc *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr); ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base); - IrBasicBlock *after_ok_block = irb->current_basic_block; + IrBasicBlockSrc *after_ok_block = irb->current_basic_block; ir_build_br(irb, parent_scope, node, end_block, is_comptime); ir_set_cursor_at_end_and_append_block(irb, end_block); - IrInstruction **incoming_values = allocate(2); + IrInstSrc **incoming_values = allocate(2); incoming_values[0] = err_result; incoming_values[1] = unwrapped_payload; - IrBasicBlock **incoming_blocks = allocate(2, "IrBasicBlock *"); + IrBasicBlockSrc **incoming_blocks = allocate(2, "IrBasicBlockSrc *"); incoming_blocks[0] = after_err_block; incoming_blocks[1] = after_ok_block; - IrInstruction *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); + IrInstSrc *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc); } @@ -8633,7 +9689,7 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o return true; } -static Buf *get_anon_type_name(CodeGen *codegen, IrExecutable *exec, const char *kind_name, +static Buf *get_anon_type_name(CodeGen *codegen, IrExecutableSrc *exec, const char *kind_name, Scope *scope, AstNode *source_node, Buf *out_bare_name) { if (exec != nullptr && exec->name) { @@ -8662,7 +9718,7 @@ static Buf *get_anon_type_name(CodeGen *codegen, IrExecutable *exec, const char } } -static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope, AstNode *node) { +static IrInstSrc *ir_gen_container_decl(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeContainerDecl); ContainerKind kind = node->data.container_decl.kind; @@ -8787,7 +9843,7 @@ static AstNode *ast_field_to_symbol_node(AstNode *err_set_field_node) { } } -static IrInstruction *ir_gen_err_set_decl(IrBuilder *irb, Scope *parent_scope, AstNode *node) { +static IrInstSrc *ir_gen_err_set_decl(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeErrorSetDecl); uint32_t err_count = node->data.err_set_decl.decls.length; @@ -8830,7 +9886,7 @@ static IrInstruction *ir_gen_err_set_decl(IrBuilder *irb, Scope *parent_scope, A buf_sprintf("duplicate error: '%s'", buf_ptr(&err->name))); add_error_note(irb->codegen, msg, ast_field_to_symbol_node(prev_err->decl_node), buf_sprintf("other error here")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } errors[err->value] = err; } @@ -8838,11 +9894,11 @@ static IrInstruction *ir_gen_err_set_decl(IrBuilder *irb, Scope *parent_scope, A return ir_build_const_type(irb, parent_scope, node, err_set_type); } -static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNode *node) { +static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeFnProto); size_t param_count = node->data.fn_proto.params.length; - IrInstruction **param_types = allocate(param_count); + IrInstSrc **param_types = allocate(param_count); bool is_var_args = false; for (size_t i = 0; i < param_count; i += 1) { @@ -8853,59 +9909,59 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo } if (param_node->data.param_decl.var_token == nullptr) { AstNode *type_node = param_node->data.param_decl.type; - IrInstruction *type_value = ir_gen_node(irb, type_node, parent_scope); - if (type_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *type_value = ir_gen_node(irb, type_node, parent_scope); + if (type_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; param_types[i] = type_value; } else { param_types[i] = nullptr; } } - IrInstruction *align_value = nullptr; + IrInstSrc *align_value = nullptr; if (node->data.fn_proto.align_expr != nullptr) { align_value = ir_gen_node(irb, node->data.fn_proto.align_expr, parent_scope); - if (align_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + if (align_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; } - IrInstruction *callconv_value = nullptr; + IrInstSrc *callconv_value = nullptr; if (node->data.fn_proto.callconv_expr != nullptr) { callconv_value = ir_gen_node(irb, node->data.fn_proto.callconv_expr, parent_scope); - if (callconv_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + if (callconv_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; } - IrInstruction *return_type; + IrInstSrc *return_type; if (node->data.fn_proto.return_var_token == nullptr) { if (node->data.fn_proto.return_type == nullptr) { return_type = ir_build_const_type(irb, parent_scope, node, irb->codegen->builtin_types.entry_void); } else { return_type = ir_gen_node(irb, node->data.fn_proto.return_type, parent_scope); - if (return_type == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + if (return_type == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; } } else { add_node_error(irb->codegen, node, buf_sprintf("TODO implement inferred return types https://github.com/ziglang/zig/issues/447")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; //return_type = nullptr; } return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, callconv_value, return_type, is_var_args); } -static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node) { +static IrInstSrc *ir_gen_resume(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeResume); - IrInstruction *target_inst = ir_gen_node_extra(irb, node->data.resume_expr.expr, scope, LValPtr, nullptr); - if (target_inst == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *target_inst = ir_gen_node_extra(irb, node->data.resume_expr.expr, scope, LValPtr, nullptr); + if (target_inst == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - return ir_build_resume(irb, scope, node, target_inst); + return ir_build_resume_src(irb, scope, node, target_inst); } -static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, +static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { assert(node->type == NodeTypeAwaitExpr); @@ -8926,7 +9982,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n ZigFn *fn_entry = exec_fn_entry(irb->exec); if (!fn_entry) { add_node_error(irb->codegen, node, buf_sprintf("await outside function definition")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } ScopeSuspend *existing_suspend_scope = get_scope_suspend(scope); if (existing_suspend_scope) { @@ -8935,24 +9991,24 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n add_error_note(irb->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("suspend block here")); existing_suspend_scope->reported_err = true; } - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } - IrInstruction *target_inst = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); - if (target_inst == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *target_inst = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); + if (target_inst == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - IrInstruction *await_inst = ir_build_await_src(irb, scope, node, target_inst, result_loc); + IrInstSrc *await_inst = ir_build_await_src(irb, scope, node, target_inst, result_loc); return ir_lval_wrap(irb, scope, await_inst, lval, result_loc); } -static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNode *node) { +static IrInstSrc *ir_gen_suspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeSuspend); ZigFn *fn_entry = exec_fn_entry(irb->exec); if (!fn_entry) { add_node_error(irb->codegen, node, buf_sprintf("suspend outside function definition")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } ScopeSuspend *existing_suspend_scope = get_scope_suspend(parent_scope); if (existing_suspend_scope) { @@ -8961,21 +10017,21 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod add_error_note(irb->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("other suspend block here")); existing_suspend_scope->reported_err = true; } - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; } - IrInstructionSuspendBegin *begin = ir_build_suspend_begin(irb, parent_scope, node); + IrInstSrcSuspendBegin *begin = ir_build_suspend_begin_src(irb, parent_scope, node); if (node->data.suspend.block != nullptr) { ScopeSuspend *suspend_scope = create_suspend_scope(irb->codegen, node, parent_scope); Scope *child_scope = &suspend_scope->base; - IrInstruction *susp_res = ir_gen_node(irb, node->data.suspend.block, child_scope); + IrInstSrc *susp_res = ir_gen_node(irb, node->data.suspend.block, child_scope); ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.suspend.block, susp_res)); } - return ir_mark_gen(ir_build_suspend_finish(irb, parent_scope, node, begin)); + return ir_mark_gen(ir_build_suspend_finish_src(irb, parent_scope, node, begin)); } -static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope, +static IrInstSrc *ir_gen_node_raw(IrBuilderSrc *irb, AstNode *node, Scope *scope, LVal lval, ResultLoc *result_loc) { assert(scope); @@ -9024,39 +10080,39 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop return ir_gen_return(irb, scope, node, lval, result_loc); case NodeTypeFieldAccessExpr: { - IrInstruction *ptr_instruction = ir_gen_field_access(irb, scope, node); - if (ptr_instruction == irb->codegen->invalid_instruction) + IrInstSrc *ptr_instruction = ir_gen_field_access(irb, scope, node); + if (ptr_instruction == irb->codegen->invalid_inst_src) return ptr_instruction; if (lval == LValPtr) return ptr_instruction; - IrInstruction *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction); + IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction); return ir_expr_wrap(irb, scope, load_ptr, result_loc); } case NodeTypePtrDeref: { AstNode *expr_node = node->data.ptr_deref_expr.target; - IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval, nullptr); - if (value == irb->codegen->invalid_instruction) + IrInstSrc *value = ir_gen_node_extra(irb, expr_node, scope, lval, nullptr); + if (value == irb->codegen->invalid_inst_src) return value; // We essentially just converted any lvalue from &(x.*) to (&x).*; // this inhibits checking that x is a pointer later, so we directly // record whether the pointer check is needed - IrInstruction *un_op = ir_build_un_op_lval(irb, scope, node, IrUnOpDereference, value, lval, result_loc); + IrInstSrc *un_op = ir_build_un_op_lval(irb, scope, node, IrUnOpDereference, value, lval, result_loc); return ir_expr_wrap(irb, scope, un_op, result_loc); } case NodeTypeUnwrapOptional: { AstNode *expr_node = node->data.unwrap_optional.expr; - IrInstruction *maybe_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); - if (maybe_ptr == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; + IrInstSrc *maybe_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); + if (maybe_ptr == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; - IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true, false); + IrInstSrc *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true, false); if (lval == LValPtr) return unwrapped_ptr; - IrInstruction *load_ptr = ir_build_load_ptr(irb, scope, node, unwrapped_ptr); + IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, unwrapped_ptr); return ir_expr_wrap(irb, scope, load_ptr, result_loc); } case NodeTypeBoolLiteral: @@ -9114,7 +10170,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop case NodeTypeInferredArrayType: add_node_error(irb->codegen, node, buf_sprintf("inferred array size invalid here")); - return irb->codegen->invalid_instruction; + return irb->codegen->invalid_inst_src; case NodeTypeVarFieldType: return ir_lval_wrap(irb, scope, ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_var), lval, result_loc); @@ -9128,7 +10184,7 @@ static ResultLoc *no_result_loc(void) { return &result_loc_none->base; } -static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval, +static IrInstSrc *ir_gen_node_extra(IrBuilderSrc *irb, AstNode *node, Scope *scope, LVal lval, ResultLoc *result_loc) { if (result_loc == nullptr) { @@ -9145,8 +10201,8 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *sc } else { child_scope = &create_expr_scope(irb->codegen, node, scope)->base; } - IrInstruction *result = ir_gen_node_raw(irb, node, child_scope, lval, result_loc); - if (result == irb->codegen->invalid_instruction) { + IrInstSrc *result = ir_gen_node_raw(irb, node, child_scope, lval, result_loc); + if (result == irb->codegen->invalid_inst_src) { if (irb->exec->first_err_trace_msg == nullptr) { irb->exec->first_err_trace_msg = irb->codegen->trace_err; } @@ -9154,11 +10210,22 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *sc return result; } -static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope) { +static IrInstSrc *ir_gen_node(IrBuilderSrc *irb, AstNode *node, Scope *scope) { return ir_gen_node_extra(irb, node, scope, LValNone, nullptr); } -static void invalidate_exec(IrExecutable *exec, ErrorMsg *msg) { +static void invalidate_exec(IrExecutableSrc *exec, ErrorMsg *msg) { + if (exec->first_err_trace_msg != nullptr) + return; + + exec->first_err_trace_msg = msg; + + for (size_t i = 0; i < exec->tld_list.length; i += 1) { + exec->tld_list.items[i]->resolution = TldResolutionInvalid; + } +} + +static void invalidate_exec_gen(IrExecutableGen *exec, ErrorMsg *msg) { if (exec->first_err_trace_msg != nullptr) return; @@ -9172,24 +10239,25 @@ static void invalidate_exec(IrExecutable *exec, ErrorMsg *msg) { invalidate_exec(exec->source_exec, msg); } -bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_executable) { + +bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutableSrc *ir_executable) { assert(node->owner); - IrBuilder ir_builder = {0}; - IrBuilder *irb = &ir_builder; + IrBuilderSrc ir_builder = {0}; + IrBuilderSrc *irb = &ir_builder; irb->codegen = codegen; irb->exec = ir_executable; irb->main_block_node = node; - IrBasicBlock *entry_block = ir_create_basic_block(irb, scope, "Entry"); + IrBasicBlockSrc *entry_block = ir_create_basic_block(irb, scope, "Entry"); ir_set_cursor_at_end_and_append_block(irb, entry_block); // Entry block gets a reference because we enter it to begin. ir_ref_bb(irb->current_basic_block); - IrInstruction *result = ir_gen_node_extra(irb, node, scope, LValNone, nullptr); + IrInstSrc *result = ir_gen_node_extra(irb, node, scope, LValNone, nullptr); - if (result == irb->codegen->invalid_instruction) + if (result == irb->codegen->invalid_inst_src) return false; if (irb->exec->first_err_trace_msg != nullptr) { @@ -9198,13 +10266,13 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec } if (!instr_is_unreachable(result)) { - ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, result->source_node, result, nullptr)); + ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, result->base.source_node, result, nullptr)); // no need for save_err_ret_addr because this cannot return error ResultLocReturn *result_loc_ret = allocate(1, "ResultLocReturn"); result_loc_ret->base.id = ResultLocIdReturn; ir_build_reset_result(irb, scope, node, &result_loc_ret->base); ir_mark_gen(ir_build_end_expr(irb, scope, node, result, &result_loc_ret->base)); - ir_mark_gen(ir_build_return(irb, scope, result->source_node, result)); + ir_mark_gen(ir_build_return_src(irb, scope, result->base.source_node, result)); } return true; @@ -9213,7 +10281,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec bool ir_gen_fn(CodeGen *codegen, ZigFn *fn_entry) { assert(fn_entry); - IrExecutable *ir_executable = fn_entry->ir_executable; + IrExecutableSrc *ir_executable = fn_entry->ir_executable; AstNode *body_node = fn_entry->body_node; assert(fn_entry->child_scope); @@ -9221,14 +10289,21 @@ bool ir_gen_fn(CodeGen *codegen, ZigFn *fn_entry) { return ir_gen(codegen, body_node, fn_entry->child_scope, ir_executable); } -static void ir_add_call_stack_errors(CodeGen *codegen, IrExecutable *exec, ErrorMsg *err_msg, int limit) { +static void ir_add_call_stack_errors_gen(CodeGen *codegen, IrExecutableGen *exec, ErrorMsg *err_msg, int limit) { if (!exec || !exec->source_node || limit < 0) return; add_error_note(codegen, err_msg, exec->source_node, buf_sprintf("called from here")); - ir_add_call_stack_errors(codegen, exec->parent_exec, err_msg, limit - 1); + ir_add_call_stack_errors_gen(codegen, exec->parent_exec, err_msg, limit - 1); } -static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg) { +static void ir_add_call_stack_errors(CodeGen *codegen, IrExecutableSrc *exec, ErrorMsg *err_msg, int limit) { + if (!exec || !exec->source_node || limit < 0) return; + add_error_note(codegen, err_msg, exec->source_node, buf_sprintf("called from here")); + + ir_add_call_stack_errors_gen(codegen, exec->parent_exec, err_msg, limit - 1); +} + +static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutableSrc *exec, AstNode *source_node, Buf *msg) { ErrorMsg *err_msg = add_node_error(codegen, source_node, msg); invalidate_exec(exec, err_msg); if (exec->parent_exec) { @@ -9237,26 +10312,40 @@ static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNo return err_msg; } +static ErrorMsg *exec_add_error_node_gen(CodeGen *codegen, IrExecutableGen *exec, AstNode *source_node, Buf *msg) { + ErrorMsg *err_msg = add_node_error(codegen, source_node, msg); + invalidate_exec_gen(exec, err_msg); + if (exec->parent_exec) { + ir_add_call_stack_errors_gen(codegen, exec, err_msg, 10); + } + return err_msg; +} + static ErrorMsg *ir_add_error_node(IrAnalyze *ira, AstNode *source_node, Buf *msg) { - return exec_add_error_node(ira->codegen, ira->new_irb.exec, source_node, msg); + return exec_add_error_node_gen(ira->codegen, ira->new_irb.exec, source_node, msg); } static ErrorMsg *opt_ir_add_error_node(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, Buf *msg) { if (ira != nullptr) - return exec_add_error_node(codegen, ira->new_irb.exec, source_node, msg); + return exec_add_error_node_gen(codegen, ira->new_irb.exec, source_node, msg); else return add_node_error(codegen, source_node, msg); } -static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction, Buf *msg) { +static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInst *source_instruction, Buf *msg) { return ir_add_error_node(ira, source_instruction->source_node, msg); } -static void ir_assert(bool ok, IrInstruction *source_instruction) { +static void ir_assert(bool ok, IrInst *source_instruction) { if (ok) return; src_assert(ok, source_instruction->source_node); } +static void ir_assert_gen(bool ok, IrInstGen *source_instruction) { + if (ok) return; + src_assert(ok, source_instruction->base.source_node); +} + // This function takes a comptime ptr and makes the child const value conform to the type // described by the pointer. static Error eval_comptime_ptr_reinterpret(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, @@ -9302,36 +10391,36 @@ ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_va return val; } -static Error ir_exec_scan_for_side_effects(CodeGen *codegen, IrExecutable *exec) { - IrBasicBlock *bb = exec->basic_block_list.at(0); +static Error ir_exec_scan_for_side_effects(CodeGen *codegen, IrExecutableGen *exec) { + IrBasicBlockGen *bb = exec->basic_block_list.at(0); for (size_t i = 0; i < bb->instruction_list.length; i += 1) { - IrInstruction *instruction = bb->instruction_list.at(i); - if (instruction->id == IrInstructionIdReturn) { + IrInstGen *instruction = bb->instruction_list.at(i); + if (instruction->id == IrInstGenIdReturn) { return ErrorNone; - } else if (ir_has_side_effects(instruction)) { + } else if (ir_inst_gen_has_side_effects(instruction)) { if (instr_is_comptime(instruction)) { switch (instruction->id) { - case IrInstructionIdUnwrapErrPayload: - case IrInstructionIdUnionFieldPtr: + case IrInstGenIdUnwrapErrPayload: + case IrInstGenIdUnionFieldPtr: continue; default: break; } } - if (get_scope_typeof(instruction->scope) != nullptr) { + if (get_scope_typeof(instruction->base.scope) != nullptr) { // doesn't count, it's inside a @TypeOf() continue; } - exec_add_error_node(codegen, exec, instruction->source_node, - buf_sprintf("unable to evaluate constant expression")); + exec_add_error_node_gen(codegen, exec, instruction->base.source_node, + buf_sprintf("unable to evaluate constant expression")); return ErrorSemanticAnalyzeFail; } } zig_unreachable(); } -static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) { - if (ir_should_inline(ira->new_irb.exec, source_instruction->scope)) { +static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInst* source_instruction) { + if (ir_should_inline(ira->old_irb.exec, source_instruction->scope)) { ir_add_error(ira, source_instruction, buf_sprintf("unable to evaluate constant expression")); return false; } @@ -10065,7 +11154,7 @@ void float_read_ieee597(ZigValue *val, uint8_t *buf, bool is_big_endian) { } } -static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruction, ZigType *other_type, +static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstGen *instruction, ZigType *other_type, bool explicit_cast) { if (type_is_invalid(other_type)) { @@ -10159,7 +11248,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc } Buf *val_buf = buf_alloc(); bigint_append_buf(val_buf, &const_val->data.x_bigint, 10); - ir_add_error(ira, instruction, + ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("integer value %s has no representation in type '%s'", buf_ptr(val_buf), buf_ptr(&other_type->name))); @@ -10254,7 +11343,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc } Buf *val_buf = buf_alloc(); float_append_buf(val_buf, const_val); - ir_add_error(ira, instruction, + ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("cast of value %s to type '%s' loses information", buf_ptr(val_buf), buf_ptr(&other_type->name))); @@ -10263,7 +11352,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc if (!other_type->data.integral.is_signed && const_val->data.x_bigint.is_negative) { Buf *val_buf = buf_alloc(); bigint_append_buf(val_buf, &const_val->data.x_bigint, 10); - ir_add_error(ira, instruction, + ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("cannot cast negative value %s to unsigned integer type '%s'", buf_ptr(val_buf), buf_ptr(&other_type->name))); @@ -10284,7 +11373,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc if (!child_type->data.integral.is_signed && const_val->data.x_bigint.is_negative) { Buf *val_buf = buf_alloc(); bigint_append_buf(val_buf, &const_val->data.x_bigint, 10); - ir_add_error(ira, instruction, + ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("cannot cast negative value %s to unsigned integer type '%s'", buf_ptr(val_buf), buf_ptr(&child_type->name))); @@ -10307,7 +11396,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc Buf *val_buf = buf_alloc(); float_append_buf(val_buf, const_val); - ir_add_error(ira, instruction, + ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("fractional component prevents float value %s from being casted to type '%s'", buf_ptr(val_buf), buf_ptr(&other_type->name))); @@ -10337,7 +11426,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc bigint_append_buf(val_buf, &const_val->data.x_bigint, 10); } - ir_add_error(ira, instruction, + ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("%s value %s cannot be coerced to type '%s'", num_lit_str, buf_ptr(val_buf), @@ -10791,11 +11880,11 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t * } static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type, - IrInstruction **instructions, size_t instruction_count) + IrInstGen **instructions, size_t instruction_count) { Error err; assert(instruction_count >= 1); - IrInstruction *prev_inst; + IrInstGen *prev_inst; size_t i = 0; for (;;) { prev_inst = instructions[i]; @@ -10815,7 +11904,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT size_t errors_count = 0; ZigType *err_set_type = nullptr; if (prev_inst->value->type->id == ZigTypeIdErrorSet) { - if (!resolve_inferred_error_set(ira->codegen, prev_inst->value->type, prev_inst->source_node)) { + if (!resolve_inferred_error_set(ira->codegen, prev_inst->value->type, prev_inst->base.source_node)) { return ira->codegen->builtin_types.entry_invalid; } if (type_is_global_error_set(prev_inst->value->type)) { @@ -10835,7 +11924,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT bool any_are_null = (prev_inst->value->type->id == ZigTypeIdNull); bool convert_to_const_slice = false; for (; i < instruction_count; i += 1) { - IrInstruction *cur_inst = instructions[i]; + IrInstGen *cur_inst = instructions[i]; ZigType *cur_type = cur_inst->value->type; ZigType *prev_type = prev_inst->value->type; @@ -10857,14 +11946,14 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT } if (prev_type->id == ZigTypeIdErrorSet) { - ir_assert(err_set_type != nullptr, prev_inst); + ir_assert_gen(err_set_type != nullptr, prev_inst); if (cur_type->id == ZigTypeIdErrorSet) { if (type_is_global_error_set(err_set_type)) { continue; } bool allow_infer = cur_type->data.error_set.infer_fn != nullptr && cur_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry; - if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) { + if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->base.source_node)) { return ira->codegen->builtin_types.entry_invalid; } if (!allow_infer && type_is_global_error_set(cur_type)) { @@ -10932,7 +12021,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT ZigType *cur_err_set_type = cur_type->data.error_union.err_set_type; bool allow_infer = cur_err_set_type->data.error_set.infer_fn != nullptr && cur_err_set_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry; - if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_err_set_type, cur_inst->source_node)) { + if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_err_set_type, cur_inst->base.source_node)) { return ira->codegen->builtin_types.entry_invalid; } if (!allow_infer && type_is_global_error_set(cur_err_set_type)) { @@ -10987,7 +12076,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT if (cur_type->id == ZigTypeIdErrorSet) { bool allow_infer = cur_type->data.error_set.infer_fn != nullptr && cur_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry; - if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) { + if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->base.source_node)) { return ira->codegen->builtin_types.entry_invalid; } if (!allow_infer && type_is_global_error_set(cur_type)) { @@ -11010,7 +12099,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT err_set_type = cur_type; } - if (!allow_infer && !resolve_inferred_error_set(ira->codegen, err_set_type, cur_inst->source_node)) { + if (!allow_infer && !resolve_inferred_error_set(ira->codegen, err_set_type, cur_inst->base.source_node)) { return ira->codegen->builtin_types.entry_invalid; } @@ -11073,11 +12162,11 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT bool allow_infer_cur = cur_err_set_type->data.error_set.infer_fn != nullptr && cur_err_set_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry; - if (!allow_infer_prev && !resolve_inferred_error_set(ira->codegen, prev_err_set_type, cur_inst->source_node)) { + if (!allow_infer_prev && !resolve_inferred_error_set(ira->codegen, prev_err_set_type, cur_inst->base.source_node)) { return ira->codegen->builtin_types.entry_invalid; } - if (!allow_infer_cur && !resolve_inferred_error_set(ira->codegen, cur_err_set_type, cur_inst->source_node)) { + if (!allow_infer_cur && !resolve_inferred_error_set(ira->codegen, cur_err_set_type, cur_inst->base.source_node)) { return ira->codegen->builtin_types.entry_invalid; } @@ -11254,7 +12343,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT ZigType *cur_err_set_type = cur_type->data.error_union.err_set_type; bool allow_infer = cur_err_set_type->data.error_set.infer_fn != nullptr && cur_err_set_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry; - if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_err_set_type, cur_inst->source_node)) { + if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_err_set_type, cur_inst->base.source_node)) { return ira->codegen->builtin_types.entry_invalid; } if ((!allow_infer && type_is_global_error_set(cur_err_set_type)) || @@ -11449,9 +12538,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("incompatible types: '%s' and '%s'", buf_ptr(&prev_type->name), buf_ptr(&cur_type->name))); - add_error_note(ira->codegen, msg, prev_inst->source_node, + add_error_note(ira->codegen, msg, prev_inst->base.source_node, buf_sprintf("type '%s' here", buf_ptr(&prev_type->name))); - add_error_note(ira->codegen, msg, cur_inst->source_node, + add_error_note(ira->codegen, msg, cur_inst->base.source_node, buf_sprintf("type '%s' here", buf_ptr(&cur_type->name))); return ira->codegen->builtin_types.entry_invalid; @@ -11521,7 +12610,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT } } -static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_instr, +static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInst *source_instr, CastOp cast_op, ZigValue *other_val, ZigType *other_type, ZigValue *const_val, ZigType *new_type) @@ -11621,58 +12710,56 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ return true; } -static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, ZigType *ty) { - IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, - old_instruction->scope, old_instruction->source_node); - IrInstruction *new_instruction = &const_instruction->base; +static IrInstGen *ir_const(IrAnalyze *ira, IrInst *inst, ZigType *ty) { + IrInstGenConst *const_instruction = ir_create_inst_gen(&ira->new_irb, + inst->scope, inst->source_node); + IrInstGen *new_instruction = &const_instruction->base; new_instruction->value->type = ty; new_instruction->value->special = ConstValSpecialStatic; return new_instruction; } -static IrInstruction *ir_const_noval(IrAnalyze *ira, IrInstruction *old_instruction) { - IrInstructionConst *const_instruction = ir_create_instruction_noval(&ira->new_irb, +static IrInstGen *ir_const_noval(IrAnalyze *ira, IrInst *old_instruction) { + IrInstGenConst *const_instruction = ir_create_inst_noval(&ira->new_irb, old_instruction->scope, old_instruction->source_node); return &const_instruction->base; } -// This function initializes the new IrInstruction with the provided ZigValue, +// This function initializes the new IrInstGen with the provided ZigValue, // rather than creating a new one. -static IrInstruction *ir_const_move(IrAnalyze *ira, IrInstruction *old_instruction, ZigValue *val) { - IrInstruction *result = ir_const_noval(ira, old_instruction); +static IrInstGen *ir_const_move(IrAnalyze *ira, IrInst *old_instruction, ZigValue *val) { + IrInstGen *result = ir_const_noval(ira, old_instruction); result->value = val; return result; } -static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, +static IrInstGen *ir_resolve_cast(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value, ZigType *wanted_type, CastOp cast_op) { if (instr_is_comptime(value) || !type_has_bits(wanted_type)) { - IrInstruction *result = ir_const(ira, source_instr, wanted_type); + IrInstGen *result = ir_const(ira, source_instr, wanted_type); if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, value->value, value->value->type, result->value, wanted_type)) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } return result; } else { - IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node, wanted_type, value, cast_op); - result->value->type = wanted_type; - return result; + return ir_build_cast(ira, source_instr, wanted_type, value, cast_op); } } -static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *value, ZigType *wanted_type) +static IrInstGen *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *value, ZigType *wanted_type) { - assert(value->value->type->id == ZigTypeIdPointer); + ir_assert(value->value->type->id == ZigTypeIdPointer, source_instr); Error err; if ((err = type_resolve(ira->codegen, value->value->type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } wanted_type = adjust_ptr_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value->type)); @@ -11680,9 +12767,9 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira, if (instr_is_comptime(value)) { ZigValue *pointee = const_ptr_pointee(ira, ira->codegen, value->value, source_instr->source_node); if (pointee == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (pointee->special != ConstValSpecialRuntime) { - IrInstruction *result = ir_const(ira, source_instr, wanted_type); + IrInstGen *result = ir_const(ira, source_instr, wanted_type); result->value->data.x_ptr.special = ConstPtrSpecialBaseArray; result->value->data.x_ptr.mut = value->value->data.x_ptr.mut; result->value->data.x_ptr.data.base_array.array_val = pointee; @@ -11691,21 +12778,18 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira, } } - IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node, - wanted_type, value, CastOpBitCast); - result->value->type = wanted_type; - return result; + return ir_build_cast(ira, source_instr, wanted_type, value, CastOpBitCast); } -static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *array_ptr, ZigType *wanted_type, ResultLoc *result_loc) +static IrInstGen *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *array_ptr, ZigType *wanted_type, ResultLoc *result_loc) { Error err; if ((err = type_resolve(ira->codegen, array_ptr->value->type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } wanted_type = adjust_slice_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, array_ptr->value->type)); @@ -11713,17 +12797,17 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc if (instr_is_comptime(array_ptr)) { ZigValue *array_ptr_val = ir_resolve_const(ira, array_ptr, UndefBad); if (array_ptr_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *pointee = const_ptr_pointee(ira, ira->codegen, array_ptr_val, source_instr->source_node); if (pointee == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (pointee->special != ConstValSpecialRuntime) { assert(array_ptr_val->type->id == ZigTypeIdPointer); ZigType *array_type = array_ptr_val->type->data.pointer.child_type; assert(is_slice(wanted_type)); bool is_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const; - IrInstruction *result = ir_const(ira, source_instr, wanted_type); + IrInstGen *result = ir_const(ira, source_instr, wanted_type); init_const_slice(ira->codegen, result->value, pointee, 0, array_type->data.array.len, is_const); result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut; result->value->type = wanted_type; @@ -11732,32 +12816,33 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc } if (result_loc == nullptr) result_loc = no_result_loc(); - IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, - nullptr, true, true); - if (type_is_invalid(result_loc_inst->value->type) || instr_is_unreachable(result_loc_inst)) { + IrInstGen *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, true); + if (type_is_invalid(result_loc_inst->value->type) || + result_loc_inst->value->type->id == ZigTypeIdUnreachable) + { return result_loc_inst; } return ir_build_ptr_of_array_to_slice(ira, source_instr, wanted_type, array_ptr, result_loc_inst); } -static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) { +static IrBasicBlockGen *ir_get_new_bb(IrAnalyze *ira, IrBasicBlockSrc *old_bb, IrInst *ref_old_instruction) { assert(old_bb); - if (old_bb->other) { - if (ref_old_instruction == nullptr || old_bb->other->ref_instruction != ref_old_instruction) { - return old_bb->other; + if (old_bb->child) { + if (ref_old_instruction == nullptr || old_bb->child->ref_instruction != ref_old_instruction) { + return old_bb->child; } } - IrBasicBlock *new_bb = ir_build_bb_from(&ira->new_irb, old_bb); + IrBasicBlockGen *new_bb = ir_build_bb_from(ira, old_bb); new_bb->ref_instruction = ref_old_instruction; return new_bb; } -static IrBasicBlock *ir_get_new_bb_runtime(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) { +static IrBasicBlockGen *ir_get_new_bb_runtime(IrAnalyze *ira, IrBasicBlockSrc *old_bb, IrInst *ref_old_instruction) { assert(ref_old_instruction != nullptr); - IrBasicBlock *new_bb = ir_get_new_bb(ira, old_bb, ref_old_instruction); + IrBasicBlockGen *new_bb = ir_get_new_bb(ira, old_bb, ref_old_instruction); if (new_bb->must_be_comptime_source_instr) { ErrorMsg *msg = ir_add_error(ira, ref_old_instruction, buf_sprintf("control flow attempts to use compile-time variable at runtime")); @@ -11768,24 +12853,24 @@ static IrBasicBlock *ir_get_new_bb_runtime(IrAnalyze *ira, IrBasicBlock *old_bb, return new_bb; } -static void ir_start_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrBasicBlock *const_predecessor_bb) { - ir_assert(!old_bb->suspended, (old_bb->instruction_list.length != 0) ? old_bb->instruction_list.at(0) : nullptr); +static void ir_start_bb(IrAnalyze *ira, IrBasicBlockSrc *old_bb, IrBasicBlockSrc *const_predecessor_bb) { + ir_assert(!old_bb->suspended, (old_bb->instruction_list.length != 0) ? &old_bb->instruction_list.at(0)->base : nullptr); ira->instruction_index = 0; ira->old_irb.current_basic_block = old_bb; ira->const_predecessor_bb = const_predecessor_bb; ira->old_bb_index = old_bb->index; } -static IrInstruction *ira_suspend(IrAnalyze *ira, IrInstruction *old_instruction, IrBasicBlock *next_bb, +static IrInstGen *ira_suspend(IrAnalyze *ira, IrInst *old_instruction, IrBasicBlockSrc *next_bb, IrSuspendPosition *suspend_pos) { if (ira->codegen->verbose_ir) { - fprintf(stderr, "suspend %s_%zu %s_%zu #%" PRIu32 " (%zu,%zu)\n", + fprintf(stderr, "suspend %s_%" PRIu32 " %s_%" PRIu32 " #%" PRIu32 " (%zu,%zu)\n", ira->old_irb.current_basic_block->name_hint, ira->old_irb.current_basic_block->debug_id, ira->old_irb.exec->basic_block_list.at(ira->old_bb_index)->name_hint, ira->old_irb.exec->basic_block_list.at(ira->old_bb_index)->debug_id, - ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index)->debug_id, + ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index)->base.debug_id, ira->old_bb_index, ira->instruction_index); } suspend_pos->basic_block_index = ira->old_bb_index; @@ -11800,13 +12885,13 @@ static IrInstruction *ira_suspend(IrAnalyze *ira, IrInstruction *old_instruction assert(ira->old_irb.current_basic_block == next_bb); ira->instruction_index = 0; ira->const_predecessor_bb = nullptr; - next_bb->other = ir_get_new_bb_runtime(ira, next_bb, old_instruction); - ira->new_irb.current_basic_block = next_bb->other; + next_bb->child = ir_get_new_bb_runtime(ira, next_bb, old_instruction); + ira->new_irb.current_basic_block = next_bb->child; } return ira->codegen->unreach_instruction; } -static IrInstruction *ira_resume(IrAnalyze *ira) { +static IrInstGen *ira_resume(IrAnalyze *ira) { IrSuspendPosition pos = ira->resume_stack.pop(); if (ira->codegen->verbose_ir) { fprintf(stderr, "resume (%zu,%zu) ", pos.basic_block_index, pos.instruction_index); @@ -11819,12 +12904,12 @@ static IrInstruction *ira_resume(IrAnalyze *ira) { ira->instruction_index = pos.instruction_index; assert(pos.instruction_index < ira->old_irb.current_basic_block->instruction_list.length); if (ira->codegen->verbose_ir) { - fprintf(stderr, "%s_%zu #%" PRIu32 "\n", ira->old_irb.current_basic_block->name_hint, + fprintf(stderr, "%s_%" PRIu32 " #%" PRIu32 "\n", ira->old_irb.current_basic_block->name_hint, ira->old_irb.current_basic_block->debug_id, - ira->old_irb.current_basic_block->instruction_list.at(pos.instruction_index)->debug_id); + ira->old_irb.current_basic_block->instruction_list.at(pos.instruction_index)->base.debug_id); } ira->const_predecessor_bb = nullptr; - ira->new_irb.current_basic_block = ira->old_irb.current_basic_block->other; + ira->new_irb.current_basic_block = ira->old_irb.current_basic_block->child; assert(ira->new_irb.current_basic_block != nullptr); return ira->codegen->unreach_instruction; } @@ -11835,8 +12920,8 @@ static void ir_start_next_bb(IrAnalyze *ira) { bool need_repeat = true; for (;;) { while (ira->old_bb_index < ira->old_irb.exec->basic_block_list.length) { - IrBasicBlock *old_bb = ira->old_irb.exec->basic_block_list.at(ira->old_bb_index); - if (old_bb->other == nullptr && old_bb->suspend_instruction_ref == nullptr) { + IrBasicBlockSrc *old_bb = ira->old_irb.exec->basic_block_list.at(ira->old_bb_index); + if (old_bb->child == nullptr && old_bb->suspend_instruction_ref == nullptr) { ira->old_bb_index += 1; continue; } @@ -11844,8 +12929,8 @@ static void ir_start_next_bb(IrAnalyze *ira) { // if it's a suspended block, // then skip it if (old_bb->suspended || - (old_bb->other != nullptr && old_bb->other->instruction_list.length != 0) || - (old_bb->other != nullptr && old_bb->other->already_appended)) + (old_bb->child != nullptr && old_bb->child->instruction_list.length != 0) || + (old_bb->child != nullptr && old_bb->child->already_appended)) { ira->old_bb_index += 1; continue; @@ -11859,10 +12944,10 @@ static void ir_start_next_bb(IrAnalyze *ira) { return; } - if (old_bb->other == nullptr) { - old_bb->other = ir_get_new_bb_runtime(ira, old_bb, old_bb->suspend_instruction_ref); + if (old_bb->child == nullptr) { + old_bb->child = ir_get_new_bb_runtime(ira, old_bb, old_bb->suspend_instruction_ref); } - ira->new_irb.current_basic_block = old_bb->other; + ira->new_irb.current_basic_block = old_bb->child; ir_start_bb(ira, old_bb, nullptr); return; } @@ -11882,16 +12967,16 @@ static void ir_finish_bb(IrAnalyze *ira) { if (!ira->new_irb.current_basic_block->already_appended) { ira->new_irb.current_basic_block->already_appended = true; if (ira->codegen->verbose_ir) { - fprintf(stderr, "append new bb %s_%zu\n", ira->new_irb.current_basic_block->name_hint, + fprintf(stderr, "append new bb %s_%" PRIu32 "\n", ira->new_irb.current_basic_block->name_hint, ira->new_irb.current_basic_block->debug_id); } ira->new_irb.exec->basic_block_list.append(ira->new_irb.current_basic_block); } ira->instruction_index += 1; while (ira->instruction_index < ira->old_irb.current_basic_block->instruction_list.length) { - IrInstruction *next_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); + IrInstSrc *next_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); if (!next_instruction->is_gen) { - ir_add_error(ira, next_instruction, buf_sprintf("unreachable code")); + ir_add_error(ira, &next_instruction->base, buf_sprintf("unreachable code")); break; } ira->instruction_index += 1; @@ -11900,7 +12985,7 @@ static void ir_finish_bb(IrAnalyze *ira) { ir_start_next_bb(ira); } -static IrInstruction *ir_unreach_error(IrAnalyze *ira) { +static IrInstGen *ir_unreach_error(IrAnalyze *ira) { ira->old_bb_index = SIZE_MAX; if (ira->new_irb.exec->first_err_trace_msg == nullptr) { ira->new_irb.exec->first_err_trace_msg = ira->codegen->trace_err; @@ -11908,7 +12993,7 @@ static IrInstruction *ir_unreach_error(IrAnalyze *ira) { return ira->codegen->unreach_instruction; } -static bool ir_emit_backward_branch(IrAnalyze *ira, IrInstruction *source_instruction) { +static bool ir_emit_backward_branch(IrAnalyze *ira, IrInst* source_instruction) { size_t *bbc = ira->new_irb.exec->backward_branch_count; size_t *quota = ira->new_irb.exec->backward_branch_quota; @@ -11927,66 +13012,82 @@ static bool ir_emit_backward_branch(IrAnalyze *ira, IrInstruction *source_instru return true; } -static IrInstruction *ir_inline_bb(IrAnalyze *ira, IrInstruction *source_instruction, IrBasicBlock *old_bb) { +static IrInstGen *ir_inline_bb(IrAnalyze *ira, IrInst* source_instruction, IrBasicBlockSrc *old_bb) { if (old_bb->debug_id <= ira->old_irb.current_basic_block->debug_id) { if (!ir_emit_backward_branch(ira, source_instruction)) return ir_unreach_error(ira); } - old_bb->other = ira->old_irb.current_basic_block->other; + old_bb->child = ira->old_irb.current_basic_block->child; ir_start_bb(ira, old_bb, ira->old_irb.current_basic_block); return ira->codegen->unreach_instruction; } -static IrInstruction *ir_finish_anal(IrAnalyze *ira, IrInstruction *instruction) { +static IrInstGen *ir_finish_anal(IrAnalyze *ira, IrInstGen *instruction) { if (instruction->value->type->id == ZigTypeIdUnreachable) ir_finish_bb(ira); return instruction; } -static IrInstruction *ir_const_type(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) { - IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_type); +static IrInstGen *ir_const_fn(IrAnalyze *ira, IrInst *source_instr, ZigFn *fn_entry) { + IrInstGen *result = ir_const(ira, source_instr, fn_entry->type_entry); + result->value->special = ConstValSpecialStatic; + result->value->data.x_ptr.data.fn.fn_entry = fn_entry; + result->value->data.x_ptr.mut = ConstPtrMutComptimeConst; + result->value->data.x_ptr.special = ConstPtrSpecialFunction; + return result; +} + +static IrInstGen *ir_const_bound_fn(IrAnalyze *ira, IrInst *src_inst, ZigFn *fn_entry, IrInstGen *first_arg) { + IrInstGen *result = ir_const(ira, src_inst, get_bound_fn_type(ira->codegen, fn_entry)); + result->value->data.x_bound_fn.fn = fn_entry; + result->value->data.x_bound_fn.first_arg = first_arg; + return result; +} + +static IrInstGen *ir_const_type(IrAnalyze *ira, IrInst *source_instruction, ZigType *ty) { + IrInstGen *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_type); result->value->data.x_type = ty; return result; } -static IrInstruction *ir_const_bool(IrAnalyze *ira, IrInstruction *source_instruction, bool value) { - IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_bool); +static IrInstGen *ir_const_bool(IrAnalyze *ira, IrInst *source_instruction, bool value) { + IrInstGen *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_bool); result->value->data.x_bool = value; return result; } -static IrInstruction *ir_const_undef(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) { - IrInstruction *result = ir_const(ira, source_instruction, ty); +static IrInstGen *ir_const_undef(IrAnalyze *ira, IrInst *source_instruction, ZigType *ty) { + IrInstGen *result = ir_const(ira, source_instruction, ty); result->value->special = ConstValSpecialUndef; return result; } -static IrInstruction *ir_const_unreachable(IrAnalyze *ira, IrInstruction *source_instruction) { - IrInstruction *result = ir_const_noval(ira, source_instruction); +static IrInstGen *ir_const_unreachable(IrAnalyze *ira, IrInst *source_instruction) { + IrInstGen *result = ir_const_noval(ira, source_instruction); result->value = ira->codegen->intern.for_unreachable(); return result; } -static IrInstruction *ir_const_void(IrAnalyze *ira, IrInstruction *source_instruction) { - IrInstruction *result = ir_const_noval(ira, source_instruction); +static IrInstGen *ir_const_void(IrAnalyze *ira, IrInst *source_instruction) { + IrInstGen *result = ir_const_noval(ira, source_instruction); result->value = ira->codegen->intern.for_void(); return result; } -static IrInstruction *ir_const_unsigned(IrAnalyze *ira, IrInstruction *source_instruction, uint64_t value) { - IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_num_lit_int); +static IrInstGen *ir_const_unsigned(IrAnalyze *ira, IrInst *source_instruction, uint64_t value) { + IrInstGen *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_num_lit_int); bigint_init_unsigned(&result->value->data.x_bigint, value); return result; } -static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instruction, +static IrInstGen *ir_get_const_ptr(IrAnalyze *ira, IrInst *instruction, ZigValue *pointee, ZigType *pointee_type, ConstPtrMut ptr_mut, bool ptr_is_const, bool ptr_is_volatile, uint32_t ptr_align) { ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, pointee_type, ptr_is_const, ptr_is_volatile, PtrLenSingle, ptr_align, 0, 0, false); - IrInstruction *const_instr = ir_const(ira, instruction, ptr_type); + IrInstGen *const_instr = ir_const(ira, instruction, ptr_type); ZigValue *const_val = const_instr->value; const_val->data.x_ptr.special = ConstPtrSpecialRef; const_val->data.x_ptr.mut = ptr_mut; @@ -11994,7 +13095,7 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio return const_instr; } -static Error ir_resolve_const_val(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, +static Error ir_resolve_const_val(CodeGen *codegen, IrExecutableGen *exec, AstNode *source_node, ZigValue *val, UndefAllowed undef_allowed) { Error err; @@ -12006,14 +13107,14 @@ static Error ir_resolve_const_val(CodeGen *codegen, IrExecutable *exec, AstNode if (!type_has_bits(val->type)) return ErrorNone; - exec_add_error_node(codegen, exec, source_node, + exec_add_error_node_gen(codegen, exec, source_node, buf_sprintf("unable to evaluate constant expression")); return ErrorSemanticAnalyzeFail; case ConstValSpecialUndef: if (undef_allowed == UndefOk || undef_allowed == LazyOk) return ErrorNone; - exec_add_error_node(codegen, exec, source_node, + exec_add_error_node_gen(codegen, exec, source_node, buf_sprintf("use of undefined value here causes undefined behavior")); return ErrorSemanticAnalyzeFail; case ConstValSpecialLazy: @@ -12028,9 +13129,9 @@ static Error ir_resolve_const_val(CodeGen *codegen, IrExecutable *exec, AstNode } } -static ZigValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) { +static ZigValue *ir_resolve_const(IrAnalyze *ira, IrInstGen *value, UndefAllowed undef_allowed) { Error err; - if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, value->source_node, + if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, value->base.source_node, value->value, undef_allowed))) { return nullptr; @@ -12041,7 +13142,7 @@ static ZigValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAll Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ZigValue *return_ptr, size_t *backward_branch_count, size_t *backward_branch_quota, ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, - IrExecutable *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef_allowed) + IrExecutableGen *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef_allowed) { Error err; @@ -12050,7 +13151,7 @@ Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, if (type_is_invalid(return_ptr->type)) return ErrorSemanticAnalyzeFail; - IrExecutable *ir_executable = allocate(1, "IrExecutablePass1"); + IrExecutableSrc *ir_executable = allocate(1, "IrExecutableSrc"); ir_executable->source_node = source_node; ir_executable->parent_exec = parent_exec; ir_executable->name = exec_name; @@ -12071,10 +13172,10 @@ Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, fprintf(stderr, "\nSource: "); ast_render(stderr, node, 4); fprintf(stderr, "\n{ // (IR)\n"); - ir_print(codegen, stderr, ir_executable, 2, IrPassSrc); + ir_print_src(codegen, stderr, ir_executable, 2); fprintf(stderr, "}\n"); } - IrExecutable *analyzed_executable = allocate(1, "IrExecutablePass2"); + IrExecutableGen *analyzed_executable = allocate(1, "IrExecutableGen"); analyzed_executable->source_node = source_node; analyzed_executable->parent_exec = parent_exec; analyzed_executable->source_exec = ir_executable; @@ -12093,7 +13194,7 @@ Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, if (codegen->verbose_ir) { fprintf(stderr, "{ // (analyzed)\n"); - ir_print(codegen, stderr, analyzed_executable, 2, IrPassGen); + ir_print_gen(codegen, stderr, analyzed_executable, 2); fprintf(stderr, "}\n"); } @@ -12109,12 +13210,12 @@ Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, return ErrorNone; } -static ErrorTableEntry *ir_resolve_error(IrAnalyze *ira, IrInstruction *err_value) { +static ErrorTableEntry *ir_resolve_error(IrAnalyze *ira, IrInstGen *err_value) { if (type_is_invalid(err_value->value->type)) return nullptr; if (err_value->value->type->id != ZigTypeIdErrorSet) { - ir_add_error(ira, err_value, + ir_add_error_node(ira, err_value->base.source_node, buf_sprintf("expected error, found '%s'", buf_ptr(&err_value->value->type->name))); return nullptr; } @@ -12127,7 +13228,7 @@ static ErrorTableEntry *ir_resolve_error(IrAnalyze *ira, IrInstruction *err_valu return const_val->data.x_err_set; } -static ZigType *ir_resolve_const_type(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, +static ZigType *ir_resolve_const_type(CodeGen *codegen, IrExecutableGen *exec, AstNode *source_node, ZigValue *val) { Error err; @@ -12138,18 +13239,18 @@ static ZigType *ir_resolve_const_type(CodeGen *codegen, IrExecutable *exec, AstN return val->data.x_type; } -static ZigValue *ir_resolve_type_lazy(IrAnalyze *ira, IrInstruction *type_value) { +static ZigValue *ir_resolve_type_lazy(IrAnalyze *ira, IrInstGen *type_value) { if (type_is_invalid(type_value->value->type)) return nullptr; if (type_value->value->type->id != ZigTypeIdMetaType) { - ir_add_error(ira, type_value, + ir_add_error_node(ira, type_value->base.source_node, buf_sprintf("expected type 'type', found '%s'", buf_ptr(&type_value->value->type->name))); return nullptr; } Error err; - if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, type_value->source_node, + if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, type_value->base.source_node, type_value->value, LazyOk))) { return nullptr; @@ -12158,17 +13259,17 @@ static ZigValue *ir_resolve_type_lazy(IrAnalyze *ira, IrInstruction *type_value) return type_value->value; } -static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { +static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstGen *type_value) { ZigValue *val = ir_resolve_type_lazy(ira, type_value); if (val == nullptr) return ira->codegen->builtin_types.entry_invalid; - return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, type_value->source_node, val); + return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, type_value->base.source_node, val); } -static Error ir_validate_vector_elem_type(IrAnalyze *ira, IrInstruction *source_instr, ZigType *elem_type) { +static Error ir_validate_vector_elem_type(IrAnalyze *ira, AstNode *source_node, ZigType *elem_type) { if (!is_valid_vector_elem_type(elem_type)) { - ir_add_error(ira, source_instr, + ir_add_error_node(ira, source_node, buf_sprintf("vector element type must be integer, float, bool, or pointer; '%s' is invalid", buf_ptr(&elem_type->name))); return ErrorSemanticAnalyzeFail; @@ -12176,28 +13277,28 @@ static Error ir_validate_vector_elem_type(IrAnalyze *ira, IrInstruction *source_ return ErrorNone; } -static ZigType *ir_resolve_vector_elem_type(IrAnalyze *ira, IrInstruction *elem_type_value) { +static ZigType *ir_resolve_vector_elem_type(IrAnalyze *ira, IrInstGen *elem_type_value) { Error err; ZigType *elem_type = ir_resolve_type(ira, elem_type_value); if (type_is_invalid(elem_type)) return ira->codegen->builtin_types.entry_invalid; - if ((err = ir_validate_vector_elem_type(ira, elem_type_value, elem_type))) + if ((err = ir_validate_vector_elem_type(ira, elem_type_value->base.source_node, elem_type))) return ira->codegen->builtin_types.entry_invalid; return elem_type; } -static ZigType *ir_resolve_int_type(IrAnalyze *ira, IrInstruction *type_value) { +static ZigType *ir_resolve_int_type(IrAnalyze *ira, IrInstGen *type_value) { ZigType *ty = ir_resolve_type(ira, type_value); if (type_is_invalid(ty)) return ira->codegen->builtin_types.entry_invalid; if (ty->id != ZigTypeIdInt) { - ErrorMsg *msg = ir_add_error(ira, type_value, + ErrorMsg *msg = ir_add_error_node(ira, type_value->base.source_node, buf_sprintf("expected integer type, found '%s'", buf_ptr(&ty->name))); if (ty->id == ZigTypeIdVector && ty->data.vector.elem_type->id == ZigTypeIdInt) { - add_error_note(ira->codegen, msg, type_value->source_node, + add_error_note(ira->codegen, msg, type_value->base.source_node, buf_sprintf("represent vectors with their element types, i.e. '%s'", buf_ptr(&ty->data.vector.elem_type->name))); } @@ -12207,12 +13308,12 @@ static ZigType *ir_resolve_int_type(IrAnalyze *ira, IrInstruction *type_value) { return ty; } -static ZigType *ir_resolve_error_set_type(IrAnalyze *ira, IrInstruction *op_source, IrInstruction *type_value) { +static ZigType *ir_resolve_error_set_type(IrAnalyze *ira, IrInst *op_source, IrInstGen *type_value) { if (type_is_invalid(type_value->value->type)) return ira->codegen->builtin_types.entry_invalid; if (type_value->value->type->id != ZigTypeIdMetaType) { - ErrorMsg *msg = ir_add_error(ira, type_value, + ErrorMsg *msg = ir_add_error_node(ira, type_value->base.source_node, buf_sprintf("expected error set type, found '%s'", buf_ptr(&type_value->value->type->name))); add_error_note(ira->codegen, msg, op_source->source_node, buf_sprintf("`||` merges error sets; `or` performs boolean OR")); @@ -12226,7 +13327,7 @@ static ZigType *ir_resolve_error_set_type(IrAnalyze *ira, IrInstruction *op_sour assert(const_val->data.x_type != nullptr); ZigType *result_type = const_val->data.x_type; if (result_type->id != ZigTypeIdErrorSet) { - ErrorMsg *msg = ir_add_error(ira, type_value, + ErrorMsg *msg = ir_add_error_node(ira, type_value->base.source_node, buf_sprintf("expected error set type, found type '%s'", buf_ptr(&result_type->name))); add_error_note(ira->codegen, msg, op_source->source_node, buf_sprintf("`||` merges error sets; `or` performs boolean OR")); @@ -12235,15 +13336,12 @@ static ZigType *ir_resolve_error_set_type(IrAnalyze *ira, IrInstruction *op_sour return result_type; } -static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { - if (fn_value == ira->codegen->invalid_instruction) - return nullptr; - +static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstGen *fn_value) { if (type_is_invalid(fn_value->value->type)) return nullptr; if (fn_value->value->type->id != ZigTypeIdFn) { - ir_add_error_node(ira, fn_value->source_node, + ir_add_error_node(ira, fn_value->base.source_node, buf_sprintf("expected function type, found '%s'", buf_ptr(&fn_value->value->type->name))); return nullptr; } @@ -12259,22 +13357,22 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { return const_val->data.x_ptr.data.fn.fn_entry; } -static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, - ZigType *wanted_type, ResultLoc *result_loc) +static IrInstGen *ir_analyze_optional_wrap(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *value, ZigType *wanted_type, ResultLoc *result_loc) { assert(wanted_type->id == ZigTypeIdOptional); if (instr_is_comptime(value)) { ZigType *payload_type = wanted_type->data.maybe.child_type; - IrInstruction *casted_payload = ir_implicit_cast(ira, value, payload_type); + IrInstGen *casted_payload = ir_implicit_cast(ira, value, payload_type); if (type_is_invalid(casted_payload->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *val = ir_resolve_const(ira, casted_payload, UndefOk); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, + IrInstGenConst *const_instruction = ir_create_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); const_instruction->base.value->special = ConstValSpecialStatic; if (types_have_same_zig_comptime_repr(ira->codegen, wanted_type, payload_type)) { @@ -12289,40 +13387,42 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so if (result_loc == nullptr && handle_is_ptr(wanted_type)) { result_loc = no_result_loc(); } - IrInstruction *result_loc_inst = nullptr; + IrInstGen *result_loc_inst = nullptr; if (result_loc != nullptr) { result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, true); - if (type_is_invalid(result_loc_inst->value->type) || instr_is_unreachable(result_loc_inst)) { + if (type_is_invalid(result_loc_inst->value->type) || + result_loc_inst->value->type->id == ZigTypeIdUnreachable) + { return result_loc_inst; } } - IrInstruction *result = ir_build_optional_wrap(ira, source_instr, wanted_type, value, result_loc_inst); + IrInstGen *result = ir_build_optional_wrap(ira, source_instr, wanted_type, value, result_loc_inst); result->value->data.rh_maybe = RuntimeHintOptionalNonNull; return result; } -static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *value, ZigType *wanted_type, ResultLoc *result_loc) +static IrInstGen *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *value, ZigType *wanted_type, ResultLoc *result_loc) { assert(wanted_type->id == ZigTypeIdErrorUnion); ZigType *payload_type = wanted_type->data.error_union.payload_type; ZigType *err_set_type = wanted_type->data.error_union.err_set_type; if (instr_is_comptime(value)) { - IrInstruction *casted_payload = ir_implicit_cast(ira, value, payload_type); + IrInstGen *casted_payload = ir_implicit_cast(ira, value, payload_type); if (type_is_invalid(casted_payload->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *val = ir_resolve_const(ira, casted_payload, UndefOk); if (val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *err_set_val = create_const_vals(1); err_set_val->type = err_set_type; err_set_val->special = ConstValSpecialStatic; err_set_val->data.x_err_set = nullptr; - IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, + IrInstGenConst *const_instruction = ir_create_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); const_instruction->base.value->type = wanted_type; const_instruction->base.value->special = ConstValSpecialStatic; @@ -12331,23 +13431,24 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction return &const_instruction->base; } - IrInstruction *result_loc_inst; + IrInstGen *result_loc_inst; if (handle_is_ptr(wanted_type)) { if (result_loc == nullptr) result_loc = no_result_loc(); result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, true); - if (type_is_invalid(result_loc_inst->value->type) || instr_is_unreachable(result_loc_inst)) { + if (type_is_invalid(result_loc_inst->value->type) || + result_loc_inst->value->type->id == ZigTypeIdUnreachable) { return result_loc_inst; } } else { result_loc_inst = nullptr; } - IrInstruction *result = ir_build_err_wrap_payload(ira, source_instr, wanted_type, value, result_loc_inst); + IrInstGen *result = ir_build_err_wrap_payload(ira, source_instr, wanted_type, value, result_loc_inst); result->value->data.rh_error_union = RuntimeHintErrorUnionNonError; return result; } -static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, +static IrInstGen *ir_analyze_err_set_cast(IrAnalyze *ira, IrInst* source_instr, IrInstGen *value, ZigType *wanted_type) { assert(value->value->type->id == ZigTypeIdErrorSet); @@ -12356,10 +13457,10 @@ static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *sou if (instr_is_comptime(value)) { ZigValue *val = ir_resolve_const(ira, value, UndefBad); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (!resolve_inferred_error_set(ira->codegen, wanted_type, source_instr->source_node)) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (!type_is_global_error_set(wanted_type)) { bool subset = false; @@ -12373,11 +13474,11 @@ static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *sou ir_add_error(ira, source_instr, buf_sprintf("error.%s not a member of error set '%s'", buf_ptr(&val->data.x_err_set->name), buf_ptr(&wanted_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } - IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, + IrInstGenConst *const_instruction = ir_create_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); const_instruction->base.value->type = wanted_type; const_instruction->base.value->special = ConstValSpecialStatic; @@ -12385,18 +13486,16 @@ static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *sou return &const_instruction->base; } - IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node, wanted_type, value, CastOpErrSet); - result->value->type = wanted_type; - return result; + return ir_build_cast(ira, source_instr, wanted_type, value, CastOpErrSet); } -static IrInstruction *ir_analyze_frame_ptr_to_anyframe(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *frame_ptr, ZigType *wanted_type) +static IrInstGen *ir_analyze_frame_ptr_to_anyframe(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *frame_ptr, ZigType *wanted_type) { if (instr_is_comptime(frame_ptr)) { ZigValue *ptr_val = ir_resolve_const(ira, frame_ptr, UndefBad); if (ptr_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ir_assert(ptr_val->type->id == ZigTypeIdPointer, source_instr); if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) { @@ -12404,44 +13503,38 @@ static IrInstruction *ir_analyze_frame_ptr_to_anyframe(IrAnalyze *ira, IrInstruc } } - IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node, - wanted_type, frame_ptr, CastOpBitCast); - result->value->type = wanted_type; - return result; + return ir_build_cast(ira, source_instr, wanted_type, frame_ptr, CastOpBitCast); } -static IrInstruction *ir_analyze_anyframe_to_anyframe(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *value, ZigType *wanted_type) +static IrInstGen *ir_analyze_anyframe_to_anyframe(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *value, ZigType *wanted_type) { if (instr_is_comptime(value)) { zig_panic("TODO comptime anyframe->T to anyframe"); } - IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node, - wanted_type, value, CastOpBitCast); - result->value->type = wanted_type; - return result; + return ir_build_cast(ira, source_instr, wanted_type, value, CastOpBitCast); } -static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, +static IrInstGen *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInst* source_instr, IrInstGen *value, ZigType *wanted_type, ResultLoc *result_loc) { assert(wanted_type->id == ZigTypeIdErrorUnion); - IrInstruction *casted_value = ir_implicit_cast(ira, value, wanted_type->data.error_union.err_set_type); + IrInstGen *casted_value = ir_implicit_cast(ira, value, wanted_type->data.error_union.err_set_type); if (instr_is_comptime(casted_value)) { ZigValue *val = ir_resolve_const(ira, casted_value, UndefBad); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *err_set_val = create_const_vals(1); err_set_val->special = ConstValSpecialStatic; err_set_val->type = wanted_type->data.error_union.err_set_type; err_set_val->data.x_err_set = val->data.x_err_set; - IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, + IrInstGenConst *const_instruction = ir_create_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); const_instruction->base.value->type = wanted_type; const_instruction->base.value->special = ConstValSpecialStatic; @@ -12450,11 +13543,13 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so return &const_instruction->base; } - IrInstruction *result_loc_inst; + IrInstGen *result_loc_inst; if (handle_is_ptr(wanted_type)) { if (result_loc == nullptr) result_loc = no_result_loc(); result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, true); - if (type_is_invalid(result_loc_inst->value->type) || instr_is_unreachable(result_loc_inst)) { + if (type_is_invalid(result_loc_inst->value->type) || + result_loc_inst->value->type->id == ZigTypeIdUnreachable) + { return result_loc_inst; } } else { @@ -12462,19 +13557,19 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so } - IrInstruction *result = ir_build_err_wrap_code(ira, source_instr, wanted_type, value, result_loc_inst); + IrInstGen *result = ir_build_err_wrap_code(ira, source_instr, wanted_type, value, result_loc_inst); result->value->data.rh_error_union = RuntimeHintErrorUnionError; return result; } -static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, ZigType *wanted_type) { +static IrInstGen *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value, ZigType *wanted_type) { assert(wanted_type->id == ZigTypeIdOptional); assert(instr_is_comptime(value)); ZigValue *val = ir_resolve_const(ira, value, UndefBad); assert(val != nullptr); - IrInstruction *result = ir_const(ira, source_instr, wanted_type); + IrInstGen *result = ir_const(ira, source_instr, wanted_type); result->value->special = ConstValSpecialStatic; if (get_codegen_ptr_type(wanted_type) != nullptr) { result->value->data.x_ptr.special = ConstPtrSpecialNull; @@ -12486,8 +13581,8 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so return result; } -static IrInstruction *ir_analyze_null_to_c_pointer(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *value, ZigType *wanted_type) +static IrInstGen *ir_analyze_null_to_c_pointer(IrAnalyze *ira, IrInst *source_instr, + IrInstGen *value, ZigType *wanted_type) { assert(wanted_type->id == ZigTypeIdPointer); assert(wanted_type->data.pointer.ptr_len == PtrLenC); @@ -12496,24 +13591,24 @@ static IrInstruction *ir_analyze_null_to_c_pointer(IrAnalyze *ira, IrInstruction ZigValue *val = ir_resolve_const(ira, value, UndefBad); assert(val != nullptr); - IrInstruction *result = ir_const(ira, source_instr, wanted_type); + IrInstGen *result = ir_const(ira, source_instr, wanted_type); result->value->data.x_ptr.special = ConstPtrSpecialNull; result->value->data.x_ptr.mut = ConstPtrMutComptimeConst; return result; } -static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value, +static IrInstGen *ir_get_ref(IrAnalyze *ira, IrInst* source_instruction, IrInstGen *value, bool is_const, bool is_volatile) { Error err; if (type_is_invalid(value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (instr_is_comptime(value)) { ZigValue *val = ir_resolve_const(ira, value, LazyOk); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return ir_get_const_ptr(ira, source_instruction, val, value->value->type, ConstPtrMutComptimeConst, is_const, is_volatile, 0); } @@ -12522,9 +13617,9 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi is_const, is_volatile, PtrLenSingle, 0, 0, 0, false); if ((err = type_resolve(ira->codegen, ptr_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *result_loc; + IrInstGen *result_loc; if (type_has_bits(ptr_type) && !handle_is_ptr(value->value->type)) { result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), value->value->type, nullptr, true, true); @@ -12532,12 +13627,12 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi result_loc = nullptr; } - IrInstruction *new_instruction = ir_build_ref_gen(ira, source_instruction, ptr_type, value, result_loc); + IrInstGen *new_instruction = ir_build_ref_gen(ira, source_instruction, ptr_type, value, result_loc); new_instruction->value->data.rh_ptr = RuntimeHintPtrStack; return new_instruction; } -static ZigType *ir_resolve_union_tag_type(IrAnalyze *ira, IrInstruction *source_instr, ZigType *union_type) { +static ZigType *ir_resolve_union_tag_type(IrAnalyze *ira, AstNode *source_node, ZigType *union_type) { assert(union_type->id == ZigTypeIdUnion); Error err; @@ -12549,36 +13644,36 @@ static ZigType *ir_resolve_union_tag_type(IrAnalyze *ira, IrInstruction *source_ assert(union_type->data.unionation.tag_type != nullptr); return union_type->data.unionation.tag_type; } else { - ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("union '%s' has no tag", + ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("union '%s' has no tag", buf_ptr(&union_type->name))); add_error_note(ira->codegen, msg, decl_node, buf_sprintf("consider 'union(enum)' here")); return ira->codegen->builtin_types.entry_invalid; } } -static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target) { +static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, IrInstGen *target) { Error err; - IrInstruction *enum_target; + IrInstGen *enum_target; ZigType *enum_type; if (target->value->type->id == ZigTypeIdUnion) { - enum_type = ir_resolve_union_tag_type(ira, target, target->value->type); + enum_type = ir_resolve_union_tag_type(ira, target->base.source_node, target->value->type); if (type_is_invalid(enum_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; enum_target = ir_implicit_cast(ira, target, enum_type); if (type_is_invalid(enum_target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else if (target->value->type->id == ZigTypeIdEnum) { enum_target = target; enum_type = target->value->type; } else { - ir_add_error(ira, target, + ir_add_error_node(ira, target->base.source_node, buf_sprintf("expected enum, found type '%s'", buf_ptr(&target->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if ((err = type_resolve(ira->codegen, enum_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *tag_type = enum_type->data.enumeration.tag_int_type; assert(tag_type->id == ZigTypeIdInt || tag_type->id == ZigTypeIdComptimeInt); @@ -12587,7 +13682,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour if (enum_type->data.enumeration.layout == ContainerLayoutAuto && enum_type->data.enumeration.src_field_count == 1) { - IrInstruction *result = ir_const(ira, source_instr, tag_type); + IrInstGen *result = ir_const(ira, source_instr, tag_type); init_const_bigint(result->value, tag_type, &enum_type->data.enumeration.fields[0].value); return result; @@ -12596,20 +13691,17 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour if (instr_is_comptime(enum_target)) { ZigValue *val = ir_resolve_const(ira, enum_target, UndefBad); if (!val) - return ira->codegen->invalid_instruction; - IrInstruction *result = ir_const(ira, source_instr, tag_type); + return ira->codegen->invalid_inst_gen; + IrInstGen *result = ir_const(ira, source_instr, tag_type); init_const_bigint(result->value, tag_type, &val->data.x_enum_tag); return result; } - IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope, - source_instr->source_node, enum_target); - result->value->type = tag_type; - return result; + return ir_build_widen_or_shorten(ira, source_instr->scope, source_instr->source_node, enum_target, tag_type); } -static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *target, ZigType *wanted_type) +static IrInstGen *ir_analyze_union_to_tag(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *target, ZigType *wanted_type) { assert(target->value->type->id == ZigTypeIdUnion); assert(wanted_type->id == ZigTypeIdEnum); @@ -12618,8 +13710,8 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou if (instr_is_comptime(target)) { ZigValue *val = ir_resolve_const(ira, target, UndefBad); if (!val) - return ira->codegen->invalid_instruction; - IrInstruction *result = ir_const(ira, source_instr, wanted_type); + return ira->codegen->invalid_inst_gen; + IrInstGen *result = ir_const(ira, source_instr, wanted_type); result->value->special = ConstValSpecialStatic; result->value->type = wanted_type; bigint_init_bigint(&result->value->data.x_enum_tag, &val->data.x_union.tag); @@ -12630,7 +13722,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou if (wanted_type->data.enumeration.layout == ContainerLayoutAuto && wanted_type->data.enumeration.src_field_count == 1) { - IrInstruction *result = ir_const(ira, source_instr, wanted_type); + IrInstGen *result = ir_const(ira, source_instr, wanted_type); result->value->special = ConstValSpecialStatic; result->value->type = wanted_type; TypeEnumField *enum_field = target->value->type->data.unionation.fields[0].enum_field; @@ -12638,48 +13730,45 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou return result; } - IrInstruction *result = ir_build_union_tag(&ira->new_irb, source_instr->scope, - source_instr->source_node, target); - result->value->type = wanted_type; - return result; + return ir_build_union_tag(ira, source_instr, target, wanted_type); } -static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *target, ZigType *wanted_type) +static IrInstGen *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *target, ZigType *wanted_type) { - IrInstruction *result = ir_const(ira, source_instr, wanted_type); + IrInstGen *result = ir_const(ira, source_instr, wanted_type); result->value->special = ConstValSpecialUndef; return result; } -static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *uncasted_target, ZigType *wanted_type) +static IrInstGen *ir_analyze_enum_to_union(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *uncasted_target, ZigType *wanted_type) { Error err; assert(wanted_type->id == ZigTypeIdUnion); if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *target = ir_implicit_cast(ira, uncasted_target, wanted_type->data.unionation.tag_type); + IrInstGen *target = ir_implicit_cast(ira, uncasted_target, wanted_type->data.unionation.tag_type); if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (instr_is_comptime(target)) { ZigValue *val = ir_resolve_const(ira, target, UndefBad); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; TypeUnionField *union_field = find_union_field_by_tag(wanted_type, &val->data.x_enum_tag); assert(union_field != nullptr); ZigType *field_type = resolve_union_field_type(ira->codegen, union_field); if (field_type == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if ((err = type_resolve(ira->codegen, field_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; switch (type_has_one_possible_value(ira->codegen, field_type)) { case OnePossibleValueInvalid: - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case OnePossibleValueNo: { AstNode *field_node = wanted_type->data.unionation.decl_node->data.container_decl.fields.at( union_field->enum_field->decl_index); @@ -12690,13 +13779,13 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so buf_ptr(union_field->name))); add_error_note(ira->codegen, msg, field_node, buf_sprintf("field '%s' declared here", buf_ptr(union_field->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } case OnePossibleValueYes: break; } - IrInstruction *result = ir_const(ira, source_instr, wanted_type); + IrInstGen *result = ir_const(ira, source_instr, wanted_type); result->value->special = ConstValSpecialStatic; result->value->type = wanted_type; bigint_init_bigint(&result->value->data.x_union.tag, &val->data.x_enum_tag); @@ -12709,9 +13798,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so // if the union has all fields 0 bits, we can do it // and in fact it's a noop cast because the union value is just the enum value if (wanted_type->data.unionation.gen_field_count == 0) { - IrInstruction *result = ir_build_cast(&ira->new_irb, target->scope, target->source_node, wanted_type, target, CastOpNoop); - result->value->type = wanted_type; - return result; + return ir_build_cast(ira, &target->base, wanted_type, target, CastOpNoop); } ErrorMsg *msg = ir_add_error(ira, source_instr, @@ -12721,10 +13808,10 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so TypeUnionField *union_field = &wanted_type->data.unionation.fields[i]; ZigType *field_type = resolve_union_field_type(ira->codegen, union_field); if (field_type == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; bool has_bits; if ((err = type_has_bits2(ira->codegen, field_type, &has_bits))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (has_bits) { AstNode *field_node = wanted_type->data.unionation.decl_node->data.container_decl.fields.at(i); add_error_note(ira->codegen, msg, field_node, @@ -12733,23 +13820,23 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so buf_ptr(&field_type->name))); } } - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } -static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *target, ZigType *wanted_type) +static IrInstGen *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *target, ZigType *wanted_type) { assert(wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdFloat); if (instr_is_comptime(target)) { ZigValue *val = ir_resolve_const(ira, target, UndefBad); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (wanted_type->id == ZigTypeIdInt) { if (bigint_cmp_zero(&val->data.x_bigint) == CmpLT && !wanted_type->data.integral.is_signed) { ir_add_error(ira, source_instr, buf_sprintf("attempt to cast negative value to unsigned integer")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (!bigint_fits_in_bits(&val->data.x_bigint, wanted_type->data.integral.bit_count, wanted_type->data.integral.is_signed)) @@ -12757,10 +13844,10 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction ir_add_error(ira, source_instr, buf_sprintf("cast from '%s' to '%s' truncates bits", buf_ptr(&target->value->type->name), buf_ptr(&wanted_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } - IrInstruction *result = ir_const(ira, source_instr, wanted_type); + IrInstGen *result = ir_const(ira, source_instr, wanted_type); result->value->type = wanted_type; if (wanted_type->id == ZigTypeIdInt) { bigint_init_bigint(&result->value->data.x_bigint, &val->data.x_bigint); @@ -12777,19 +13864,16 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction assert(wanted_type->id == ZigTypeIdInt); assert(type_has_bits(target->value->type)); ir_build_assert_zero(ira, source_instr, target); - IrInstruction *result = ir_const_unsigned(ira, source_instr, 0); + IrInstGen *result = ir_const_unsigned(ira, source_instr, 0); result->value->type = wanted_type; return result; } - IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope, - source_instr->source_node, target); - result->value->type = wanted_type; - return result; + return ir_build_widen_or_shorten(ira, source_instr->scope, source_instr->source_node, target, wanted_type); } -static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *target, ZigType *wanted_type) +static IrInstGen *ir_analyze_int_to_enum(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *target, ZigType *wanted_type) { Error err; assert(wanted_type->id == ZigTypeIdEnum); @@ -12797,14 +13881,14 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour ZigType *actual_type = target->value->type; if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (actual_type != wanted_type->data.enumeration.tag_int_type) { ir_add_error(ira, source_instr, buf_sprintf("integer to enum cast from '%s' instead of its tag type, '%s'", buf_ptr(&actual_type->name), buf_ptr(&wanted_type->data.enumeration.tag_int_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } assert(actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt); @@ -12812,10 +13896,10 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour if (instr_is_comptime(target)) { ZigValue *val = ir_resolve_const(ira, target, UndefBad); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; TypeEnumField *field = find_enum_field_by_tag(wanted_type, &val->data.x_bigint); - if (field == nullptr && wanted_type->data.enumeration.layout != ContainerLayoutExtern) { + if (field == nullptr && !wanted_type->data.enumeration.non_exhaustive) { Buf *val_buf = buf_alloc(); bigint_append_buf(val_buf, &val->data.x_bigint, 10); ErrorMsg *msg = ir_add_error(ira, source_instr, @@ -12823,28 +13907,25 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour buf_ptr(&wanted_type->name), buf_ptr(val_buf))); add_error_note(ira->codegen, msg, wanted_type->data.enumeration.decl_node, buf_sprintf("'%s' declared here", buf_ptr(&wanted_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *result = ir_const(ira, source_instr, wanted_type); + IrInstGen *result = ir_const(ira, source_instr, wanted_type); bigint_init_bigint(&result->value->data.x_enum_tag, &val->data.x_bigint); return result; } - IrInstruction *result = ir_build_int_to_enum(&ira->new_irb, source_instr->scope, - source_instr->source_node, nullptr, target); - result->value->type = wanted_type; - return result; + return ir_build_int_to_enum_gen(ira, source_instr->scope, source_instr->source_node, wanted_type, target); } -static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *target, ZigType *wanted_type) +static IrInstGen *ir_analyze_number_to_literal(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *target, ZigType *wanted_type) { ZigValue *val = ir_resolve_const(ira, target, UndefBad); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *result = ir_const(ira, source_instr, wanted_type); + IrInstGen *result = ir_const(ira, source_instr, wanted_type); if (wanted_type->id == ZigTypeIdComptimeFloat) { float_init_float(result->value, val); } else if (wanted_type->id == ZigTypeIdComptimeInt) { @@ -12855,7 +13936,7 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction return result; } -static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target, +static IrInstGen *ir_analyze_int_to_err(IrAnalyze *ira, IrInst* source_instr, IrInstGen *target, ZigType *wanted_type) { assert(target->value->type->id == ZigTypeIdInt); @@ -12865,12 +13946,12 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc if (instr_is_comptime(target)) { ZigValue *val = ir_resolve_const(ira, target, UndefBad); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *result = ir_const(ira, source_instr, wanted_type); + IrInstGen *result = ir_const(ira, source_instr, wanted_type); if (!resolve_inferred_error_set(ira->codegen, wanted_type, source_instr->source_node)) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (type_is_global_error_set(wanted_type)) { @@ -12882,7 +13963,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc bigint_append_buf(val_buf, &val->data.x_bigint, 10); ir_add_error(ira, source_instr, buf_sprintf("integer value %s represents no error", buf_ptr(val_buf))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } size_t index = bigint_as_usize(&val->data.x_bigint); @@ -12906,7 +13987,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc bigint_append_buf(val_buf, &val->data.x_bigint, 10); ir_add_error(ira, source_instr, buf_sprintf("integer value %s represents no error in '%s'", buf_ptr(val_buf), buf_ptr(&wanted_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } result->value->data.x_err_set = err; @@ -12914,12 +13995,10 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc } } - IrInstruction *result = ir_build_int_to_err(&ira->new_irb, source_instr->scope, source_instr->source_node, target); - result->value->type = wanted_type; - return result; + return ir_build_int_to_err_gen(ira, source_instr->scope, source_instr->source_node, target, wanted_type); } -static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target, +static IrInstGen *ir_analyze_err_to_int(IrAnalyze *ira, IrInst* source_instr, IrInstGen *target, ZigType *wanted_type) { assert(wanted_type->id == ZigTypeIdInt); @@ -12929,9 +14008,9 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc if (instr_is_comptime(target)) { ZigValue *val = ir_resolve_const(ira, target, UndefBad); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *result = ir_const(ira, source_instr, wanted_type); + IrInstGen *result = ir_const(ira, source_instr, wanted_type); ErrorTableEntry *err; if (err_type->id == ZigTypeIdErrorUnion) { @@ -12951,7 +14030,7 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc ir_add_error_node(ira, source_instr->source_node, buf_sprintf("error code '%s' does not fit in '%s'", buf_ptr(&err->name), buf_ptr(&wanted_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } return result; @@ -12967,14 +14046,14 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc } if (!type_is_global_error_set(err_set_type)) { if (!resolve_inferred_error_set(ira->codegen, err_set_type, source_instr->source_node)) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (err_set_type->data.error_set.err_count == 0) { - IrInstruction *result = ir_const(ira, source_instr, wanted_type); + IrInstGen *result = ir_const(ira, source_instr, wanted_type); bigint_init_unsigned(&result->value->data.x_bigint, 0); return result; } else if (err_set_type->data.error_set.err_count == 1) { - IrInstruction *result = ir_const(ira, source_instr, wanted_type); + IrInstGen *result = ir_const(ira, source_instr, wanted_type); ErrorTableEntry *err = err_set_type->data.error_set.errors[0]; bigint_init_unsigned(&result->value->data.x_bigint, err->value); return result; @@ -12986,21 +14065,19 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc if (!bigint_fits_in_bits(&bn, wanted_type->data.integral.bit_count, wanted_type->data.integral.is_signed)) { ir_add_error_node(ira, source_instr->source_node, buf_sprintf("too many error values to fit in '%s'", buf_ptr(&wanted_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *result = ir_build_err_to_int(&ira->new_irb, source_instr->scope, source_instr->source_node, target); - result->value->type = wanted_type; - return result; + return ir_build_err_to_int_gen(ira, source_instr->scope, source_instr->source_node, target, wanted_type); } -static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target, +static IrInstGen *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInst* source_instr, IrInstGen *target, ZigType *wanted_type) { assert(wanted_type->id == ZigTypeIdPointer); Error err; if ((err = type_resolve(ira->codegen, target->value->type->data.pointer.child_type, ResolveStatusAlignmentKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; assert((wanted_type->data.pointer.is_const && target->value->type->data.pointer.is_const) || !target->value->type->data.pointer.is_const); wanted_type = adjust_ptr_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, target->value->type)); ZigType *array_type = wanted_type->data.pointer.child_type; @@ -13010,12 +14087,12 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou if (instr_is_comptime(target)) { ZigValue *val = ir_resolve_const(ira, target, UndefBad); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; assert(val->type->id == ZigTypeIdPointer); ZigValue *pointee = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node); if (pointee == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (pointee->special != ConstValSpecialRuntime) { ZigValue *array_val = create_const_vals(1); array_val->special = ConstValSpecialStatic; @@ -13025,7 +14102,7 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou array_val->parent.id = ConstParentIdScalar; array_val->parent.data.p_scalar.scalar_val = pointee; - IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, + IrInstGenConst *const_instruction = ir_create_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); const_instruction->base.value->type = wanted_type; const_instruction->base.value->special = ConstValSpecialStatic; @@ -13037,10 +14114,7 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou } // pointer to array and pointer to single item are represented the same way at runtime - IrInstruction *result = ir_build_cast(&ira->new_irb, target->scope, target->source_node, - wanted_type, target, CastOpBitCast); - result->value->type = wanted_type; - return result; + return ir_build_cast(ira, &target->base, wanted_type, target, CastOpBitCast); } static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCastOnly *cast_result, @@ -13228,12 +14302,12 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa } } -static IrInstruction *ir_analyze_array_to_vector(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *array, ZigType *vector_type) +static IrInstGen *ir_analyze_array_to_vector(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *array, ZigType *vector_type) { if (instr_is_comptime(array)) { // arrays and vectors have the same ZigValue representation - IrInstruction *result = ir_const(ira, source_instr, vector_type); + IrInstGen *result = ir_const(ira, source_instr, vector_type); copy_const_val(result->value, array->value); result->value->type = vector_type; return result; @@ -13241,12 +14315,12 @@ static IrInstruction *ir_analyze_array_to_vector(IrAnalyze *ira, IrInstruction * return ir_build_array_to_vector(ira, source_instr, array, vector_type); } -static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *vector, ZigType *array_type, ResultLoc *result_loc) +static IrInstGen *ir_analyze_vector_to_array(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *vector, ZigType *array_type, ResultLoc *result_loc) { if (instr_is_comptime(vector)) { // arrays and vectors have the same ZigValue representation - IrInstruction *result = ir_const(ira, source_instr, array_type); + IrInstGen *result = ir_const(ira, source_instr, array_type); copy_const_val(result->value, vector->value); result->value->type = array_type; return result; @@ -13254,18 +14328,17 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction * if (result_loc == nullptr) { result_loc = no_result_loc(); } - IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, array_type, nullptr, - true, true); - if (type_is_invalid(result_loc_inst->value->type) || instr_is_unreachable(result_loc_inst)) { + IrInstGen *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, array_type, nullptr, true, true); + if (type_is_invalid(result_loc_inst->value->type) || result_loc_inst->value->type->id == ZigTypeIdUnreachable) { return result_loc_inst; } return ir_build_vector_to_array(ira, source_instr, array_type, vector, result_loc_inst); } -static IrInstruction *ir_analyze_int_to_c_ptr(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *integer, ZigType *dest_type) +static IrInstGen *ir_analyze_int_to_c_ptr(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *integer, ZigType *dest_type) { - IrInstruction *unsigned_integer; + IrInstGen *unsigned_integer; if (instr_is_comptime(integer)) { unsigned_integer = integer; } else { @@ -13278,7 +14351,7 @@ static IrInstruction *ir_analyze_int_to_c_ptr(IrAnalyze *ira, IrInstruction *sou buf_sprintf("integer type '%s' too big for implicit @intToPtr to type '%s'", buf_ptr(&integer->value->type->name), buf_ptr(&dest_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (integer->value->type->data.integral.is_signed) { @@ -13286,7 +14359,7 @@ static IrInstruction *ir_analyze_int_to_c_ptr(IrAnalyze *ira, IrInstruction *sou integer->value->type->data.integral.bit_count); unsigned_integer = ir_analyze_bit_cast(ira, source_instr, integer, unsigned_int_type); if (type_is_invalid(unsigned_integer->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else { unsigned_integer = integer; } @@ -13306,14 +14379,14 @@ static bool is_pointery_and_elem_is_not_pointery(ZigType *ty) { return false; } -static IrInstruction *ir_analyze_enum_literal(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, +static IrInstGen *ir_analyze_enum_literal(IrAnalyze *ira, IrInst* source_instr, IrInstGen *value, ZigType *enum_type) { assert(enum_type->id == ZigTypeIdEnum); Error err; if ((err = type_resolve(ira->codegen, enum_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; TypeEnumField *field = find_enum_type_field(enum_type, value->value->data.x_enum_literal); if (field == nullptr) { @@ -13321,40 +14394,40 @@ static IrInstruction *ir_analyze_enum_literal(IrAnalyze *ira, IrInstruction *sou buf_ptr(&enum_type->name), buf_ptr(value->value->data.x_enum_literal))); add_error_note(ira->codegen, msg, enum_type->data.enumeration.decl_node, buf_sprintf("'%s' declared here", buf_ptr(&enum_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *result = ir_const(ira, source_instr, enum_type); + IrInstGen *result = ir_const(ira, source_instr, enum_type); bigint_init_bigint(&result->value->data.x_enum_tag, &field->value); return result; } -static IrInstruction *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *value, ZigType *wanted_type) +static IrInstGen *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *value, ZigType *wanted_type) { ir_add_error(ira, source_instr, buf_sprintf("TODO: type coercion of anon list literal to array")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } -static IrInstruction *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *value, ZigType *wanted_type) +static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *value, ZigType *wanted_type) { ir_add_error(ira, source_instr, buf_sprintf("TODO: type coercion of anon struct literal to struct")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } -static IrInstruction *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *value, ZigType *wanted_type) +static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *value, ZigType *wanted_type) { ir_add_error(ira, source_instr, buf_sprintf("TODO: type coercion of anon struct literal to union")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } // Add a compile error and return ErrorSemanticAnalyzeFail if the pointer alignment does not work, // otherwise return ErrorNone. Does not emit any instructions. // Assumes that the pointer types have element types with the same ABI alignment. Avoids resolving the // pointer types' alignments if both of the pointer types are ABI aligned. -static Error ir_cast_ptr_align(IrAnalyze *ira, IrInstruction *source_instr, ZigType *dest_ptr_type, +static Error ir_cast_ptr_align(IrAnalyze *ira, IrInst* source_instr, ZigType *dest_ptr_type, ZigType *src_ptr_type, AstNode *src_source_node) { Error err; @@ -13388,37 +14461,37 @@ static Error ir_cast_ptr_align(IrAnalyze *ira, IrInstruction *source_instr, ZigT return ErrorNone; } -static IrInstruction *ir_analyze_struct_value_field_value(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *struct_operand, TypeStructField *field) +static IrInstGen *ir_analyze_struct_value_field_value(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *struct_operand, TypeStructField *field) { - IrInstruction *struct_ptr = ir_get_ref(ira, source_instr, struct_operand, true, false); + IrInstGen *struct_ptr = ir_get_ref(ira, source_instr, struct_operand, true, false); if (type_is_invalid(struct_ptr->value->type)) - return ira->codegen->invalid_instruction; - IrInstruction *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, field, struct_ptr, + return ira->codegen->invalid_inst_gen; + IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, field, struct_ptr, struct_operand->value->type, false); if (type_is_invalid(field_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return ir_get_deref(ira, source_instr, field_ptr, nullptr); } -static IrInstruction *ir_analyze_optional_value_payload_value(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *optional_operand, bool safety_check_on) +static IrInstGen *ir_analyze_optional_value_payload_value(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *optional_operand, bool safety_check_on) { - IrInstruction *opt_ptr = ir_get_ref(ira, source_instr, optional_operand, true, false); - IrInstruction *payload_ptr = ir_analyze_unwrap_optional_payload(ira, source_instr, opt_ptr, + IrInstGen *opt_ptr = ir_get_ref(ira, source_instr, optional_operand, true, false); + IrInstGen *payload_ptr = ir_analyze_unwrap_optional_payload(ira, source_instr, opt_ptr, safety_check_on, false); return ir_get_deref(ira, source_instr, payload_ptr, nullptr); } -static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, - ZigType *wanted_type, IrInstruction *value) +static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr, + ZigType *wanted_type, IrInstGen *value) { Error err; ZigType *actual_type = value->value->type; AstNode *source_node = source_instr->source_node; if (type_is_invalid(wanted_type) || type_is_invalid(actual_type)) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } // This means the wanted type is anything. @@ -13430,7 +14503,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst ConstCastOnly const_cast_result = types_match_const_cast_only(ira, wanted_type, actual_type, source_node, false); if (const_cast_result.id == ConstCastResultIdInvalid) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (const_cast_result.id == ConstCastResultIdOk) { return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop); } @@ -13464,7 +14537,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) { return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type, nullptr); } else { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } else if ( wanted_child_type->id == ZigTypeIdPointer && @@ -13474,18 +14547,18 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst actual_type->data.pointer.child_type->id == ZigTypeIdArray) { if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if ((err = type_resolve(ira->codegen, wanted_child_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_child_type) && types_match_const_cast_only(ira, wanted_child_type->data.pointer.child_type, actual_type->data.pointer.child_type->data.array.child_type, source_node, !wanted_child_type->data.pointer.is_const).id == ConstCastResultIdOk) { - IrInstruction *cast1 = ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, + IrInstGen *cast1 = ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_child_type); if (type_is_invalid(cast1->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return ir_analyze_optional_wrap(ira, source_instr, cast1, wanted_type, nullptr); } } @@ -13503,7 +14576,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) { return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type, nullptr); } else { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } } @@ -13519,13 +14592,13 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst actual_type->id == ZigTypeIdComptimeInt || actual_type->id == ZigTypeIdComptimeFloat) { - IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value); + IrInstGen *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value); if (type_is_invalid(cast1->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1); + IrInstGen *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1); if (type_is_invalid(cast2->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return cast2; } @@ -13540,13 +14613,13 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat)) { if (value->value->special == ConstValSpecialUndef) { - IrInstruction *result = ir_const(ira, source_instr, wanted_type); + IrInstGen *result = ir_const(ira, source_instr, wanted_type); result->value->special = ConstValSpecialUndef; return result; } if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) { if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) { - IrInstruction *result = ir_const(ira, source_instr, wanted_type); + IrInstGen *result = ir_const(ira, source_instr, wanted_type); if (actual_type->id == ZigTypeIdComptimeInt || actual_type->id == ZigTypeIdInt) { copy_const_val(result->value, value->value); result->value->type = wanted_type; @@ -13555,7 +14628,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst } return result; } else if (wanted_type->id == ZigTypeIdComptimeFloat || wanted_type->id == ZigTypeIdFloat) { - IrInstruction *result = ir_const(ira, source_instr, wanted_type); + IrInstGen *result = ir_const(ira, source_instr, wanted_type); if (actual_type->id == ZigTypeIdComptimeInt || actual_type->id == ZigTypeIdInt) { BigFloat bf; bigfloat_init_bigint(&bf, &value->value->data.x_bigint); @@ -13567,7 +14640,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst } zig_unreachable(); } else { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } @@ -13603,13 +14676,13 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst actual_type->data.pointer.ptr_len == PtrLenSingle && actual_type->data.pointer.child_type->id == ZigTypeIdArray) { - IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.maybe.child_type, value); + IrInstGen *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.maybe.child_type, value); if (type_is_invalid(cast1->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1); + IrInstGen *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1); if (type_is_invalid(cast2->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return cast2; } @@ -13630,9 +14703,9 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst actual_array_type->data.array.sentinel))) { if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if ((err = type_resolve(ira->codegen, wanted_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type) && types_match_const_cast_only(ira, wanted_type->data.pointer.child_type, actual_type->data.pointer.child_type->data.array.child_type, source_node, @@ -13673,24 +14746,24 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if ((err = type_resolve(ira->codegen, slice_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ok_align = get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, slice_ptr_type); } if (ok_align) { if (wanted_type->id == ZigTypeIdErrorUnion) { - IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, slice_type, value); + IrInstGen *cast1 = ir_analyze_cast(ira, source_instr, slice_type, value); if (type_is_invalid(cast1->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1); + IrInstGen *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1); if (type_is_invalid(cast2->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return cast2; } else { @@ -13725,12 +14798,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if ((err = type_resolve(ira->codegen, slice_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ok_align = get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, slice_ptr_type); } @@ -13771,7 +14844,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst } } if (ok) { - IrInstruction *cast1 = ir_analyze_frame_ptr_to_anyframe(ira, source_instr, value, anyframe_type); + IrInstGen *cast1 = ir_analyze_frame_ptr_to_anyframe(ira, source_instr, value, anyframe_type); if (anyframe_type == wanted_type) return cast1; return ir_analyze_cast(ira, source_instr, wanted_type, cast1); @@ -13826,28 +14899,28 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst if (actual_type->id == ZigTypeIdEnumLiteral && (wanted_type->id == ZigTypeIdOptional && wanted_type->data.maybe.child_type->id == ZigTypeIdEnum)) { - IrInstruction *result = ir_analyze_enum_literal(ira, source_instr, value, wanted_type->data.maybe.child_type); - if (result == ira->codegen->invalid_instruction) + IrInstGen *result = ir_analyze_enum_literal(ira, source_instr, value, wanted_type->data.maybe.child_type); + if (type_is_invalid(result->value->type)) return result; - return ir_analyze_optional_wrap(ira, result, value, wanted_type, nullptr); + return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type, nullptr); } // cast from enum literal to error union when payload is an enum if (actual_type->id == ZigTypeIdEnumLiteral && (wanted_type->id == ZigTypeIdErrorUnion && wanted_type->data.error_union.payload_type->id == ZigTypeIdEnum)) { - IrInstruction *result = ir_analyze_enum_literal(ira, source_instr, value, wanted_type->data.error_union.payload_type); - if (result == ira->codegen->invalid_instruction) + IrInstGen *result = ir_analyze_enum_literal(ira, source_instr, value, wanted_type->data.error_union.payload_type); + if (type_is_invalid(result->value->type)) return result; - return ir_analyze_err_wrap_payload(ira, result, value, wanted_type, nullptr); + return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type, nullptr); } // cast from union to the enum type of the union if (actual_type->id == ZigTypeIdUnion && wanted_type->id == ZigTypeIdEnum) { if ((err = type_resolve(ira->codegen, actual_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (actual_type->data.unionation.tag_type == wanted_type) { return ir_analyze_union_to_tag(ira, source_instr, value, wanted_type); @@ -13875,8 +14948,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) && (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile)) { - if ((err = ir_cast_ptr_align(ira, source_instr, wanted_type, actual_type, value->source_node))) - return ira->codegen->invalid_instruction; + if ((err = ir_cast_ptr_align(ira, source_instr, wanted_type, actual_type, value->base.source_node))) + return ira->codegen->invalid_inst_gen; return ir_analyze_ptr_to_array(ira, source_instr, value, wanted_type); } @@ -13899,7 +14972,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst slice_ptr_type->data.pointer.sentinel)))) { TypeStructField *ptr_field = actual_type->data.structure.fields[slice_ptr_index]; - IrInstruction *slice_ptr = ir_analyze_struct_value_field_value(ira, source_instr, value, ptr_field); + IrInstGen *slice_ptr = ir_analyze_struct_value_field_value(ira, source_instr, value, ptr_field); return ir_implicit_cast2(ira, source_instr, slice_ptr, wanted_type); } } @@ -13930,7 +15003,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst { bool has_bits; if ((err = type_has_bits2(ira->codegen, actual_type, &has_bits))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (!has_bits) { return ir_get_ref(ira, source_instr, value, false, false); } @@ -13997,9 +15070,9 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst // T to ?U, where T implicitly casts to U if (wanted_type->id == ZigTypeIdOptional && actual_type->id != ZigTypeIdOptional) { - IrInstruction *cast1 = ir_implicit_cast2(ira, source_instr, value, wanted_type->data.maybe.child_type); + IrInstGen *cast1 = ir_implicit_cast2(ira, source_instr, value, wanted_type->data.maybe.child_type); if (type_is_invalid(cast1->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return ir_implicit_cast2(ira, source_instr, cast1, wanted_type); } @@ -14007,9 +15080,9 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst if (wanted_type->id == ZigTypeIdErrorUnion && actual_type->id != ZigTypeIdErrorUnion && actual_type->id != ZigTypeIdErrorSet) { - IrInstruction *cast1 = ir_implicit_cast2(ira, source_instr, value, wanted_type->data.error_union.payload_type); + IrInstGen *cast1 = ir_implicit_cast2(ira, source_instr, value, wanted_type->data.error_union.payload_type); if (type_is_invalid(cast1->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return ir_implicit_cast2(ira, source_instr, cast1, wanted_type); } @@ -14018,14 +15091,13 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst buf_ptr(&wanted_type->name), buf_ptr(&actual_type->name))); report_recursive_error(ira, source_instr->source_node, &const_cast_result, parent_msg); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } -static IrInstruction *ir_implicit_cast2(IrAnalyze *ira, IrInstruction *value_source_instr, - IrInstruction *value, ZigType *expected_type) +static IrInstGen *ir_implicit_cast2(IrAnalyze *ira, IrInst *value_source_instr, + IrInstGen *value, ZigType *expected_type) { assert(value); - assert(value != ira->codegen->invalid_instruction); assert(!expected_type || !type_is_invalid(expected_type)); assert(value->value->type); assert(!type_is_invalid(value->value->type)); @@ -14039,17 +15111,17 @@ static IrInstruction *ir_implicit_cast2(IrAnalyze *ira, IrInstruction *value_sou return ir_analyze_cast(ira, value_source_instr, expected_type, value); } -static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type) { - return ir_implicit_cast2(ira, value, value, expected_type); +static IrInstGen *ir_implicit_cast(IrAnalyze *ira, IrInstGen *value, ZigType *expected_type) { + return ir_implicit_cast2(ira, &value->base, value, expected_type); } -static ZigType *get_ptr_elem_type(CodeGen *g, IrInstruction *ptr) { - ir_assert(ptr->value->type->id == ZigTypeIdPointer, ptr); +static ZigType *get_ptr_elem_type(CodeGen *g, IrInstGen *ptr) { + ir_assert_gen(ptr->value->type->id == ZigTypeIdPointer, ptr); ZigType *elem_type = ptr->value->type->data.pointer.child_type; if (elem_type != g->builtin_types.entry_var) return elem_type; - if (ir_resolve_lazy(g, ptr->source_node, ptr->value)) + if (ir_resolve_lazy(g, ptr->base.source_node, ptr->value)) return g->builtin_types.entry_invalid; assert(value_is_comptime(ptr->value)); @@ -14057,28 +15129,28 @@ static ZigType *get_ptr_elem_type(CodeGen *g, IrInstruction *ptr) { return pointee->type; } -static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr, +static IrInstGen *ir_get_deref(IrAnalyze *ira, IrInst* source_instruction, IrInstGen *ptr, ResultLoc *result_loc) { Error err; ZigType *ptr_type = ptr->value->type; if (type_is_invalid(ptr_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (ptr_type->id != ZigTypeIdPointer) { ir_add_error_node(ira, source_instruction->source_node, buf_sprintf("attempt to dereference non-pointer type '%s'", buf_ptr(&ptr_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *child_type = ptr_type->data.pointer.child_type; if (type_is_invalid(child_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; // if the child type has one possible value, the deref is comptime switch (type_has_one_possible_value(ira->codegen, child_type)) { case OnePossibleValueInvalid: - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case OnePossibleValueYes: return ir_const_move(ira, source_instruction, get_the_one_possible_value(ira->codegen, child_type)); @@ -14087,8 +15159,8 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc } if (instr_is_comptime(ptr)) { if (ptr->value->special == ConstValSpecialUndef) { - ir_add_error(ira, ptr, buf_sprintf("attempt to dereference undefined value")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &ptr->base, buf_sprintf("attempt to dereference undefined value")); + return ira->codegen->invalid_inst_gen; } if (ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar) { ZigValue *pointee = const_ptr_pointee_unchecked(ira->codegen, ptr->value); @@ -14096,12 +15168,12 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc child_type = pointee->type; } if (pointee->special != ConstValSpecialRuntime) { - IrInstruction *result = ir_const(ira, source_instruction, child_type); + IrInstGen *result = ir_const(ira, source_instruction, child_type); if ((err = ir_read_const_ptr(ira, ira->codegen, source_instruction->source_node, result->value, ptr->value))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } result->value->type = child_type; return result; @@ -14110,38 +15182,37 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc } // if the instruction is a const ref instruction we can skip it - if (ptr->id == IrInstructionIdRef) { - IrInstructionRef *ref_inst = reinterpret_cast(ptr); - return ref_inst->value; + if (ptr->id == IrInstGenIdRef) { + IrInstGenRef *ref_inst = reinterpret_cast(ptr); + return ref_inst->operand; } // If the instruction is a element pointer instruction to a vector, we emit // vector element extract instruction rather than load pointer. If the // pointer type has non-VECTOR_INDEX_RUNTIME value, it would have been - // possible to implement this in the codegen for IrInstructionLoadPtrGen. + // possible to implement this in the codegen for IrInstGenLoadPtr. // However if it has VECTOR_INDEX_RUNTIME then we must emit a compile error // if the vector index cannot be determined right here, right now, because // the type information does not contain enough information to actually // perform a dereference. if (ptr_type->data.pointer.vector_index == VECTOR_INDEX_RUNTIME) { - if (ptr->id == IrInstructionIdElemPtr) { - IrInstructionElemPtr *elem_ptr = (IrInstructionElemPtr *)ptr; - IrInstruction *vector_loaded = ir_get_deref(ira, elem_ptr->array_ptr, + if (ptr->id == IrInstGenIdElemPtr) { + IrInstGenElemPtr *elem_ptr = (IrInstGenElemPtr *)ptr; + IrInstGen *vector_loaded = ir_get_deref(ira, &elem_ptr->array_ptr->base, elem_ptr->array_ptr, nullptr); - IrInstruction *elem_index = elem_ptr->elem_index; + IrInstGen *elem_index = elem_ptr->elem_index; return ir_build_vector_extract_elem(ira, source_instruction, vector_loaded, elem_index); } - ir_add_error(ira, ptr, + ir_add_error(ira, &ptr->base, buf_sprintf("unable to determine vector element index of type '%s'", buf_ptr(&ptr_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *result_loc_inst; + IrInstGen *result_loc_inst; if (ptr_type->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) { if (result_loc == nullptr) result_loc = no_result_loc(); - result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr, - true, true); - if (type_is_invalid(result_loc_inst->value->type) || instr_is_unreachable(result_loc_inst)) { + result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr, true, true); + if (type_is_invalid(result_loc_inst->value->type) || result_loc_inst->value->type->id == ZigTypeIdUnreachable) { return result_loc_inst; } } else { @@ -14151,7 +15222,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc return ir_build_load_ptr_gen(ira, source_instruction, ptr, child_type, result_loc_inst); } -static bool ir_resolve_const_align(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, +static bool ir_resolve_const_align(CodeGen *codegen, IrExecutableGen *exec, AstNode *source_node, ZigValue *const_val, uint32_t *out) { Error err; @@ -14160,12 +15231,12 @@ static bool ir_resolve_const_align(CodeGen *codegen, IrExecutable *exec, AstNode uint32_t align_bytes = bigint_as_u32(&const_val->data.x_bigint); if (align_bytes == 0) { - exec_add_error_node(codegen, exec, source_node, buf_sprintf("alignment must be >= 1")); + exec_add_error_node_gen(codegen, exec, source_node, buf_sprintf("alignment must be >= 1")); return false; } if (!is_power_of_2(align_bytes)) { - exec_add_error_node(codegen, exec, source_node, + exec_add_error_node_gen(codegen, exec, source_node, buf_sprintf("alignment value %" PRIu32 " is not a power of 2", align_bytes)); return false; } @@ -14174,7 +15245,7 @@ static bool ir_resolve_const_align(CodeGen *codegen, IrExecutable *exec, AstNode return true; } -static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, ZigType *elem_type, uint32_t *out) { +static bool ir_resolve_align(IrAnalyze *ira, IrInstGen *value, ZigType *elem_type, uint32_t *out) { if (type_is_invalid(value->value->type)) return false; @@ -14195,19 +15266,19 @@ static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, ZigType *elem } } - IrInstruction *casted_value = ir_implicit_cast(ira, value, get_align_amt_type(ira->codegen)); + IrInstGen *casted_value = ir_implicit_cast(ira, value, get_align_amt_type(ira->codegen)); if (type_is_invalid(casted_value->value->type)) return false; - return ir_resolve_const_align(ira->codegen, ira->new_irb.exec, value->source_node, + return ir_resolve_const_align(ira->codegen, ira->new_irb.exec, value->base.source_node, casted_value->value, out); } -static bool ir_resolve_unsigned(IrAnalyze *ira, IrInstruction *value, ZigType *int_type, uint64_t *out) { +static bool ir_resolve_unsigned(IrAnalyze *ira, IrInstGen *value, ZigType *int_type, uint64_t *out) { if (type_is_invalid(value->value->type)) return false; - IrInstruction *casted_value = ir_implicit_cast(ira, value, int_type); + IrInstGen *casted_value = ir_implicit_cast(ira, value, int_type); if (type_is_invalid(casted_value->value->type)) return false; @@ -14219,15 +15290,15 @@ static bool ir_resolve_unsigned(IrAnalyze *ira, IrInstruction *value, ZigType *i return true; } -static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) { +static bool ir_resolve_usize(IrAnalyze *ira, IrInstGen *value, uint64_t *out) { return ir_resolve_unsigned(ira, value, ira->codegen->builtin_types.entry_usize, out); } -static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *value, bool *out) { +static bool ir_resolve_bool(IrAnalyze *ira, IrInstGen *value, bool *out) { if (type_is_invalid(value->value->type)) return false; - IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->codegen->builtin_types.entry_bool); + IrInstGen *casted_value = ir_implicit_cast(ira, value, ira->codegen->builtin_types.entry_bool); if (type_is_invalid(casted_value->value->type)) return false; @@ -14239,7 +15310,7 @@ static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *value, bool *out) { return true; } -static bool ir_resolve_comptime(IrAnalyze *ira, IrInstruction *value, bool *out) { +static bool ir_resolve_comptime(IrAnalyze *ira, IrInstGen *value, bool *out) { if (!value) { *out = false; return true; @@ -14247,13 +15318,13 @@ static bool ir_resolve_comptime(IrAnalyze *ira, IrInstruction *value, bool *out) return ir_resolve_bool(ira, value, out); } -static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, AtomicOrder *out) { +static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstGen *value, AtomicOrder *out) { if (type_is_invalid(value->value->type)) return false; ZigType *atomic_order_type = get_builtin_type(ira->codegen, "AtomicOrder"); - IrInstruction *casted_value = ir_implicit_cast(ira, value, atomic_order_type); + IrInstGen *casted_value = ir_implicit_cast(ira, value, atomic_order_type); if (type_is_invalid(casted_value->value->type)) return false; @@ -14265,13 +15336,13 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic return true; } -static bool ir_resolve_atomic_rmw_op(IrAnalyze *ira, IrInstruction *value, AtomicRmwOp *out) { +static bool ir_resolve_atomic_rmw_op(IrAnalyze *ira, IrInstGen *value, AtomicRmwOp *out) { if (type_is_invalid(value->value->type)) return false; ZigType *atomic_rmw_op_type = get_builtin_type(ira->codegen, "AtomicRmwOp"); - IrInstruction *casted_value = ir_implicit_cast(ira, value, atomic_rmw_op_type); + IrInstGen *casted_value = ir_implicit_cast(ira, value, atomic_rmw_op_type); if (type_is_invalid(casted_value->value->type)) return false; @@ -14283,13 +15354,13 @@ static bool ir_resolve_atomic_rmw_op(IrAnalyze *ira, IrInstruction *value, Atomi return true; } -static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, GlobalLinkageId *out) { +static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstGen *value, GlobalLinkageId *out) { if (type_is_invalid(value->value->type)) return false; ZigType *global_linkage_type = get_builtin_type(ira->codegen, "GlobalLinkage"); - IrInstruction *casted_value = ir_implicit_cast(ira, value, global_linkage_type); + IrInstGen *casted_value = ir_implicit_cast(ira, value, global_linkage_type); if (type_is_invalid(casted_value->value->type)) return false; @@ -14301,13 +15372,13 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob return true; } -static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMode *out) { +static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstGen *value, FloatMode *out) { if (type_is_invalid(value->value->type)) return false; ZigType *float_mode_type = get_builtin_type(ira->codegen, "FloatMode"); - IrInstruction *casted_value = ir_implicit_cast(ira, value, float_mode_type); + IrInstGen *casted_value = ir_implicit_cast(ira, value, float_mode_type); if (type_is_invalid(casted_value->value->type)) return false; @@ -14319,14 +15390,14 @@ static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMod return true; } -static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { +static Buf *ir_resolve_str(IrAnalyze *ira, IrInstGen *value) { if (type_is_invalid(value->value->type)) return nullptr; ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8, true, false, PtrLenUnknown, 0, 0, 0, false); ZigType *str_type = get_slice_type(ira->codegen, ptr_type); - IrInstruction *casted_value = ir_implicit_cast(ira, value, str_type); + IrInstGen *casted_value = ir_implicit_cast(ira, value, str_type); if (type_is_invalid(casted_value->value->type)) return nullptr; @@ -14350,7 +15421,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { size_t new_index = ptr_field->data.x_ptr.data.base_array.elem_index + i; ZigValue *char_val = &array_val->data.x_array.data.s_none.elements[new_index]; if (char_val->special == ConstValSpecialUndef) { - ir_add_error(ira, casted_value, buf_sprintf("use of undefined value")); + ir_add_error(ira, &casted_value->base, buf_sprintf("use of undefined value")); return nullptr; } uint64_t big_c = bigint_as_u64(&char_val->data.x_bigint); @@ -14361,10 +15432,10 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { return result; } -static IrInstruction *ir_analyze_instruction_add_implicit_return_type(IrAnalyze *ira, - IrInstructionAddImplicitReturnType *instruction) +static IrInstGen *ir_analyze_instruction_add_implicit_return_type(IrAnalyze *ira, + IrInstSrcAddImplicitReturnType *instruction) { - IrInstruction *value = instruction->value->child; + IrInstGen *value = instruction->value->child; if (type_is_invalid(value->value->type)) return ir_unreach_error(ira); @@ -14372,15 +15443,15 @@ static IrInstruction *ir_analyze_instruction_add_implicit_return_type(IrAnalyze ira->src_implicit_return_type_list.append(value); } - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } -static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructionReturn *instruction) { - IrInstruction *operand = instruction->operand->child; +static IrInstGen *ir_analyze_instruction_return(IrAnalyze *ira, IrInstSrcReturn *instruction) { + IrInstGen *operand = instruction->operand->child; if (type_is_invalid(operand->value->type)) return ir_unreach_error(ira); - IrInstruction *casted_operand = ir_implicit_cast(ira, operand, ira->explicit_return_type); + IrInstGen *casted_operand = ir_implicit_cast(ira, operand, ira->explicit_return_type); if (type_is_invalid(casted_operand->value->type)) { AstNode *source_node = ira->explicit_return_type_source_node; if (source_node != nullptr) { @@ -14395,9 +15466,7 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio handle_is_ptr(ira->explicit_return_type)) { // result location mechanism took care of it. - IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, nullptr); - result->value->type = ira->codegen->builtin_types.entry_unreachable; + IrInstGen *result = ir_build_return_gen(ira, &instruction->base.base, nullptr); return ir_finish_anal(ira, result); } @@ -14405,47 +15474,45 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio casted_operand->value->type->id == ZigTypeIdPointer && casted_operand->value->data.rh_ptr == RuntimeHintPtrStack) { - ir_add_error(ira, casted_operand, buf_sprintf("function returns address of local variable")); + ir_add_error(ira, &casted_operand->base, buf_sprintf("function returns address of local variable")); return ir_unreach_error(ira); } - IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, casted_operand); - result->value->type = ira->codegen->builtin_types.entry_unreachable; + IrInstGen *result = ir_build_return_gen(ira, &instruction->base.base, casted_operand); return ir_finish_anal(ira, result); } -static IrInstruction *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *instruction) { - return ir_const_move(ira, &instruction->base, instruction->base.value); +static IrInstGen *ir_analyze_instruction_const(IrAnalyze *ira, IrInstSrcConst *instruction) { + return ir_const_move(ira, &instruction->base.base, instruction->value); } -static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { - IrInstruction *op1 = bin_op_instruction->op1->child; +static IrInstGen *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstSrcBinOp *bin_op_instruction) { + IrInstGen *op1 = bin_op_instruction->op1->child; if (type_is_invalid(op1->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *op2 = bin_op_instruction->op2->child; + IrInstGen *op2 = bin_op_instruction->op2->child; if (type_is_invalid(op2->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *bool_type = ira->codegen->builtin_types.entry_bool; - IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, bool_type); - if (casted_op1 == ira->codegen->invalid_instruction) - return ira->codegen->invalid_instruction; + IrInstGen *casted_op1 = ir_implicit_cast(ira, op1, bool_type); + if (type_is_invalid(casted_op1->value->type)) + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, bool_type); - if (casted_op2 == ira->codegen->invalid_instruction) - return ira->codegen->invalid_instruction; + IrInstGen *casted_op2 = ir_implicit_cast(ira, op2, bool_type); + if (type_is_invalid(casted_op2->value->type)) + return ira->codegen->invalid_inst_gen; if (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2)) { ZigValue *op1_val = ir_resolve_const(ira, casted_op1, UndefBad); if (op1_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad); if (op2_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; assert(casted_op1->value->type->id == ZigTypeIdBool); assert(casted_op2->value->type->id == ZigTypeIdBool); @@ -14457,14 +15524,11 @@ static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp } else { zig_unreachable(); } - return ir_const_bool(ira, &bin_op_instruction->base, result_bool); + return ir_const_bool(ira, &bin_op_instruction->base.base, result_bool); } - IrInstruction *result = ir_build_bin_op(&ira->new_irb, - bin_op_instruction->base.scope, bin_op_instruction->base.source_node, + return ir_build_bin_op_gen(ira, &bin_op_instruction->base.base, bool_type, bin_op_instruction->op_id, casted_op1, casted_op2, bin_op_instruction->safety_check_on); - result->value->type = bool_type; - return result; } static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) { @@ -14529,12 +15593,13 @@ static void set_optional_payload(ZigValue *opt_val, ZigValue *payload) { } } -static IrInstruction *ir_evaluate_bin_op_cmp(IrAnalyze *ira, ZigType *resolved_type, - ZigValue *op1_val, ZigValue *op2_val, IrInstructionBinOp *bin_op_instruction, IrBinOp op_id, - bool one_possible_value) { +static IrInstGen *ir_evaluate_bin_op_cmp(IrAnalyze *ira, ZigType *resolved_type, + ZigValue *op1_val, ZigValue *op2_val, IrInstSrcBinOp *bin_op_instruction, IrBinOp op_id, + bool one_possible_value) +{ if (op1_val->special == ConstValSpecialUndef || op2_val->special == ConstValSpecialUndef) - return ir_const_undef(ira, &bin_op_instruction->base, resolved_type); + return ir_const_undef(ira, &bin_op_instruction->base.base, resolved_type); if (resolved_type->id == ZigTypeIdPointer && op_id != IrBinOpCmpEq && op_id != IrBinOpCmpNotEq) { if ((op1_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr || op1_val->data.x_ptr.special == ConstPtrSpecialNull) && @@ -14554,7 +15619,7 @@ static IrInstruction *ir_evaluate_bin_op_cmp(IrAnalyze *ira, ZigType *resolved_t cmp_result = CmpEQ; } bool answer = resolve_cmp_op_id(op_id, cmp_result); - return ir_const_bool(ira, &bin_op_instruction->base, answer); + return ir_const_bool(ira, &bin_op_instruction->base.base, answer); } } else { bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val); @@ -14566,7 +15631,7 @@ static IrInstruction *ir_evaluate_bin_op_cmp(IrAnalyze *ira, ZigType *resolved_t } else { zig_unreachable(); } - return ir_const_bool(ira, &bin_op_instruction->base, answer); + return ir_const_bool(ira, &bin_op_instruction->base.base, answer); } zig_unreachable(); } @@ -14620,7 +15685,7 @@ static Error lazy_cmp_zero(AstNode *source_node, ZigValue *val, Cmp *result) { zig_unreachable(); } -static ErrorMsg *ir_eval_bin_op_cmp_scalar(IrAnalyze *ira, IrInstruction *source_instr, +static ErrorMsg *ir_eval_bin_op_cmp_scalar(IrAnalyze *ira, IrInst* source_instr, ZigValue *op1_val, IrBinOp op_id, ZigValue *op2_val, ZigValue *out_val) { Error err; @@ -14698,14 +15763,14 @@ never_mind_just_calculate_it_normally: return nullptr; } if (op1_val->type->id == ZigTypeIdComptimeFloat) { - IrInstruction *tmp = ir_const_noval(ira, source_instr); + IrInstGen *tmp = ir_const_noval(ira, source_instr); tmp->value = op1_val; - IrInstruction *casted = ir_implicit_cast(ira, tmp, op2_val->type); + IrInstGen *casted = ir_implicit_cast(ira, tmp, op2_val->type); op1_val = casted->value; } else if (op2_val->type->id == ZigTypeIdComptimeFloat) { - IrInstruction *tmp = ir_const_noval(ira, source_instr); + IrInstGen *tmp = ir_const_noval(ira, source_instr); tmp->value = op2_val; - IrInstruction *casted = ir_implicit_cast(ira, tmp, op1_val->type); + IrInstGen *casted = ir_implicit_cast(ira, tmp, op1_val->type); op2_val = casted->value; } Cmp cmp_result = float_cmp(op1_val, op2_val); @@ -14747,8 +15812,8 @@ never_mind_just_calculate_it_normally: return nullptr; } -static IrInstruction *ir_analyze_bin_op_cmp_numeric(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *op1, IrInstruction *op2, IrBinOp op_id) +static IrInstGen *ir_analyze_bin_op_cmp_numeric(IrAnalyze *ira, IrInst *source_instr, + IrInstGen *op1, IrInstGen *op2, IrBinOp op_id) { Error err; @@ -14761,7 +15826,7 @@ static IrInstruction *ir_analyze_bin_op_cmp_numeric(IrAnalyze *ira, IrInstructio ir_add_error(ira, source_instr, buf_sprintf("vector length mismatch: %" PRIu32 " and %" PRIu32, op1->value->type->data.vector.len, op2->value->type->data.vector.len)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } result_type = get_vector_type(ira->codegen, op1->value->type->data.vector.len, scalar_result_type); op1_scalar_type = op1->value->type->data.vector.elem_type; @@ -14770,13 +15835,13 @@ static IrInstruction *ir_analyze_bin_op_cmp_numeric(IrAnalyze *ira, IrInstructio ir_add_error(ira, source_instr, buf_sprintf("mixed scalar and vector operands to comparison operator: '%s' and '%s'", buf_ptr(&op1->value->type->name), buf_ptr(&op2->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } bool opv_op1; switch (type_has_one_possible_value(ira->codegen, op1->value->type)) { case OnePossibleValueInvalid: - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case OnePossibleValueYes: opv_op1 = true; break; @@ -14787,7 +15852,7 @@ static IrInstruction *ir_analyze_bin_op_cmp_numeric(IrAnalyze *ira, IrInstructio bool opv_op2; switch (type_has_one_possible_value(ira->codegen, op2->value->type)) { case OnePossibleValueInvalid: - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case OnePossibleValueYes: opv_op2 = true; break; @@ -14798,21 +15863,21 @@ static IrInstruction *ir_analyze_bin_op_cmp_numeric(IrAnalyze *ira, IrInstructio Cmp op1_cmp_zero; bool have_op1_cmp_zero = false; if ((err = lazy_cmp_zero(source_instr->source_node, op1->value, &op1_cmp_zero))) { - if (err != ErrorNotLazy) return ira->codegen->invalid_instruction; + if (err != ErrorNotLazy) return ira->codegen->invalid_inst_gen; } else { have_op1_cmp_zero = true; } Cmp op2_cmp_zero; bool have_op2_cmp_zero = false; if ((err = lazy_cmp_zero(source_instr->source_node, op2->value, &op2_cmp_zero))) { - if (err != ErrorNotLazy) return ira->codegen->invalid_instruction; + if (err != ErrorNotLazy) return ira->codegen->invalid_inst_gen; } else { have_op2_cmp_zero = true; } if (((opv_op1 || instr_is_comptime(op1)) && (opv_op2 || instr_is_comptime(op2))) || (have_op1_cmp_zero && have_op2_cmp_zero)) { - IrInstruction *result_instruction = ir_const(ira, source_instr, result_type); + IrInstGen *result_instruction = ir_const(ira, source_instr, result_type); ZigValue *out_val = result_instruction->value; if (result_type->id == ZigTypeIdVector) { size_t len = result_type->data.vector.len; @@ -14830,7 +15895,7 @@ static IrInstruction *ir_analyze_bin_op_cmp_numeric(IrAnalyze *ira, IrInstructio if (msg != nullptr) { add_error_note(ira->codegen, msg, source_instr->source_node, buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } out_val->type = result_type; @@ -14839,7 +15904,7 @@ static IrInstruction *ir_analyze_bin_op_cmp_numeric(IrAnalyze *ira, IrInstructio if (ir_eval_bin_op_cmp_scalar(ira, source_instr, op1->value, op_id, op2->value, out_val) != nullptr) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } return result_instruction; @@ -14933,10 +15998,10 @@ static IrInstruction *ir_analyze_bin_op_cmp_numeric(IrAnalyze *ira, IrInstructio } ZigType *dest_type = (result_type->id == ZigTypeIdVector) ? get_vector_type(ira->codegen, result_type->data.vector.len, dest_scalar_type) : dest_scalar_type; - IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, dest_type); - IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, dest_type); + IrInstGen *casted_op1 = ir_implicit_cast(ira, op1, dest_type); + IrInstGen *casted_op2 = ir_implicit_cast(ira, op2, dest_type); if (type_is_invalid(casted_op1->value->type) || type_is_invalid(casted_op2->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return ir_build_bin_op_gen(ira, source_instr, result_type, op_id, casted_op1, casted_op2, true); } @@ -14966,12 +16031,12 @@ static IrInstruction *ir_analyze_bin_op_cmp_numeric(IrAnalyze *ira, IrInstructio if (instr_is_comptime(op1)) { ZigValue *op1_val = ir_resolve_const(ira, op1, UndefOk); if (op1_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (op1_val->special == ConstValSpecialUndef) return ir_const_undef(ira, source_instr, ira->codegen->builtin_types.entry_bool); if (result_type->id == ZigTypeIdVector) { - ir_add_error(ira, op1, buf_sprintf("compiler bug: TODO: support comptime vector here")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &op1->base, buf_sprintf("compiler bug: TODO: support comptime vector here")); + return ira->codegen->invalid_inst_gen; } bool is_unsigned; if (op1_is_float) { @@ -15010,12 +16075,12 @@ static IrInstruction *ir_analyze_bin_op_cmp_numeric(IrAnalyze *ira, IrInstructio if (instr_is_comptime(op2)) { ZigValue *op2_val = ir_resolve_const(ira, op2, UndefOk); if (op2_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (op2_val->special == ConstValSpecialUndef) return ir_const_undef(ira, source_instr, ira->codegen->builtin_types.entry_bool); if (result_type->id == ZigTypeIdVector) { - ir_add_error(ira, op2, buf_sprintf("compiler bug: TODO: support comptime vector here")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &op2->base, buf_sprintf("compiler bug: TODO: support comptime vector here")); + return ira->codegen->invalid_inst_gen; } bool is_unsigned; if (op2_is_float) { @@ -15056,35 +16121,35 @@ static IrInstruction *ir_analyze_bin_op_cmp_numeric(IrAnalyze *ira, IrInstructio ZigType *dest_type = (result_type->id == ZigTypeIdVector) ? get_vector_type(ira->codegen, result_type->data.vector.len, dest_scalar_type) : dest_scalar_type; - IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, dest_type); + IrInstGen *casted_op1 = ir_implicit_cast(ira, op1, dest_type); if (type_is_invalid(casted_op1->value->type)) - return ira->codegen->invalid_instruction; - IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, dest_type); + return ira->codegen->invalid_inst_gen; + IrInstGen *casted_op2 = ir_implicit_cast(ira, op2, dest_type); if (type_is_invalid(casted_op2->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return ir_build_bin_op_gen(ira, source_instr, result_type, op_id, casted_op1, casted_op2, true); } -static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { - IrInstruction *op1 = bin_op_instruction->op1->child; +static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_instruction) { + IrInstGen *op1 = bin_op_instruction->op1->child; if (type_is_invalid(op1->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *op2 = bin_op_instruction->op2->child; + IrInstGen *op2 = bin_op_instruction->op2->child; if (type_is_invalid(op2->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - AstNode *source_node = bin_op_instruction->base.source_node; + AstNode *source_node = bin_op_instruction->base.base.source_node; IrBinOp op_id = bin_op_instruction->op_id; bool is_equality_cmp = (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq); if (is_equality_cmp && op1->value->type->id == ZigTypeIdNull && op2->value->type->id == ZigTypeIdNull) { - return ir_const_bool(ira, &bin_op_instruction->base, (op_id == IrBinOpCmpEq)); + return ir_const_bool(ira, &bin_op_instruction->base.base, (op_id == IrBinOpCmpEq)); } else if (is_equality_cmp && ((op1->value->type->id == ZigTypeIdNull && op2->value->type->id == ZigTypeIdOptional) || (op2->value->type->id == ZigTypeIdNull && op1->value->type->id == ZigTypeIdOptional))) { - IrInstruction *maybe_op; + IrInstGen *maybe_op; if (op1->value->type->id == ZigTypeIdNull) { maybe_op = op2; } else if (op2->value->type->id == ZigTypeIdNull) { @@ -15095,21 +16160,16 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * if (instr_is_comptime(maybe_op)) { ZigValue *maybe_val = ir_resolve_const(ira, maybe_op, UndefBad); if (!maybe_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; bool is_null = optional_value_is_null(maybe_val); bool bool_result = (op_id == IrBinOpCmpEq) ? is_null : !is_null; - return ir_const_bool(ira, &bin_op_instruction->base, bool_result); + return ir_const_bool(ira, &bin_op_instruction->base.base, bool_result); } - IrInstruction *is_non_null = ir_build_test_nonnull(&ira->new_irb, bin_op_instruction->base.scope, - source_node, maybe_op); - is_non_null->value->type = ira->codegen->builtin_types.entry_bool; + IrInstGen *is_non_null = ir_build_test_non_null_gen(ira, &bin_op_instruction->base.base, maybe_op); if (op_id == IrBinOpCmpEq) { - IrInstruction *result = ir_build_bool_not(&ira->new_irb, bin_op_instruction->base.scope, - bin_op_instruction->base.source_node, is_non_null); - result->value->type = ira->codegen->builtin_types.entry_bool; - return result; + return ir_build_bool_not_gen(ira, &bin_op_instruction->base.base, is_non_null); } else { return is_non_null; } @@ -15119,7 +16179,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * (op2->value->type->id == ZigTypeIdNull && op1->value->type->id == ZigTypeIdPointer && op1->value->type->data.pointer.ptr_len == PtrLenC))) { - IrInstruction *c_ptr_op; + IrInstGen *c_ptr_op; if (op1->value->type->id == ZigTypeIdNull) { c_ptr_op = op2; } else if (op2->value->type->id == ZigTypeIdNull) { @@ -15130,24 +16190,19 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * if (instr_is_comptime(c_ptr_op)) { ZigValue *c_ptr_val = ir_resolve_const(ira, c_ptr_op, UndefOk); if (!c_ptr_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (c_ptr_val->special == ConstValSpecialUndef) - return ir_const_undef(ira, &bin_op_instruction->base, ira->codegen->builtin_types.entry_bool); + return ir_const_undef(ira, &bin_op_instruction->base.base, ira->codegen->builtin_types.entry_bool); bool is_null = c_ptr_val->data.x_ptr.special == ConstPtrSpecialNull || (c_ptr_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr && c_ptr_val->data.x_ptr.data.hard_coded_addr.addr == 0); bool bool_result = (op_id == IrBinOpCmpEq) ? is_null : !is_null; - return ir_const_bool(ira, &bin_op_instruction->base, bool_result); + return ir_const_bool(ira, &bin_op_instruction->base.base, bool_result); } - IrInstruction *is_non_null = ir_build_test_nonnull(&ira->new_irb, bin_op_instruction->base.scope, - source_node, c_ptr_op); - is_non_null->value->type = ira->codegen->builtin_types.entry_bool; + IrInstGen *is_non_null = ir_build_test_non_null_gen(ira, &bin_op_instruction->base.base, c_ptr_op); if (op_id == IrBinOpCmpEq) { - IrInstruction *result = ir_build_bool_not(&ira->new_irb, bin_op_instruction->base.scope, - bin_op_instruction->base.source_node, is_non_null); - result->value->type = ira->codegen->builtin_types.entry_bool; - return result; + return ir_build_bool_not_gen(ira, &bin_op_instruction->base.base, is_non_null); } else { return is_non_null; } @@ -15155,61 +16210,57 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * ZigType *non_null_type = (op1->value->type->id == ZigTypeIdNull) ? op2->value->type : op1->value->type; ir_add_error_node(ira, source_node, buf_sprintf("comparison of '%s' with null", buf_ptr(&non_null_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else if (is_equality_cmp && ( (op1->value->type->id == ZigTypeIdEnumLiteral && op2->value->type->id == ZigTypeIdUnion) || (op2->value->type->id == ZigTypeIdEnumLiteral && op1->value->type->id == ZigTypeIdUnion))) { // Support equality comparison between a union's tag value and a enum literal - IrInstruction *union_val = op1->value->type->id == ZigTypeIdUnion ? op1 : op2; - IrInstruction *enum_val = op1->value->type->id == ZigTypeIdUnion ? op2 : op1; + IrInstGen *union_val = op1->value->type->id == ZigTypeIdUnion ? op1 : op2; + IrInstGen *enum_val = op1->value->type->id == ZigTypeIdUnion ? op2 : op1; ZigType *tag_type = union_val->value->type->data.unionation.tag_type; assert(tag_type != nullptr); - IrInstruction *casted_union = ir_implicit_cast(ira, union_val, tag_type); + IrInstGen *casted_union = ir_implicit_cast(ira, union_val, tag_type); if (type_is_invalid(casted_union->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_val = ir_implicit_cast(ira, enum_val, tag_type); + IrInstGen *casted_val = ir_implicit_cast(ira, enum_val, tag_type); if (type_is_invalid(casted_val->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (instr_is_comptime(casted_union)) { ZigValue *const_union_val = ir_resolve_const(ira, casted_union, UndefBad); if (!const_union_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *const_enum_val = ir_resolve_const(ira, casted_val, UndefBad); if (!const_enum_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; Cmp cmp_result = bigint_cmp(&const_union_val->data.x_union.tag, &const_enum_val->data.x_enum_tag); bool bool_result = (op_id == IrBinOpCmpEq) ? cmp_result == CmpEQ : cmp_result != CmpEQ; - return ir_const_bool(ira, &bin_op_instruction->base, bool_result); + return ir_const_bool(ira, &bin_op_instruction->base.base, bool_result); } - IrInstruction *result = ir_build_bin_op(&ira->new_irb, - bin_op_instruction->base.scope, bin_op_instruction->base.source_node, + return ir_build_bin_op_gen(ira, &bin_op_instruction->base.base, ira->codegen->builtin_types.entry_bool, op_id, casted_union, casted_val, bin_op_instruction->safety_check_on); - result->value->type = ira->codegen->builtin_types.entry_bool; - - return result; } if (op1->value->type->id == ZigTypeIdErrorSet && op2->value->type->id == ZigTypeIdErrorSet) { if (!is_equality_cmp) { ir_add_error_node(ira, source_node, buf_sprintf("operator not allowed for errors")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *intersect_type = get_error_set_intersection(ira, op1->value->type, op2->value->type, source_node); if (type_is_invalid(intersect_type)) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (!resolve_inferred_error_set(ira->codegen, intersect_type, source_node)) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } // exception if one of the operators has the type of the empty error set, we allow the comparison @@ -15226,7 +16277,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * } else { zig_unreachable(); } - return ir_const_bool(ira, &bin_op_instruction->base, answer); + return ir_const_bool(ira, &bin_op_instruction->base.base, answer); } if (!type_is_global_error_set(intersect_type)) { @@ -15234,7 +16285,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * ir_add_error_node(ira, source_node, buf_sprintf("error sets '%s' and '%s' have no common errors", buf_ptr(&op1->value->type->name), buf_ptr(&op2->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (op1->value->type->data.error_set.err_count == 1 && op2->value->type->data.error_set.err_count == 1) { bool are_equal = true; @@ -15246,17 +16297,17 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * } else { zig_unreachable(); } - return ir_const_bool(ira, &bin_op_instruction->base, answer); + return ir_const_bool(ira, &bin_op_instruction->base.base, answer); } } if (instr_is_comptime(op1) && instr_is_comptime(op2)) { ZigValue *op1_val = ir_resolve_const(ira, op1, UndefBad); if (op1_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *op2_val = ir_resolve_const(ira, op2, UndefBad); if (op2_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; bool answer; bool are_equal = op1_val->data.x_err_set->value == op2_val->data.x_err_set->value; @@ -15268,27 +16319,24 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * zig_unreachable(); } - return ir_const_bool(ira, &bin_op_instruction->base, answer); + return ir_const_bool(ira, &bin_op_instruction->base.base, answer); } - IrInstruction *result = ir_build_bin_op(&ira->new_irb, - bin_op_instruction->base.scope, bin_op_instruction->base.source_node, + return ir_build_bin_op_gen(ira, &bin_op_instruction->base.base, ira->codegen->builtin_types.entry_bool, op_id, op1, op2, bin_op_instruction->safety_check_on); - result->value->type = ira->codegen->builtin_types.entry_bool; - return result; } if (type_is_numeric(op1->value->type) && type_is_numeric(op2->value->type)) { // This operation allows any combination of integer and float types, regardless of the // signed-ness, comptime-ness, and bit-width. So peer type resolution is incorrect for // numeric types. - return ir_analyze_bin_op_cmp_numeric(ira, &bin_op_instruction->base, op1, op2, op_id); + return ir_analyze_bin_op_cmp_numeric(ira, &bin_op_instruction->base.base, op1, op2, op_id); } - IrInstruction *instructions[] = {op1, op2}; + IrInstGen *instructions[] = {op1, op2}; ZigType *resolved_type = ir_resolve_peer_types(ira, source_node, nullptr, instructions, 2); if (type_is_invalid(resolved_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; bool operator_allowed; switch (resolved_type->id) { @@ -15336,21 +16384,21 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * if (!operator_allowed) { ir_add_error_node(ira, source_node, buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, resolved_type); - if (casted_op1 == ira->codegen->invalid_instruction) - return ira->codegen->invalid_instruction; + IrInstGen *casted_op1 = ir_implicit_cast(ira, op1, resolved_type); + if (type_is_invalid(casted_op1->value->type)) + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, resolved_type); - if (casted_op2 == ira->codegen->invalid_instruction) - return ira->codegen->invalid_instruction; + IrInstGen *casted_op2 = ir_implicit_cast(ira, op2, resolved_type); + if (type_is_invalid(casted_op2->value->type)) + return ira->codegen->invalid_inst_gen; bool one_possible_value; switch (type_has_one_possible_value(ira->codegen, resolved_type)) { case OnePossibleValueInvalid: - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case OnePossibleValueYes: one_possible_value = true; break; @@ -15362,20 +16410,20 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) { ZigValue *op1_val = one_possible_value ? casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad); if (op1_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *op2_val = one_possible_value ? casted_op2->value : ir_resolve_const(ira, casted_op2, UndefBad); if (op2_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (resolved_type->id != ZigTypeIdVector) return ir_evaluate_bin_op_cmp(ira, resolved_type, op1_val, op2_val, bin_op_instruction, op_id, one_possible_value); - IrInstruction *result = ir_const(ira, &bin_op_instruction->base, + IrInstGen *result = ir_const(ira, &bin_op_instruction->base.base, get_vector_type(ira->codegen, resolved_type->data.vector.len, ira->codegen->builtin_types.entry_bool)); result->value->data.x_array.data.s_none.elements = create_const_vals(resolved_type->data.vector.len); expand_undef_array(ira->codegen, result->value); for (size_t i = 0;i < resolved_type->data.vector.len;i++) { - IrInstruction *cur_res = ir_evaluate_bin_op_cmp(ira, resolved_type->data.vector.elem_type, + IrInstGen *cur_res = ir_evaluate_bin_op_cmp(ira, resolved_type->data.vector.elem_type, &op1_val->data.x_array.data.s_none.elements[i], &op2_val->data.x_array.data.s_none.elements[i], bin_op_instruction, op_id, one_possible_value); @@ -15384,19 +16432,14 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * return result; } - IrInstruction *result = ir_build_bin_op(&ira->new_irb, - bin_op_instruction->base.scope, bin_op_instruction->base.source_node, + ZigType *res_type = (resolved_type->id == ZigTypeIdVector) ? + get_vector_type(ira->codegen, resolved_type->data.vector.len, ira->codegen->builtin_types.entry_bool) : + ira->codegen->builtin_types.entry_bool; + return ir_build_bin_op_gen(ira, &bin_op_instruction->base.base, res_type, op_id, casted_op1, casted_op2, bin_op_instruction->safety_check_on); - if (resolved_type->id == ZigTypeIdVector) { - result->value->type = get_vector_type(ira->codegen, resolved_type->data.vector.len, - ira->codegen->builtin_types.entry_bool); - } else { - result->value->type = ira->codegen->builtin_types.entry_bool; - } - return result; } -static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, IrInstruction *source_instr, ZigType *type_entry, +static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, IrInst* source_instr, ZigType *type_entry, ZigValue *op1_val, IrBinOp op_id, ZigValue *op2_val, ZigValue *out_val) { bool is_int; @@ -15576,10 +16619,10 @@ static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, IrInstruction *source_in } // This works on operands that have already been checked to be comptime known. -static IrInstruction *ir_analyze_math_op(IrAnalyze *ira, IrInstruction *source_instr, +static IrInstGen *ir_analyze_math_op(IrAnalyze *ira, IrInst* source_instr, ZigType *type_entry, ZigValue *op1_val, IrBinOp op_id, ZigValue *op2_val) { - IrInstruction *result_instruction = ir_const(ira, source_instr, type_entry); + IrInstGen *result_instruction = ir_const(ira, source_instr, type_entry); ZigValue *out_val = result_instruction->value; if (type_entry->id == ZigTypeIdVector) { expand_undef_array(ira->codegen, op1_val); @@ -15600,43 +16643,43 @@ static IrInstruction *ir_analyze_math_op(IrAnalyze *ira, IrInstruction *source_i if (msg != nullptr) { add_error_note(ira->codegen, msg, source_instr->source_node, buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } out_val->type = type_entry; out_val->special = ConstValSpecialStatic; } else { if (ir_eval_math_op_scalar(ira, source_instr, type_entry, op1_val, op_id, op2_val, out_val) != nullptr) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } return ir_implicit_cast(ira, result_instruction, type_entry); } -static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { - IrInstruction *op1 = bin_op_instruction->op1->child; +static IrInstGen *ir_analyze_bit_shift(IrAnalyze *ira, IrInstSrcBinOp *bin_op_instruction) { + IrInstGen *op1 = bin_op_instruction->op1->child; if (type_is_invalid(op1->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (op1->value->type->id != ZigTypeIdInt && op1->value->type->id != ZigTypeIdComptimeInt) { - ir_add_error(ira, bin_op_instruction->op1, + ir_add_error(ira, &bin_op_instruction->op1->base, buf_sprintf("bit shifting operation expected integer type, found '%s'", buf_ptr(&op1->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *op2 = bin_op_instruction->op2->child; + IrInstGen *op2 = bin_op_instruction->op2->child; if (type_is_invalid(op2->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (op2->value->type->id != ZigTypeIdInt && op2->value->type->id != ZigTypeIdComptimeInt) { - ir_add_error(ira, bin_op_instruction->op2, + ir_add_error(ira, &bin_op_instruction->op2->base, buf_sprintf("shift amount has to be an integer type, but found '%s'", buf_ptr(&op2->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *casted_op2; + IrInstGen *casted_op2; IrBinOp op_id = bin_op_instruction->op_id; if (op1->value->type->id == ZigTypeIdComptimeInt) { casted_op2 = op2; @@ -15648,8 +16691,8 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b if (casted_op2->value->data.x_bigint.is_negative) { Buf *val_buf = buf_alloc(); bigint_append_buf(val_buf, &casted_op2->value->data.x_bigint, 10); - ir_add_error(ira, casted_op2, buf_sprintf("shift by negative value %s", buf_ptr(val_buf))); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &casted_op2->base, buf_sprintf("shift by negative value %s", buf_ptr(val_buf))); + return ira->codegen->invalid_inst_gen; } } else { ZigType *shift_amt_type = get_smallest_unsigned_int_type(ira->codegen, @@ -15659,57 +16702,51 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b ZigValue *op2_val = ir_resolve_const(ira, op2, UndefBad); if (op2_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (!bigint_fits_in_bits(&op2_val->data.x_bigint, shift_amt_type->data.integral.bit_count, op2_val->data.x_bigint.is_negative)) { Buf *val_buf = buf_alloc(); bigint_append_buf(val_buf, &op2_val->data.x_bigint, 10); ErrorMsg* msg = ir_add_error(ira, - &bin_op_instruction->base, + &bin_op_instruction->base.base, buf_sprintf("RHS of shift is too large for LHS type")); add_error_note( ira->codegen, msg, - op2->source_node, + op2->base.source_node, buf_sprintf("value %s cannot fit into type %s", buf_ptr(val_buf), buf_ptr(&shift_amt_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } casted_op2 = ir_implicit_cast(ira, op2, shift_amt_type); - if (casted_op2 == ira->codegen->invalid_instruction) - return ira->codegen->invalid_instruction; + if (type_is_invalid(casted_op2->value->type)) + return ira->codegen->invalid_inst_gen; } if (instr_is_comptime(op1) && instr_is_comptime(casted_op2)) { ZigValue *op1_val = ir_resolve_const(ira, op1, UndefBad); if (op1_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad); if (op2_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_analyze_math_op(ira, &bin_op_instruction->base, op1->value->type, op1_val, op_id, op2_val); + return ir_analyze_math_op(ira, &bin_op_instruction->base.base, op1->value->type, op1_val, op_id, op2_val); } else if (op1->value->type->id == ZigTypeIdComptimeInt) { - ir_add_error(ira, &bin_op_instruction->base, + ir_add_error(ira, &bin_op_instruction->base.base, buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else if (instr_is_comptime(casted_op2) && bigint_cmp_zero(&casted_op2->value->data.x_bigint) == CmpEQ) { - IrInstruction *result = ir_build_cast(&ira->new_irb, bin_op_instruction->base.scope, - bin_op_instruction->base.source_node, op1->value->type, op1, CastOpNoop); - result->value->type = op1->value->type; - return result; + return ir_build_cast(ira, &bin_op_instruction->base.base, op1->value->type, op1, CastOpNoop); } - IrInstruction *result = ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.scope, - bin_op_instruction->base.source_node, op_id, - op1, casted_op2, bin_op_instruction->safety_check_on); - result->value->type = op1->value->type; - return result; + return ir_build_bin_op_gen(ira, &bin_op_instruction->base.base, op1->value->type, + op_id, op1, casted_op2, bin_op_instruction->safety_check_on); } static bool ok_float_op(IrBinOp op) { @@ -15773,24 +16810,24 @@ static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) { zig_unreachable(); } -static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) { +static IrInstGen *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstSrcBinOp *instruction) { Error err; - IrInstruction *op1 = instruction->op1->child; + IrInstGen *op1 = instruction->op1->child; if (type_is_invalid(op1->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *op2 = instruction->op2->child; + IrInstGen *op2 = instruction->op2->child; if (type_is_invalid(op2->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; IrBinOp op_id = instruction->op_id; // look for pointer math if (is_pointer_arithmetic_allowed(op1->value->type, op_id)) { - IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize); + IrInstGen *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize); if (type_is_invalid(casted_op2->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; // If either operand is undef, result is undef. ZigValue *op1_val = nullptr; @@ -15798,28 +16835,28 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp if (instr_is_comptime(op1)) { op1_val = ir_resolve_const(ira, op1, UndefOk); if (op1_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (op1_val->special == ConstValSpecialUndef) - return ir_const_undef(ira, &instruction->base, op1->value->type); + return ir_const_undef(ira, &instruction->base.base, op1->value->type); } if (instr_is_comptime(casted_op2)) { op2_val = ir_resolve_const(ira, casted_op2, UndefOk); if (op2_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (op2_val->special == ConstValSpecialUndef) - return ir_const_undef(ira, &instruction->base, op1->value->type); + return ir_const_undef(ira, &instruction->base.base, op1->value->type); } ZigType *elem_type = op1->value->type->data.pointer.child_type; if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; // NOTE: this variable is meaningful iff op2_val is not null! uint64_t byte_offset; if (op2_val != nullptr) { uint64_t elem_offset; if (!ir_resolve_usize(ira, casted_op2, &elem_offset)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; byte_offset = type_size(ira->codegen, elem_type) * elem_offset; } @@ -15834,7 +16871,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp { uint32_t align_bytes; if ((err = resolve_ptr_align(ira, op1->value->type, &align_bytes))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; // If the addend is not a comptime-known value we can still count on // it being a multiple of the type size @@ -15863,23 +16900,20 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp } else { zig_unreachable(); } - IrInstruction *result = ir_const(ira, &instruction->base, result_type); + IrInstGen *result = ir_const(ira, &instruction->base.base, result_type); result->value->data.x_ptr.special = ConstPtrSpecialHardCodedAddr; result->value->data.x_ptr.mut = ConstPtrMutRuntimeVar; result->value->data.x_ptr.data.hard_coded_addr.addr = new_addr; return result; } - IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, op_id, op1, casted_op2, true); - result->value->type = result_type; - return result; + return ir_build_bin_op_gen(ira, &instruction->base.base, result_type, op_id, op1, casted_op2, true); } - IrInstruction *instructions[] = {op1, op2}; - ZigType *resolved_type = ir_resolve_peer_types(ira, instruction->base.source_node, nullptr, instructions, 2); + IrInstGen *instructions[] = {op1, op2}; + ZigType *resolved_type = ir_resolve_peer_types(ira, instruction->base.base.source_node, nullptr, instructions, 2); if (type_is_invalid(resolved_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; bool is_int = resolved_type->id == ZigTypeIdInt || resolved_type->id == ZigTypeIdComptimeInt; bool is_float = resolved_type->id == ZigTypeIdFloat || resolved_type->id == ZigTypeIdComptimeFloat; @@ -15899,11 +16933,11 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp if (instr_is_comptime(op1) && instr_is_comptime(op2)) { ZigValue *op1_val = ir_resolve_const(ira, op1, UndefBad); if (op1_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *op2_val = ir_resolve_const(ira, op2, UndefBad); if (op2_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (bigint_cmp_zero(&op2_val->data.x_bigint) == CmpEQ) { // the division by zero error will be caught later, but we don't have a @@ -15922,11 +16956,11 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp } } if (!ok) { - ir_add_error(ira, &instruction->base, + ir_add_error(ira, &instruction->base.base, buf_sprintf("division with '%s' and '%s': signed integers must use @divTrunc, @divFloor, or @divExact", buf_ptr(&op1->value->type->name), buf_ptr(&op2->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } else { op_id = IrBinOpDivTrunc; @@ -15937,12 +16971,12 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp if (instr_is_comptime(op1) && instr_is_comptime(op2)) { ZigValue *op1_val = ir_resolve_const(ira, op1, UndefBad); if (op1_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (is_int) { ZigValue *op2_val = ir_resolve_const(ira, op2, UndefBad); if (op2_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (bigint_cmp_zero(&op2->value->data.x_bigint) == CmpEQ) { // the division by zero error will be caught later, but we don't @@ -15956,13 +16990,13 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp ok = bigint_cmp(&rem_result, &mod_result) == CmpEQ; } } else { - IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, resolved_type); - if (casted_op2 == ira->codegen->invalid_instruction) - return ira->codegen->invalid_instruction; + IrInstGen *casted_op2 = ir_implicit_cast(ira, op2, resolved_type); + if (type_is_invalid(casted_op2->value->type)) + return ira->codegen->invalid_inst_gen; ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad); if (op2_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (float_cmp_zero(casted_op2->value) == CmpEQ) { // the division by zero error will be caught later, but we don't @@ -15978,11 +17012,11 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp } } if (!ok) { - ir_add_error(ira, &instruction->base, + ir_add_error(ira, &instruction->base.base, buf_sprintf("remainder division with '%s' and '%s': signed integers and floats must use @rem or @mod", buf_ptr(&op1->value->type->name), buf_ptr(&op2->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } op_id = IrBinOpRemRem; @@ -16002,12 +17036,12 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp } } if (!ok) { - AstNode *source_node = instruction->base.source_node; + AstNode *source_node = instruction->base.base.source_node; ir_add_error_node(ira, source_node, buf_sprintf("invalid operands to binary expression: '%s' and '%s'", buf_ptr(&op1->value->type->name), buf_ptr(&op2->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (resolved_type->id == ZigTypeIdComptimeInt) { @@ -16020,33 +17054,31 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp } } - IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, resolved_type); - if (casted_op1 == ira->codegen->invalid_instruction) - return ira->codegen->invalid_instruction; + IrInstGen *casted_op1 = ir_implicit_cast(ira, op1, resolved_type); + if (type_is_invalid(casted_op1->value->type)) + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, resolved_type); - if (casted_op2 == ira->codegen->invalid_instruction) - return ira->codegen->invalid_instruction; + IrInstGen *casted_op2 = ir_implicit_cast(ira, op2, resolved_type); + if (type_is_invalid(casted_op2->value->type)) + return ira->codegen->invalid_inst_gen; if (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2)) { ZigValue *op1_val = ir_resolve_const(ira, casted_op1, UndefBad); if (op1_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad); if (op2_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_analyze_math_op(ira, &instruction->base, resolved_type, op1_val, op_id, op2_val); + return ir_analyze_math_op(ira, &instruction->base.base, resolved_type, op1_val, op_id, op2_val); } - IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, op_id, casted_op1, casted_op2, instruction->safety_check_on); - result->value->type = resolved_type; - return result; + return ir_build_bin_op_gen(ira, &instruction->base.base, resolved_type, + op_id, casted_op1, casted_op2, instruction->safety_check_on); } -static IrInstruction *ir_analyze_tuple_cat(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *op1, IrInstruction *op2) +static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *op1, IrInstGen *op2) { Error err; ZigType *op1_type = op1->value->type; @@ -16063,9 +17095,9 @@ static IrInstruction *ir_analyze_tuple_cat(IrAnalyze *ira, IrInstruction *source new_type->data.structure.special = StructSpecialInferredTuple; new_type->data.structure.resolve_status = ResolveStatusBeingInferred; - bool is_comptime = ir_should_inline(ira->new_irb.exec, source_instr->scope); + bool is_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope); - IrInstruction *new_struct_ptr = ir_resolve_result(ira, source_instr, no_result_loc(), + IrInstGen *new_struct_ptr = ir_resolve_result(ira, source_instr, no_result_loc(), new_type, nullptr, false, true); uint32_t new_field_count = op1_field_count + op2_field_count; @@ -16089,13 +17121,13 @@ static IrInstruction *ir_analyze_tuple_cat(IrAnalyze *ira, IrInstruction *source new_field->is_comptime = src_field->is_comptime; } if ((err = type_resolve(ira->codegen, new_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - ZigList const_ptrs = {}; - IrInstruction *first_non_const_instruction = nullptr; + ZigList const_ptrs = {}; + IrInstGen *first_non_const_instruction = nullptr; for (uint32_t i = 0; i < new_field_count; i += 1) { TypeStructField *dst_field = new_type->data.structure.fields[i]; - IrInstruction *src_struct_op; + IrInstGen *src_struct_op; TypeStructField *src_field; if (i < op1_field_count) { src_field = op1_type->data.structure.fields[i]; @@ -16104,73 +17136,73 @@ static IrInstruction *ir_analyze_tuple_cat(IrAnalyze *ira, IrInstruction *source src_field = op2_type->data.structure.fields[i - op1_field_count]; src_struct_op = op2; } - IrInstruction *field_value = ir_analyze_struct_value_field_value(ira, source_instr, + IrInstGen *field_value = ir_analyze_struct_value_field_value(ira, source_instr, src_struct_op, src_field); if (type_is_invalid(field_value->value->type)) - return ira->codegen->invalid_instruction; - IrInstruction *dest_ptr = ir_analyze_struct_field_ptr(ira, source_instr, dst_field, + return ira->codegen->invalid_inst_gen; + IrInstGen *dest_ptr = ir_analyze_struct_field_ptr(ira, source_instr, dst_field, new_struct_ptr, new_type, true); if (type_is_invalid(dest_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (instr_is_comptime(field_value)) { const_ptrs.append(dest_ptr); } else { first_non_const_instruction = field_value; } - IrInstruction *store_ptr_inst = ir_analyze_store_ptr(ira, source_instr, dest_ptr, field_value, + IrInstGen *store_ptr_inst = ir_analyze_store_ptr(ira, source_instr, dest_ptr, field_value, true); if (type_is_invalid(store_ptr_inst->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (const_ptrs.length != new_field_count) { new_struct_ptr->value->special = ConstValSpecialRuntime; for (size_t i = 0; i < const_ptrs.length; i += 1) { - IrInstruction *elem_result_loc = const_ptrs.at(i); + IrInstGen *elem_result_loc = const_ptrs.at(i); assert(elem_result_loc->value->special == ConstValSpecialStatic); if (elem_result_loc->value->type->data.pointer.inferred_struct_field != nullptr) { // This field will be generated comptime; no need to do this. continue; } - IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr); + IrInstGen *deref = ir_get_deref(ira, &elem_result_loc->base, elem_result_loc, nullptr); elem_result_loc->value->special = ConstValSpecialRuntime; - ir_analyze_store_ptr(ira, elem_result_loc, elem_result_loc, deref, false); + ir_analyze_store_ptr(ira, &elem_result_loc->base, elem_result_loc, deref, false); } } - IrInstruction *result = ir_get_deref(ira, source_instr, new_struct_ptr, nullptr); + IrInstGen *result = ir_get_deref(ira, source_instr, new_struct_ptr, nullptr); if (instr_is_comptime(result)) return result; if (is_comptime) { - ir_add_error_node(ira, first_non_const_instruction->source_node, + ir_add_error(ira, &first_non_const_instruction->base, buf_sprintf("unable to evaluate constant expression")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } return result; } -static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruction) { - IrInstruction *op1 = instruction->op1->child; +static IrInstGen *ir_analyze_array_cat(IrAnalyze *ira, IrInstSrcBinOp *instruction) { + IrInstGen *op1 = instruction->op1->child; ZigType *op1_type = op1->value->type; if (type_is_invalid(op1_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *op2 = instruction->op2->child; + IrInstGen *op2 = instruction->op2->child; ZigType *op2_type = op2->value->type; if (type_is_invalid(op2_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (is_tuple(op1_type) && is_tuple(op2_type)) { - return ir_analyze_tuple_cat(ira, &instruction->base, op1, op2); + return ir_analyze_tuple_cat(ira, &instruction->base.base, op1, op2); } ZigValue *op1_val = ir_resolve_const(ira, op1, UndefBad); if (!op1_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *op2_val = ir_resolve_const(ira, op2, UndefBad); if (!op2_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *sentinel1 = nullptr; ZigValue *op1_array_val; @@ -16208,15 +17240,15 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i { ZigType *array_type = op1_type->data.pointer.child_type; child_type = array_type->data.array.child_type; - op1_array_val = const_ptr_pointee(ira, ira->codegen, op1_val, op1->source_node); + op1_array_val = const_ptr_pointee(ira, ira->codegen, op1_val, op1->base.source_node); if (op1_array_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; op1_array_index = 0; op1_array_end = array_type->data.array.len; sentinel1 = array_type->data.array.sentinel; } else { - ir_add_error(ira, op1, buf_sprintf("expected array, found '%s'", buf_ptr(&op1->value->type->name))); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &op1->base, buf_sprintf("expected array, found '%s'", buf_ptr(&op1->value->type->name))); + return ira->codegen->invalid_inst_gen; } ZigValue *sentinel2 = nullptr; @@ -16256,23 +17288,23 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i { ZigType *array_type = op2_type->data.pointer.child_type; op2_type_valid = array_type->data.array.child_type == child_type; - op2_array_val = const_ptr_pointee(ira, ira->codegen, op2_val, op2->source_node); + op2_array_val = const_ptr_pointee(ira, ira->codegen, op2_val, op2->base.source_node); if (op2_array_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; op2_array_index = 0; op2_array_end = array_type->data.array.len; sentinel2 = array_type->data.array.sentinel; } else { - ir_add_error(ira, op2, + ir_add_error(ira, &op2->base, buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (!op2_type_valid) { - ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'", + ir_add_error(ira, &op2->base, buf_sprintf("expected array of type '%s', found '%s'", buf_ptr(&child_type->name), buf_ptr(&op2->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigValue *sentinel; @@ -16289,7 +17321,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i } // The type of result is populated in the following if blocks - IrInstruction *result = ir_const(ira, &instruction->base, nullptr); + IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); ZigValue *out_val = result->value; ZigValue *out_array_val; @@ -16377,14 +17409,14 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i return result; } -static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *instruction) { - IrInstruction *op1 = instruction->op1->child; +static IrInstGen *ir_analyze_array_mult(IrAnalyze *ira, IrInstSrcBinOp *instruction) { + IrInstGen *op1 = instruction->op1->child; if (type_is_invalid(op1->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *op2 = instruction->op2->child; + IrInstGen *op2 = instruction->op2->child; if (type_is_invalid(op2->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; bool want_ptr_to_array = false; ZigType *array_type; @@ -16393,49 +17425,49 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp * array_type = op1->value->type; array_val = ir_resolve_const(ira, op1, UndefOk); if (array_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else if (op1->value->type->id == ZigTypeIdPointer && op1->value->type->data.pointer.ptr_len == PtrLenSingle && op1->value->type->data.pointer.child_type->id == ZigTypeIdArray) { array_type = op1->value->type->data.pointer.child_type; - IrInstruction *array_inst = ir_get_deref(ira, op1, op1, nullptr); + IrInstGen *array_inst = ir_get_deref(ira, &op1->base, op1, nullptr); if (type_is_invalid(array_inst->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; array_val = ir_resolve_const(ira, array_inst, UndefOk); if (array_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; want_ptr_to_array = true; } else { - ir_add_error(ira, op1, buf_sprintf("expected array type, found '%s'", buf_ptr(&op1->value->type->name))); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &op1->base, buf_sprintf("expected array type, found '%s'", buf_ptr(&op1->value->type->name))); + return ira->codegen->invalid_inst_gen; } uint64_t mult_amt; if (!ir_resolve_usize(ira, op2, &mult_amt)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; uint64_t old_array_len = array_type->data.array.len; uint64_t new_array_len; if (mul_u64_overflow(old_array_len, mult_amt, &new_array_len)) { - ir_add_error(ira, &instruction->base, buf_sprintf("operation results in overflow")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("operation results in overflow")); + return ira->codegen->invalid_inst_gen; } ZigType *child_type = array_type->data.array.child_type; ZigType *result_array_type = get_array_type(ira->codegen, child_type, new_array_len, array_type->data.array.sentinel); - IrInstruction *array_result; + IrInstGen *array_result; if (array_val->special == ConstValSpecialUndef || array_val->data.x_array.special == ConstArraySpecialUndef) { - array_result = ir_const_undef(ira, &instruction->base, result_array_type); + array_result = ir_const_undef(ira, &instruction->base.base, result_array_type); } else { - array_result = ir_const(ira, &instruction->base, result_array_type); + array_result = ir_const(ira, &instruction->base.base, result_array_type); ZigValue *out_val = array_result->value; switch (type_has_one_possible_value(ira->codegen, result_array_type)) { case OnePossibleValueInvalid: - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case OnePossibleValueYes: goto skip_computation; case OnePossibleValueNo: @@ -16471,35 +17503,35 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp * } skip_computation: if (want_ptr_to_array) { - return ir_get_ref(ira, &instruction->base, array_result, true, false); + return ir_get_ref(ira, &instruction->base.base, array_result, true, false); } else { return array_result; } } -static IrInstruction *ir_analyze_instruction_merge_err_sets(IrAnalyze *ira, - IrInstructionMergeErrSets *instruction) +static IrInstGen *ir_analyze_instruction_merge_err_sets(IrAnalyze *ira, + IrInstSrcMergeErrSets *instruction) { - ZigType *op1_type = ir_resolve_error_set_type(ira, &instruction->base, instruction->op1->child); + ZigType *op1_type = ir_resolve_error_set_type(ira, &instruction->base.base, instruction->op1->child); if (type_is_invalid(op1_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - ZigType *op2_type = ir_resolve_error_set_type(ira, &instruction->base, instruction->op2->child); + ZigType *op2_type = ir_resolve_error_set_type(ira, &instruction->base.base, instruction->op2->child); if (type_is_invalid(op2_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (type_is_global_error_set(op1_type) || type_is_global_error_set(op2_type)) { - return ir_const_type(ira, &instruction->base, ira->codegen->builtin_types.entry_global_error_set); + return ir_const_type(ira, &instruction->base.base, ira->codegen->builtin_types.entry_global_error_set); } - if (!resolve_inferred_error_set(ira->codegen, op1_type, instruction->op1->child->source_node)) { - return ira->codegen->invalid_instruction; + if (!resolve_inferred_error_set(ira->codegen, op1_type, instruction->op1->child->base.source_node)) { + return ira->codegen->invalid_inst_gen; } - if (!resolve_inferred_error_set(ira->codegen, op2_type, instruction->op2->child->source_node)) { - return ira->codegen->invalid_instruction; + if (!resolve_inferred_error_set(ira->codegen, op2_type, instruction->op2->child->base.source_node)) { + return ira->codegen->invalid_inst_gen; } size_t errors_count = ira->codegen->errors_by_index.length; @@ -16512,11 +17544,11 @@ static IrInstruction *ir_analyze_instruction_merge_err_sets(IrAnalyze *ira, ZigType *result_type = get_error_set_union(ira->codegen, errors, op1_type, op2_type, instruction->type_name); deallocate(errors, errors_count, "ErrorTableEntry *"); - return ir_const_type(ira, &instruction->base, result_type); + return ir_const_type(ira, &instruction->base.base, result_type); } -static IrInstruction *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { +static IrInstGen *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstSrcBinOp *bin_op_instruction) { IrBinOp op_id = bin_op_instruction->op_id; switch (op_id) { case IrBinOpInvalid: @@ -16561,41 +17593,39 @@ static IrInstruction *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructio zig_unreachable(); } -static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, - IrInstructionDeclVarSrc *decl_var_instruction) -{ +static IrInstGen *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstSrcDeclVar *decl_var_instruction) { Error err; ZigVar *var = decl_var_instruction->var; ZigType *explicit_type = nullptr; - IrInstruction *var_type = nullptr; + IrInstGen *var_type = nullptr; if (decl_var_instruction->var_type != nullptr) { var_type = decl_var_instruction->var_type->child; ZigType *proposed_type = ir_resolve_type(ira, var_type); - explicit_type = validate_var_type(ira->codegen, var_type->source_node, proposed_type); + explicit_type = validate_var_type(ira->codegen, var_type->base.source_node, proposed_type); if (type_is_invalid(explicit_type)) { var->var_type = ira->codegen->builtin_types.entry_invalid; - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } - AstNode *source_node = decl_var_instruction->base.source_node; + AstNode *source_node = decl_var_instruction->base.base.source_node; bool is_comptime_var = ir_get_var_is_comptime(var); bool var_class_requires_const = false; - IrInstruction *var_ptr = decl_var_instruction->ptr->child; + IrInstGen *var_ptr = decl_var_instruction->ptr->child; // if this is null, a compiler error happened and did not initialize the variable. // if there are no compile errors there may be a missing ir_expr_wrap in pass1 IR generation. if (var_ptr == nullptr || type_is_invalid(var_ptr->value->type)) { - ir_assert(var_ptr != nullptr || ira->codegen->errors.length != 0, &decl_var_instruction->base); + ir_assert(var_ptr != nullptr || ira->codegen->errors.length != 0, &decl_var_instruction->base.base); var->var_type = ira->codegen->builtin_types.entry_invalid; - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } // The ir_build_var_decl_src call is supposed to pass a pointer to the allocation, not an initialization value. - ir_assert(var_ptr->value->type->id == ZigTypeIdPointer, &decl_var_instruction->base); + ir_assert(var_ptr->value->type->id == ZigTypeIdPointer, &decl_var_instruction->base.base); ZigType *result_type = var_ptr->value->type->data.pointer.child_type; if (type_is_invalid(result_type)) { @@ -16606,7 +17636,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, ZigValue *init_val = nullptr; if (instr_is_comptime(var_ptr) && var_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar) { - init_val = const_ptr_pointee(ira, ira->codegen, var_ptr->value, decl_var_instruction->base.source_node); + init_val = const_ptr_pointee(ira, ira->codegen, var_ptr->value, decl_var_instruction->base.base.source_node); if (is_comptime_var) { if (var->gen_is_const) { var->const_value = init_val; @@ -16633,7 +17663,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, case ReqCompTimeNo: if (init_val != nullptr && value_is_comptime(init_val)) { if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, - decl_var_instruction->base.source_node, init_val, UndefOk))) + decl_var_instruction->base.base.source_node, init_val, UndefOk))) { result_type = ira->codegen->builtin_types.entry_invalid; } else if (init_val->type->id == ZigTypeIdFn && @@ -16666,13 +17696,13 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, assert(var->var_type); if (type_is_invalid(result_type)) { - return ir_const_void(ira, &decl_var_instruction->base); + return ir_const_void(ira, &decl_var_instruction->base.base); } if (decl_var_instruction->align_value == nullptr) { if ((err = type_resolve(ira->codegen, result_type, ResolveStatusAlignmentKnown))) { var->var_type = ira->codegen->builtin_types.entry_invalid; - return ir_const_void(ira, &decl_var_instruction->base); + return ir_const_void(ira, &decl_var_instruction->base.base); } var->align_bytes = get_abi_alignment(ira->codegen, result_type); } else { @@ -16691,98 +17721,96 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, // we need a runtime ptr but we have a comptime val. // since it's a comptime val there are no instructions for it. // we memcpy the init value here - IrInstruction *deref = ir_get_deref(ira, var_ptr, var_ptr, nullptr); + IrInstGen *deref = ir_get_deref(ira, &var_ptr->base, var_ptr, nullptr); if (type_is_invalid(deref->value->type)) { var->var_type = ira->codegen->builtin_types.entry_invalid; - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } // If this assertion trips, something is wrong with the IR instructions, because // we expected the above deref to return a constant value, but it created a runtime // instruction. assert(deref->value->special != ConstValSpecialRuntime); var_ptr->value->special = ConstValSpecialRuntime; - ir_analyze_store_ptr(ira, var_ptr, var_ptr, deref, false); + ir_analyze_store_ptr(ira, &var_ptr->base, var_ptr, deref, false); } - if (instr_is_comptime(var_ptr) && - (is_comptime_var || (var_class_requires_const && var->gen_is_const))) - { - return ir_const_void(ira, &decl_var_instruction->base); + if (instr_is_comptime(var_ptr) && (is_comptime_var || (var_class_requires_const && var->gen_is_const))) { + return ir_const_void(ira, &decl_var_instruction->base.base); } } else if (is_comptime_var) { - ir_add_error(ira, &decl_var_instruction->base, + ir_add_error(ira, &decl_var_instruction->base.base, buf_sprintf("cannot store runtime value in compile time variable")); var->var_type = ira->codegen->builtin_types.entry_invalid; - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); + ZigFn *fn_entry = ira->new_irb.exec->fn_entry; if (fn_entry) fn_entry->variable_list.append(var); - return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, var_ptr); + return ir_build_var_decl_gen(ira, &decl_var_instruction->base.base, var, var_ptr); } -static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) { - IrInstruction *target = instruction->target->child; +static IrInstGen *ir_analyze_instruction_export(IrAnalyze *ira, IrInstSrcExport *instruction) { + IrInstGen *target = instruction->target->child; if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *options = instruction->options->child; + IrInstGen *options = instruction->options->child; if (type_is_invalid(options->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *options_type = options->value->type; assert(options_type->id == ZigTypeIdStruct); TypeStructField *name_field = find_struct_type_field(options_type, buf_create_from_str("name")); - ir_assert(name_field != nullptr, &instruction->base); - IrInstruction *name_inst = ir_analyze_struct_value_field_value(ira, &instruction->base, options, name_field); + ir_assert(name_field != nullptr, &instruction->base.base); + IrInstGen *name_inst = ir_analyze_struct_value_field_value(ira, &instruction->base.base, options, name_field); if (type_is_invalid(name_inst->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; TypeStructField *linkage_field = find_struct_type_field(options_type, buf_create_from_str("linkage")); - ir_assert(linkage_field != nullptr, &instruction->base); - IrInstruction *linkage_inst = ir_analyze_struct_value_field_value(ira, &instruction->base, options, linkage_field); + ir_assert(linkage_field != nullptr, &instruction->base.base); + IrInstGen *linkage_inst = ir_analyze_struct_value_field_value(ira, &instruction->base.base, options, linkage_field); if (type_is_invalid(linkage_inst->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; TypeStructField *section_field = find_struct_type_field(options_type, buf_create_from_str("section")); - ir_assert(section_field != nullptr, &instruction->base); - IrInstruction *section_inst = ir_analyze_struct_value_field_value(ira, &instruction->base, options, section_field); + ir_assert(section_field != nullptr, &instruction->base.base); + IrInstGen *section_inst = ir_analyze_struct_value_field_value(ira, &instruction->base.base, options, section_field); if (type_is_invalid(section_inst->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; // The `section` field is optional, we have to unwrap it first - IrInstruction *non_null_check = ir_analyze_test_non_null(ira, &instruction->base, section_inst); + IrInstGen *non_null_check = ir_analyze_test_non_null(ira, &instruction->base.base, section_inst); bool is_non_null; if (!ir_resolve_bool(ira, non_null_check, &is_non_null)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *section_str_inst = nullptr; + IrInstGen *section_str_inst = nullptr; if (is_non_null) { - section_str_inst = ir_analyze_optional_value_payload_value(ira, &instruction->base, section_inst, false); + section_str_inst = ir_analyze_optional_value_payload_value(ira, &instruction->base.base, section_inst, false); if (type_is_invalid(section_str_inst->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } // Resolve all the comptime values Buf *symbol_name = ir_resolve_str(ira, name_inst); if (!symbol_name) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (buf_len(symbol_name) < 1) { - ir_add_error(ira, name_inst, + ir_add_error(ira, &name_inst->base, buf_sprintf("exported symbol name cannot be empty")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } GlobalLinkageId global_linkage_id; if (!ir_resolve_global_linkage(ira, linkage_inst, &global_linkage_id)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; Buf *section_name = nullptr; if (section_str_inst != nullptr && !(section_name = ir_resolve_str(ira, section_str_inst))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; // TODO: This function needs to be audited. // It's not clear how all the different types are supposed to be handled. @@ -16790,15 +17818,15 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio // in another file. TldFn *tld_fn = allocate(1); tld_fn->base.id = TldIdFn; - tld_fn->base.source_node = instruction->base.source_node; + tld_fn->base.source_node = instruction->base.base.source_node; auto entry = ira->codegen->exported_symbol_names.put_unique(symbol_name, &tld_fn->base); if (entry) { AstNode *other_export_node = entry->value->source_node; - ErrorMsg *msg = ir_add_error(ira, &instruction->base, + ErrorMsg *msg = ir_add_error(ira, &instruction->base.base, buf_sprintf("exported symbol collision: '%s'", buf_ptr(symbol_name))); add_error_note(ira->codegen, msg, other_export_node, buf_sprintf("other symbol is here")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } Error err; @@ -16814,12 +17842,12 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio CallingConvention cc = fn_entry->type_entry->data.fn.fn_type_id.cc; switch (cc) { case CallingConventionUnspecified: { - ErrorMsg *msg = ir_add_error(ira, target, + ErrorMsg *msg = ir_add_error(ira, &target->base, buf_sprintf("exported function must specify calling convention")); add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("declared here")); } break; case CallingConventionAsync: { - ErrorMsg *msg = ir_add_error(ira, target, + ErrorMsg *msg = ir_add_error(ira, &target->base, buf_sprintf("exported function cannot be async")); add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("declared here")); } break; @@ -16842,10 +17870,10 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio } break; case ZigTypeIdStruct: if (is_slice(target->value->type)) { - ir_add_error(ira, target, + ir_add_error(ira, &target->base, buf_sprintf("unable to export value of type '%s'", buf_ptr(&target->value->type->name))); } else if (target->value->type->data.structure.layout != ContainerLayoutExtern) { - ErrorMsg *msg = ir_add_error(ira, target, + ErrorMsg *msg = ir_add_error(ira, &target->base, buf_sprintf("exported struct value must be declared extern")); add_error_note(ira->codegen, msg, target->value->type->data.structure.decl_node, buf_sprintf("declared here")); } else { @@ -16854,7 +17882,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio break; case ZigTypeIdUnion: if (target->value->type->data.unionation.layout != ContainerLayoutExtern) { - ErrorMsg *msg = ir_add_error(ira, target, + ErrorMsg *msg = ir_add_error(ira, &target->base, buf_sprintf("exported union value must be declared extern")); add_error_note(ira->codegen, msg, target->value->type->data.unionation.decl_node, buf_sprintf("declared here")); } else { @@ -16863,7 +17891,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio break; case ZigTypeIdEnum: if (target->value->type->data.enumeration.layout != ContainerLayoutExtern) { - ErrorMsg *msg = ir_add_error(ira, target, + ErrorMsg *msg = ir_add_error(ira, &target->base, buf_sprintf("exported enum value must be declared extern")); add_error_note(ira->codegen, msg, target->value->type->data.enumeration.decl_node, buf_sprintf("declared here")); } else { @@ -16873,10 +17901,10 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio case ZigTypeIdArray: { bool ok_type; if ((err = type_allowed_in_extern(ira->codegen, target->value->type->data.array.child_type, &ok_type))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (!ok_type) { - ir_add_error(ira, target, + ir_add_error(ira, &target->base, buf_sprintf("array element type '%s' not extern-compatible", buf_ptr(&target->value->type->data.array.child_type->name))); } else { @@ -16891,31 +17919,31 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio zig_unreachable(); case ZigTypeIdStruct: if (is_slice(type_value)) { - ir_add_error(ira, target, + ir_add_error(ira, &target->base, buf_sprintf("unable to export type '%s'", buf_ptr(&type_value->name))); } else if (type_value->data.structure.layout != ContainerLayoutExtern) { - ErrorMsg *msg = ir_add_error(ira, target, + ErrorMsg *msg = ir_add_error(ira, &target->base, buf_sprintf("exported struct must be declared extern")); add_error_note(ira->codegen, msg, type_value->data.structure.decl_node, buf_sprintf("declared here")); } break; case ZigTypeIdUnion: if (type_value->data.unionation.layout != ContainerLayoutExtern) { - ErrorMsg *msg = ir_add_error(ira, target, + ErrorMsg *msg = ir_add_error(ira, &target->base, buf_sprintf("exported union must be declared extern")); add_error_note(ira->codegen, msg, type_value->data.unionation.decl_node, buf_sprintf("declared here")); } break; case ZigTypeIdEnum: if (type_value->data.enumeration.layout != ContainerLayoutExtern) { - ErrorMsg *msg = ir_add_error(ira, target, + ErrorMsg *msg = ir_add_error(ira, &target->base, buf_sprintf("exported enum must be declared extern")); add_error_note(ira->codegen, msg, type_value->data.enumeration.decl_node, buf_sprintf("declared here")); } break; case ZigTypeIdFn: { if (type_value->data.fn.fn_type_id.cc == CallingConventionUnspecified) { - ir_add_error(ira, target, + ir_add_error(ira, &target->base, buf_sprintf("exported function type must specify calling convention")); } } break; @@ -16941,7 +17969,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio case ZigTypeIdOpaque: case ZigTypeIdFnFrame: case ZigTypeIdAnyFrame: - ir_add_error(ira, target, + ir_add_error(ira, &target->base, buf_sprintf("invalid export target '%s'", buf_ptr(&type_value->name))); break; } @@ -16966,61 +17994,55 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio case ZigTypeIdEnumLiteral: case ZigTypeIdFnFrame: case ZigTypeIdAnyFrame: - ir_add_error(ira, target, + ir_add_error(ira, &target->base, buf_sprintf("invalid export target type '%s'", buf_ptr(&target->value->type->name))); break; } // TODO audit the various ways to use @export - if (want_var_export && target->id == IrInstructionIdLoadPtrGen) { - IrInstructionLoadPtrGen *load_ptr = reinterpret_cast(target); - if (load_ptr->ptr->id == IrInstructionIdVarPtr) { - IrInstructionVarPtr *var_ptr = reinterpret_cast(load_ptr->ptr); + if (want_var_export && target->id == IrInstGenIdLoadPtr) { + IrInstGenLoadPtr *load_ptr = reinterpret_cast(target); + if (load_ptr->ptr->id == IrInstGenIdVarPtr) { + IrInstGenVarPtr *var_ptr = reinterpret_cast(load_ptr->ptr); ZigVar *var = var_ptr->var; add_var_export(ira->codegen, var, buf_ptr(symbol_name), global_linkage_id); var->section_name = section_name; } } - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } -static bool exec_has_err_ret_trace(CodeGen *g, IrExecutable *exec) { +static bool exec_has_err_ret_trace(CodeGen *g, IrExecutableSrc *exec) { ZigFn *fn_entry = exec_fn_entry(exec); return fn_entry != nullptr && fn_entry->calls_or_awaits_errorable_fn && g->have_err_ret_tracing; } -static IrInstruction *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, - IrInstructionErrorReturnTrace *instruction) +static IrInstGen *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, + IrInstSrcErrorReturnTrace *instruction) { ZigType *ptr_to_stack_trace_type = get_pointer_to_type(ira->codegen, get_stack_trace_type(ira->codegen), false); - if (instruction->optional == IrInstructionErrorReturnTrace::Null) { + if (instruction->optional == IrInstErrorReturnTraceNull) { ZigType *optional_type = get_optional_type(ira->codegen, ptr_to_stack_trace_type); - if (!exec_has_err_ret_trace(ira->codegen, ira->new_irb.exec)) { - IrInstruction *result = ir_const(ira, &instruction->base, optional_type); + if (!exec_has_err_ret_trace(ira->codegen, ira->old_irb.exec)) { + IrInstGen *result = ir_const(ira, &instruction->base.base, optional_type); ZigValue *out_val = result->value; assert(get_codegen_ptr_type(optional_type) != nullptr); out_val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr; out_val->data.x_ptr.data.hard_coded_addr.addr = 0; return result; } - IrInstruction *new_instruction = ir_build_error_return_trace(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, instruction->optional); - new_instruction->value->type = optional_type; - return new_instruction; + return ir_build_error_return_trace_gen(ira, instruction->base.base.scope, + instruction->base.base.source_node, instruction->optional, optional_type); } else { assert(ira->codegen->have_err_ret_tracing); - IrInstruction *new_instruction = ir_build_error_return_trace(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, instruction->optional); - new_instruction->value->type = ptr_to_stack_trace_type; - return new_instruction; + return ir_build_error_return_trace_gen(ira, instruction->base.base.scope, + instruction->base.base.source_node, instruction->optional, ptr_to_stack_trace_type); } } -static IrInstruction *ir_analyze_instruction_error_union(IrAnalyze *ira, - IrInstructionErrorUnion *instruction) -{ - IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type); +static IrInstGen *ir_analyze_instruction_error_union(IrAnalyze *ira, IrInstSrcErrorUnion *instruction) { + IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_type); result->value->special = ConstValSpecialLazy; LazyValueErrUnionType *lazy_err_union_type = allocate(1, "LazyValueErrUnionType"); @@ -17030,16 +18052,16 @@ static IrInstruction *ir_analyze_instruction_error_union(IrAnalyze *ira, lazy_err_union_type->err_set_type = instruction->err_set->child; if (ir_resolve_type_lazy(ira, lazy_err_union_type->err_set_type) == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; lazy_err_union_type->payload_type = instruction->payload->child; if (ir_resolve_type_lazy(ira, lazy_err_union_type->payload_type) == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return result; } -static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_inst, ZigType *var_type, +static IrInstGen *ir_analyze_alloca(IrAnalyze *ira, IrInst *source_inst, ZigType *var_type, uint32_t align, const char *name_hint, bool force_comptime) { Error err; @@ -17048,7 +18070,7 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in pointee->special = ConstValSpecialUndef; pointee->llvm_align = align; - IrInstructionAllocaGen *result = ir_build_alloca_gen(ira, source_inst, align, name_hint); + IrInstGenAlloca *result = ir_build_alloca_gen(ira, source_inst, align, name_hint); result->base.value->special = ConstValSpecialStatic; result->base.value->data.x_ptr.special = ConstPtrSpecialRef; result->base.value->data.x_ptr.mut = force_comptime ? ConstPtrMutComptimeVar : ConstPtrMutInfer; @@ -17056,15 +18078,15 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in bool var_type_has_bits; if ((err = type_has_bits2(ira->codegen, var_type, &var_type_has_bits))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (align != 0) { if ((err = type_resolve(ira->codegen, var_type, ResolveStatusAlignmentKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (!var_type_has_bits) { ir_add_error(ira, source_inst, buf_sprintf("variable '%s' of zero-bit type '%s' has no in-memory representation, it cannot be aligned", name_hint, buf_ptr(&var_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } assert(result->base.value->data.x_ptr.special != ConstPtrSpecialInvalid); @@ -17074,16 +18096,15 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in PtrLenSingle, align, 0, 0, false); if (!force_comptime) { - ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); + ZigFn *fn_entry = ira->new_irb.exec->fn_entry; if (fn_entry != nullptr) { fn_entry->alloca_gen_list.append(result); } } - result->base.is_gen = true; return &result->base; } -static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, IrInstruction *suspend_source_instr, +static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, IrInst *suspend_source_instr, ResultLoc *result_loc) { switch (result_loc->id) { @@ -17126,7 +18147,7 @@ static bool type_can_bit_cast(ZigType *t) { } } -static void set_up_result_loc_for_inferred_comptime(IrInstruction *ptr) { +static void set_up_result_loc_for_inferred_comptime(IrInstGen *ptr) { ZigValue *undef_child = create_const_vals(1); undef_child->type = ptr->value->type->data.pointer.child_type; undef_child->special = ConstValSpecialUndef; @@ -17165,16 +18186,16 @@ static Error ir_result_has_type(IrAnalyze *ira, ResultLoc *result_loc, bool *out zig_unreachable(); } -static IrInstruction *ir_resolve_no_result_loc(IrAnalyze *ira, IrInstruction *suspend_source_instr, +static IrInstGen *ir_resolve_no_result_loc(IrAnalyze *ira, IrInst *suspend_source_instr, ResultLoc *result_loc, ZigType *value_type) { if (type_is_invalid(value_type)) - return ira->codegen->invalid_instruction; - IrInstructionAllocaGen *alloca_gen = ir_build_alloca_gen(ira, suspend_source_instr, 0, ""); + return ira->codegen->invalid_inst_gen; + IrInstGenAlloca *alloca_gen = ir_build_alloca_gen(ira, suspend_source_instr, 0, ""); alloca_gen->base.value->type = get_pointer_to_type_extra(ira->codegen, value_type, false, false, PtrLenSingle, 0, 0, 0, false); set_up_result_loc_for_inferred_comptime(&alloca_gen->base); - ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); + ZigFn *fn_entry = ira->new_irb.exec->fn_entry; if (fn_entry != nullptr && get_scope_typeof(suspend_source_instr->scope) == nullptr) { fn_entry->alloca_gen_list.append(alloca_gen); } @@ -17184,8 +18205,8 @@ static IrInstruction *ir_resolve_no_result_loc(IrAnalyze *ira, IrInstruction *su } // when calling this function, at the callsite must check for result type noreturn and propagate it up -static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr, - ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, +static IrInstGen *ir_resolve_result_raw(IrAnalyze *ira, IrInst *suspend_source_instr, + ResultLoc *result_loc, ZigType *value_type, IrInstGen *value, bool force_runtime, bool allow_discard) { Error err; @@ -17210,10 +18231,8 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe } case ResultLocIdVar: { ResultLocVar *result_loc_var = reinterpret_cast(result_loc); - assert(result_loc->source_instruction->id == IrInstructionIdAllocaSrc); - - IrInstructionAllocaSrc *alloca_src = - reinterpret_cast(result_loc->source_instruction); + assert(result_loc->source_instruction->id == IrInstSrcIdAlloca); + IrInstSrcAlloca *alloca_src = reinterpret_cast(result_loc->source_instruction); ZigVar *var = result_loc_var->var; if (var->var_type != nullptr && !ir_get_var_is_comptime(var)) { @@ -17231,26 +18250,26 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe var = new_var; } if (value_type->id == ZigTypeIdUnreachable || value_type->id == ZigTypeIdOpaque) { - ir_add_error(ira, result_loc->source_instruction, + ir_add_error(ira, &result_loc->source_instruction->base, buf_sprintf("variable of type '%s' not allowed", buf_ptr(&value_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (alloca_src->base.child == nullptr || var->ptr_instruction == nullptr) { bool force_comptime; if (!ir_resolve_comptime(ira, alloca_src->is_comptime->child, &force_comptime)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; uint32_t align = 0; if (alloca_src->align != nullptr && !ir_resolve_align(ira, alloca_src->align->child, nullptr, &align)) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *alloca_gen = ir_analyze_alloca(ira, result_loc->source_instruction, - value_type, align, alloca_src->name_hint, force_comptime); + IrInstGen *alloca_gen = ir_analyze_alloca(ira, &result_loc->source_instruction->base, value_type, + align, alloca_src->name_hint, force_comptime); if (force_runtime) { alloca_gen->value->data.x_ptr.mut = ConstPtrMutRuntimeVar; alloca_gen->value->special = ConstValSpecialRuntime; } if (alloca_src->base.child != nullptr && !result_loc->written) { - alloca_src->base.child->ref_count = 0; + alloca_src->base.child->base.ref_count = 0; } alloca_src->base.child = alloca_gen; var->ptr_instruction = alloca_gen; @@ -17278,7 +18297,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe ResultLocPeerParent *peer_parent = result_peer->parent; if (peer_parent->peers.length == 1) { - IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, + IrInstGen *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, value_type, value, force_runtime, true); result_peer->suspend_pos.basic_block_index = SIZE_MAX; result_peer->suspend_pos.instruction_index = SIZE_MAX; @@ -17294,7 +18313,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe bool is_condition_comptime; if (!ir_resolve_comptime(ira, peer_parent->is_comptime->child, &is_condition_comptime)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (is_condition_comptime) { peer_parent->skipped = true; return ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, @@ -17302,10 +18321,10 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe } bool peer_parent_has_type; if ((err = ir_result_has_type(ira, peer_parent->parent, &peer_parent_has_type))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (peer_parent_has_type) { peer_parent->skipped = true; - IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, + IrInstGen *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, value_type, value, force_runtime || !is_condition_comptime, true); if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value->type) || parent_result_loc->value->type->id == ZigTypeIdUnreachable) @@ -17322,7 +18341,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe if (peer_parent->end_bb->suspend_instruction_ref == nullptr) { peer_parent->end_bb->suspend_instruction_ref = suspend_source_instr; } - IrInstruction *unreach_inst = ira_suspend(ira, suspend_source_instr, result_peer->next_bb, + IrInstGen *unreach_inst = ira_suspend(ira, suspend_source_instr, result_peer->next_bb, &result_peer->suspend_pos); if (result_peer->next_bb == nullptr) { ir_start_next_bb(ira); @@ -17330,7 +18349,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe return unreach_inst; } - IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, + IrInstGen *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, peer_parent->resolved_type, nullptr, force_runtime, true); if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value->type) || parent_result_loc->value->type->id == ZigTypeIdUnreachable) @@ -17347,23 +18366,23 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe ResultLocCast *result_cast = reinterpret_cast(result_loc); ZigType *dest_type = ir_resolve_type(ira, result_cast->base.source_instruction->child); if (type_is_invalid(dest_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (dest_type == ira->codegen->builtin_types.entry_var) { return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type); } - IrInstruction *casted_value; + IrInstGen *casted_value; if (value != nullptr) { casted_value = ir_implicit_cast(ira, value, dest_type); if (type_is_invalid(casted_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; dest_type = casted_value->value->type; } else { casted_value = nullptr; } - IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_cast->parent, + IrInstGen *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_cast->parent, dest_type, casted_value, force_runtime, true); if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value->type) || parent_result_loc->value->type->id == ZigTypeIdUnreachable) @@ -17377,11 +18396,11 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe if ((err = type_resolve(ira->codegen, parent_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } uint64_t parent_ptr_align = get_ptr_align(ira->codegen, parent_ptr_type); if ((err = type_resolve(ira->codegen, value_type, ResolveStatusAlignmentKnown))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (!type_has_bits(value_type)) { parent_ptr_align = 0; @@ -17404,9 +18423,9 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe ConstCastOnly const_cast_result = types_match_const_cast_only(ira, parent_result_loc->value->type, ptr_type, - result_cast->base.source_instruction->source_node, false); + result_cast->base.source_instruction->base.source_node, false); if (const_cast_result.id == ConstCastResultIdInvalid) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (const_cast_result.id != ConstCastResultIdOk) { if (allow_discard) { return parent_result_loc; @@ -17419,42 +18438,42 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe result_loc->written = true; result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr, parent_result_loc, - ptr_type, result_cast->base.source_instruction, false); + ptr_type, &result_cast->base.source_instruction->base, false); return result_loc->resolved_loc; } case ResultLocIdBitCast: { ResultLocBitCast *result_bit_cast = reinterpret_cast(result_loc); ZigType *dest_type = ir_resolve_type(ira, result_bit_cast->base.source_instruction->child); if (type_is_invalid(dest_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (get_codegen_ptr_type(dest_type) != nullptr) { - ir_add_error(ira, result_loc->source_instruction, + ir_add_error(ira, &result_loc->source_instruction->base, buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (!type_can_bit_cast(dest_type)) { - ir_add_error(ira, result_loc->source_instruction, + ir_add_error(ira, &result_loc->source_instruction->base, buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (get_codegen_ptr_type(value_type) != nullptr) { ir_add_error(ira, suspend_source_instr, buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&value_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (!type_can_bit_cast(value_type)) { ir_add_error(ira, suspend_source_instr, buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&value_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *bitcasted_value; + IrInstGen *bitcasted_value; if (value != nullptr) { - bitcasted_value = ir_analyze_bit_cast(ira, result_loc->source_instruction, value, dest_type); + bitcasted_value = ir_analyze_bit_cast(ira, &result_loc->source_instruction->base, value, dest_type); dest_type = bitcasted_value->value->type; } else { bitcasted_value = nullptr; @@ -17464,7 +18483,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe return bitcasted_value; } - IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_bit_cast->parent, + IrInstGen *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_bit_cast->parent, dest_type, bitcasted_value, force_runtime, true); if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value->type) || parent_result_loc->value->type->id == ZigTypeIdUnreachable) @@ -17477,7 +18496,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe bool has_bits; if ((err = type_has_bits2(ira->codegen, child_type, &has_bits))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } // This happens when the bitCast result is assigned to _ @@ -17487,12 +18506,12 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe } if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } uint64_t parent_ptr_align = get_ptr_align(ira->codegen, parent_ptr_type); if ((err = type_resolve(ira->codegen, value_type, ResolveStatusAlignmentKnown))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value_type, parent_ptr_type->data.pointer.is_const, parent_ptr_type->data.pointer.is_volatile, PtrLenSingle, @@ -17500,30 +18519,37 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe result_loc->written = true; result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr, parent_result_loc, - ptr_type, result_bit_cast->base.source_instruction, false); + ptr_type, &result_bit_cast->base.source_instruction->base, false); return result_loc->resolved_loc; } } zig_unreachable(); } -static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr, - ResultLoc *result_loc_pass1, ZigType *value_type, IrInstruction *value, bool force_runtime, +static IrInstGen *ir_resolve_result(IrAnalyze *ira, IrInst *suspend_source_instr, + ResultLoc *result_loc_pass1, ZigType *value_type, IrInstGen *value, bool force_runtime, bool allow_discard) { Error err; if (!allow_discard && result_loc_pass1->id == ResultLocIdInstruction && - instr_is_comptime(result_loc_pass1->source_instruction) && - result_loc_pass1->source_instruction->value->type->id == ZigTypeIdPointer && - result_loc_pass1->source_instruction->value->data.x_ptr.special == ConstPtrSpecialDiscard) + result_loc_pass1->source_instruction->id == IrInstSrcIdConst) { - result_loc_pass1 = no_result_loc(); + IrInstSrcConst *const_inst = reinterpret_cast(result_loc_pass1->source_instruction); + if (value_is_comptime(const_inst->value) && + const_inst->value->type->id == ZigTypeIdPointer && + const_inst->value->data.x_ptr.special == ConstPtrSpecialDiscard) + { + result_loc_pass1 = no_result_loc(); + } } bool was_written = result_loc_pass1->written; - IrInstruction *result_loc = ir_resolve_result_raw(ira, suspend_source_instr, result_loc_pass1, value_type, + IrInstGen *result_loc = ir_resolve_result_raw(ira, suspend_source_instr, result_loc_pass1, value_type, value, force_runtime, allow_discard); - if (result_loc == nullptr || (instr_is_unreachable(result_loc) || type_is_invalid(result_loc->value->type))) + if (result_loc == nullptr || result_loc->value->type->id == ZigTypeIdUnreachable || + type_is_invalid(result_loc->value->type)) + { return result_loc; + } if ((force_runtime || (value != nullptr && !instr_is_comptime(value))) && result_loc_pass1->written && result_loc->value->data.x_ptr.mut == ConstPtrMutInfer) @@ -17534,7 +18560,7 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s InferredStructField *isf = result_loc->value->type->data.pointer.inferred_struct_field; if (isf != nullptr) { TypeStructField *field; - IrInstruction *casted_ptr; + IrInstGen *casted_ptr; if (isf->already_resolved) { field = find_struct_type_field(isf->inferred_struct_type, isf->field_name); casted_ptr = result_loc; @@ -17552,11 +18578,11 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s field->type_entry = value_type; field->type_val = create_const_type(ira->codegen, field->type_entry); field->src_index = old_field_count; - field->decl_node = value ? value->source_node : suspend_source_instr->source_node; + field->decl_node = value ? value->base.source_node : suspend_source_instr->source_node; if (value && instr_is_comptime(value)) { ZigValue *val = ir_resolve_const(ira, value, UndefOk); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; field->is_comptime = true; field->init_val = create_const_vals(1); copy_const_val(field->init_val, val); @@ -17574,7 +18600,7 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s if (instr_is_comptime(casted_ptr)) { ZigValue *ptr_val = ir_resolve_const(ira, casted_ptr, UndefBad); if (!ptr_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { ZigValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, suspend_source_instr->source_node); @@ -17610,7 +18636,7 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s if (!same_comptime_repr) { bool has_bits; if ((err = type_has_bits2(ira->codegen, value_type, &has_bits))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (has_bits) { result_loc_pass1->written = false; return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true); @@ -17619,12 +18645,12 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s } else if (actual_elem_type->id == ZigTypeIdErrorUnion && value_type->id != ZigTypeIdErrorUnion) { bool has_bits; if ((err = type_has_bits2(ira->codegen, value_type, &has_bits))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (has_bits) { if (value_type->id == ZigTypeIdErrorSet) { return ir_analyze_unwrap_err_code(ira, suspend_source_instr, result_loc, true); } else { - IrInstruction *unwrapped_err_ptr = ir_analyze_unwrap_error_payload(ira, suspend_source_instr, + IrInstGen *unwrapped_err_ptr = ir_analyze_unwrap_error_payload(ira, suspend_source_instr, result_loc, false, true); ZigType *actual_payload_type = actual_elem_type->data.error_union.payload_type; if (actual_payload_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional && @@ -17640,37 +18666,35 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s return result_loc; } -static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, - IrInstructionResolveResult *instruction) -{ +static IrInstGen *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrInstSrcResolveResult *instruction) { ZigType *implicit_elem_type; if (instruction->ty == nullptr) { if (instruction->result_loc->id == ResultLocIdCast) { implicit_elem_type = ir_resolve_type(ira, instruction->result_loc->source_instruction->child); if (type_is_invalid(implicit_elem_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else if (instruction->result_loc->id == ResultLocIdReturn) { implicit_elem_type = ira->explicit_return_type; if (type_is_invalid(implicit_elem_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else { implicit_elem_type = ira->codegen->builtin_types.entry_var; } if (implicit_elem_type == ira->codegen->builtin_types.entry_var) { Buf *bare_name = buf_alloc(); Buf *name = get_anon_type_name(ira->codegen, nullptr, container_string(ContainerKindStruct), - instruction->base.scope, instruction->base.source_node, bare_name); + instruction->base.base.scope, instruction->base.base.source_node, bare_name); StructSpecial struct_special = StructSpecialInferredStruct; - if (instruction->base.source_node->type == NodeTypeContainerInitExpr && - instruction->base.source_node->data.container_init_expr.kind == ContainerInitKindArray) + if (instruction->base.base.source_node->type == NodeTypeContainerInitExpr && + instruction->base.base.source_node->data.container_init_expr.kind == ContainerInitKindArray) { struct_special = StructSpecialInferredTuple; } ZigType *inferred_struct_type = get_partial_container_type(ira->codegen, - instruction->base.scope, ContainerKindStruct, instruction->base.source_node, + instruction->base.base.scope, ContainerKindStruct, instruction->base.base.source_node, buf_ptr(name), bare_name, ContainerLayoutAuto); inferred_struct_type->data.structure.special = struct_special; inferred_struct_type->data.structure.resolve_status = ResolveStatusBeingInferred; @@ -17679,21 +18703,21 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, } else { implicit_elem_type = ir_resolve_type(ira, instruction->ty->child); if (type_is_invalid(implicit_elem_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, + IrInstGen *result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc, implicit_elem_type, nullptr, false, true); if (result_loc != nullptr) return result_loc; - ZigFn *fn = exec_fn_entry(ira->new_irb.exec); + ZigFn *fn = ira->new_irb.exec->fn_entry; if (fn != nullptr && fn->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync && instruction->result_loc->id == ResultLocIdReturn) { - result_loc = ir_resolve_result(ira, &instruction->base, no_result_loc(), + result_loc = ir_resolve_result(ira, &instruction->base.base, no_result_loc(), implicit_elem_type, nullptr, false, true); if (result_loc != nullptr && - (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc))) + (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable)) { return result_loc; } @@ -17701,9 +18725,9 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, return result_loc; } - IrInstruction *result = ir_const(ira, &instruction->base, implicit_elem_type); + IrInstGen *result = ir_const(ira, &instruction->base.base, implicit_elem_type); result->value->special = ConstValSpecialUndef; - IrInstruction *ptr = ir_get_ref(ira, &instruction->base, result, false, false); + IrInstGen *ptr = ir_get_ref(ira, &instruction->base.base, result, false, false); ptr->value->data.x_ptr.mut = ConstPtrMutComptimeVar; return ptr; } @@ -17727,8 +18751,7 @@ static void ir_reset_result(ResultLoc *result_loc) { break; } case ResultLocIdVar: { - IrInstructionAllocaSrc *alloca_src = - reinterpret_cast(result_loc->source_instruction); + IrInstSrcAlloca *alloca_src = reinterpret_cast(result_loc->source_instruction); alloca_src->base.child = nullptr; break; } @@ -17744,18 +18767,18 @@ static void ir_reset_result(ResultLoc *result_loc) { } } -static IrInstruction *ir_analyze_instruction_reset_result(IrAnalyze *ira, IrInstructionResetResult *instruction) { +static IrInstGen *ir_analyze_instruction_reset_result(IrAnalyze *ira, IrInstSrcResetResult *instruction) { ir_reset_result(instruction->result_loc); - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } -static IrInstruction *get_async_call_result_loc(IrAnalyze *ira, IrInstruction *source_instr, - ZigType *fn_ret_type, bool is_async_call_builtin, IrInstruction **args_ptr, size_t args_len, - IrInstruction *ret_ptr_uncasted) +static IrInstGen *get_async_call_result_loc(IrAnalyze *ira, IrInst* source_instr, + ZigType *fn_ret_type, bool is_async_call_builtin, IrInstGen **args_ptr, size_t args_len, + IrInstGen *ret_ptr_uncasted) { ir_assert(is_async_call_builtin, source_instr); if (type_is_invalid(ret_ptr_uncasted->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (ret_ptr_uncasted->value->type->id == ZigTypeIdVoid) { // Result location will be inside the async frame. return nullptr; @@ -17763,57 +18786,57 @@ static IrInstruction *get_async_call_result_loc(IrAnalyze *ira, IrInstruction *s return ir_implicit_cast(ira, ret_ptr_uncasted, get_pointer_to_type(ira->codegen, fn_ret_type, false)); } -static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstruction *source_instr, ZigFn *fn_entry, - ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count, - IrInstruction *casted_new_stack, bool is_async_call_builtin, IrInstruction *ret_ptr_uncasted, +static IrInstGen *ir_analyze_async_call(IrAnalyze *ira, IrInst* source_instr, ZigFn *fn_entry, + ZigType *fn_type, IrInstGen *fn_ref, IrInstGen **casted_args, size_t arg_count, + IrInstGen *casted_new_stack, bool is_async_call_builtin, IrInstGen *ret_ptr_uncasted, ResultLoc *call_result_loc) { if (fn_entry == nullptr) { if (fn_type->data.fn.fn_type_id.cc != CallingConventionAsync) { - ir_add_error(ira, fn_ref, + ir_add_error(ira, &fn_ref->base, buf_sprintf("expected async function, found '%s'", buf_ptr(&fn_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (casted_new_stack == nullptr) { - ir_add_error(ira, fn_ref, buf_sprintf("function is not comptime-known; @asyncCall required")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &fn_ref->base, buf_sprintf("function is not comptime-known; @asyncCall required")); + return ira->codegen->invalid_inst_gen; } } if (casted_new_stack != nullptr) { ZigType *fn_ret_type = fn_type->data.fn.fn_type_id.return_type; - IrInstruction *ret_ptr = get_async_call_result_loc(ira, source_instr, fn_ret_type, is_async_call_builtin, + IrInstGen *ret_ptr = get_async_call_result_loc(ira, source_instr, fn_ret_type, is_async_call_builtin, casted_args, arg_count, ret_ptr_uncasted); if (ret_ptr != nullptr && type_is_invalid(ret_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *anyframe_type = get_any_frame_type(ira->codegen, fn_ret_type); - IrInstructionCallGen *call_gen = ir_build_call_gen(ira, source_instr, fn_entry, fn_ref, + IrInstGenCall *call_gen = ir_build_call_gen(ira, source_instr, fn_entry, fn_ref, arg_count, casted_args, CallModifierAsync, casted_new_stack, is_async_call_builtin, ret_ptr, anyframe_type); return &call_gen->base; } else { ZigType *frame_type = get_fn_frame_type(ira->codegen, fn_entry); - IrInstruction *result_loc = ir_resolve_result(ira, source_instr, call_result_loc, + IrInstGen *result_loc = ir_resolve_result(ira, source_instr, call_result_loc, frame_type, nullptr, true, false); - if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) { + if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) { return result_loc; } result_loc = ir_implicit_cast(ira, result_loc, get_pointer_to_type(ira->codegen, frame_type, false)); if (type_is_invalid(result_loc->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return &ir_build_call_gen(ira, source_instr, fn_entry, fn_ref, arg_count, casted_args, CallModifierAsync, casted_new_stack, is_async_call_builtin, result_loc, frame_type)->base; } } static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node, - IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i) + IrInstGen *arg, Scope **exec_scope, size_t *next_proto_i) { AstNode *param_decl_node = fn_proto_node->data.fn_proto.params.at(*next_proto_i); assert(param_decl_node->type == NodeTypeParamDecl); - IrInstruction *casted_arg; + IrInstGen *casted_arg; if (param_decl_node->data.param_decl.var_token == nullptr) { AstNode *param_type_node = param_decl_node->data.param_decl.type; ZigType *param_type = ir_analyze_type_expr(ira, *exec_scope, param_type_node); @@ -17841,15 +18864,15 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node } static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_node, - IrInstruction *arg, Scope **child_scope, size_t *next_proto_i, - GenericFnTypeId *generic_id, FnTypeId *fn_type_id, IrInstruction **casted_args, + IrInstGen *arg, Scope **child_scope, size_t *next_proto_i, + GenericFnTypeId *generic_id, FnTypeId *fn_type_id, IrInstGen **casted_args, ZigFn *impl_fn) { AstNode *param_decl_node = fn_proto_node->data.fn_proto.params.at(*next_proto_i); assert(param_decl_node->type == NodeTypeParamDecl); bool is_var_args = param_decl_node->data.param_decl.is_var_args; bool arg_part_of_generic_id = false; - IrInstruction *casted_arg; + IrInstGen *casted_arg; if (is_var_args) { arg_part_of_generic_id = true; casted_arg = arg; @@ -17909,7 +18932,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod } else if (casted_arg->value->type->id == ZigTypeIdComptimeInt || casted_arg->value->type->id == ZigTypeIdComptimeFloat) { - ir_add_error(ira, casted_arg, + ir_add_error(ira, &casted_arg->base, buf_sprintf("compiler bug: integer and float literals in var args function must be casted. https://github.com/ziglang/zig/issues/557")); return false; } @@ -17926,13 +18949,13 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod return true; } -static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var) { +static IrInstGen *ir_get_var_ptr(IrAnalyze *ira, IrInst *source_instr, ZigVar *var) { while (var->next_var != nullptr) { var = var->next_var; } if (var->var_type == nullptr || type_is_invalid(var->var_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; bool is_volatile = false; ZigType *var_ptr_type = get_pointer_to_type_extra(ira->codegen, var->var_type, @@ -17945,8 +18968,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, bool comptime_var_mem = ir_get_var_is_comptime(var); bool linkage_makes_it_runtime = var->decl_node->data.variable_declaration.is_extern; - IrInstruction *result = ir_build_var_ptr(&ira->new_irb, - instruction->scope, instruction->source_node, var); + IrInstGen *result = ir_build_var_ptr_gen(ira, source_instr, var); result->value->type = var_ptr_type; if (!linkage_makes_it_runtime && !var->is_thread_local && value_is_comptime(var->const_value)) { @@ -17982,7 +19004,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, } // This function is called when a comptime value becomes accessible at runtime. -static void mark_comptime_value_escape(IrAnalyze *ira, IrInstruction *source_instr, ZigValue *val) { +static void mark_comptime_value_escape(IrAnalyze *ira, IrInst* source_instr, ZigValue *val) { ir_assert(value_is_comptime(val), source_instr); if (val->special == ConstValSpecialUndef) return; @@ -17995,8 +19017,8 @@ static void mark_comptime_value_escape(IrAnalyze *ira, IrInstruction *source_ins } } -static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *ptr, IrInstruction *uncasted_value, bool allow_write_through_const) +static IrInstGen *ir_analyze_store_ptr(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *ptr, IrInstGen *uncasted_value, bool allow_write_through_const) { assert(ptr->value->type->id == ZigTypeIdPointer); @@ -18005,24 +19027,24 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source uncasted_value->value->type->id == ZigTypeIdErrorSet) { ir_add_error(ira, source_instr, buf_sprintf("error is discarded")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } return ir_const_void(ira, source_instr); } if (ptr->value->type->data.pointer.is_const && !allow_write_through_const) { ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *child_type = ptr->value->type->data.pointer.child_type; - IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type); - if (value == ira->codegen->invalid_instruction) - return ira->codegen->invalid_instruction; + IrInstGen *value = ir_implicit_cast(ira, uncasted_value, child_type); + if (type_is_invalid(value->value->type)) + return ira->codegen->invalid_inst_gen; switch (type_has_one_possible_value(ira->codegen, child_type)) { case OnePossibleValueInvalid: - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case OnePossibleValueYes: return ir_const_void(ira, source_instr); case OnePossibleValueNo: @@ -18032,7 +19054,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source if (instr_is_comptime(ptr) && ptr->value->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { if (!allow_write_through_const && ptr->value->data.x_ptr.mut == ConstPtrMutComptimeConst) { ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if ((allow_write_through_const && ptr->value->data.x_ptr.mut == ConstPtrMutComptimeConst) || ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar || @@ -18041,7 +19063,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source if (instr_is_comptime(value)) { ZigValue *dest_val = const_ptr_pointee(ira, ira->codegen, ptr->value, source_instr->source_node); if (dest_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (dest_val->special != ConstValSpecialRuntime) { copy_const_val(dest_val, value->value); @@ -18061,7 +19083,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source ZigValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, ptr->value); dest_val->type = ira->codegen->builtin_types.entry_invalid; - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } } @@ -18074,15 +19096,15 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source switch (type_requires_comptime(ira->codegen, child_type)) { case ReqCompTimeInvalid: - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case ReqCompTimeYes: switch (type_has_one_possible_value(ira->codegen, ptr->value->type)) { case OnePossibleValueInvalid: - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case OnePossibleValueNo: ir_add_error(ira, source_instr, buf_sprintf("cannot store runtime value in type '%s'", buf_ptr(&child_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case OnePossibleValueYes: return ir_const_void(ira, source_instr); } @@ -18096,30 +19118,28 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source } // If this is a store to a pointer with a runtime-known vector index, - // we have to figure out the IrInstruction which represents the index and - // emit a IrInstructionVectorStoreElem, or emit a compile error + // we have to figure out the IrInstGen which represents the index and + // emit a IrInstGenVectorStoreElem, or emit a compile error // explaining why it is impossible for this store to work. Which is that // the pointer address is of the vector; without the element index being known // we cannot properly perform the insertion. if (ptr->value->type->data.pointer.vector_index == VECTOR_INDEX_RUNTIME) { - if (ptr->id == IrInstructionIdElemPtr) { - IrInstructionElemPtr *elem_ptr = (IrInstructionElemPtr *)ptr; + if (ptr->id == IrInstGenIdElemPtr) { + IrInstGenElemPtr *elem_ptr = (IrInstGenElemPtr *)ptr; return ir_build_vector_store_elem(ira, source_instr, elem_ptr->array_ptr, elem_ptr->elem_index, value); } - ir_add_error(ira, ptr, + ir_add_error(ira, &ptr->base, buf_sprintf("unable to determine vector element index of type '%s'", buf_ptr(&ptr->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstructionStorePtr *store_ptr = ir_build_store_ptr(&ira->new_irb, source_instr->scope, - source_instr->source_node, ptr, value); - return &store_ptr->base; + return ir_build_store_ptr_gen(ira, source_instr, ptr, value); } -static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *new_stack, bool is_async_call_builtin, ZigFn *fn_entry) +static IrInstGen *analyze_casted_new_stack(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *new_stack, bool is_async_call_builtin, ZigFn *fn_entry) { if (new_stack == nullptr) return nullptr; @@ -18148,11 +19168,11 @@ static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstruction *so } } -static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_instr, - ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref, - IrInstruction *first_arg_ptr, CallModifier modifier, - IrInstruction *new_stack, bool is_async_call_builtin, - IrInstruction **args_ptr, size_t args_len, IrInstruction *ret_ptr, ResultLoc *call_result_loc) +static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, + ZigFn *fn_entry, ZigType *fn_type, IrInstGen *fn_ref, + IrInstGen *first_arg_ptr, CallModifier modifier, + IrInstGen *new_stack, bool is_async_call_builtin, + IrInstGen **args_ptr, size_t args_len, IrInstGen *ret_ptr, ResultLoc *call_result_loc) { Error err; FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; @@ -18173,11 +19193,11 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i AstNode *fn_proto_node = fn_entry ? fn_entry->proto_node : nullptr;; if (fn_type_id->cc == CallingConventionNaked) { - ErrorMsg *msg = ir_add_error(ira, fn_ref, buf_sprintf("unable to call function with naked calling convention")); + ErrorMsg *msg = ir_add_error(ira, &fn_ref->base, buf_sprintf("unable to call function with naked calling convention")); if (fn_proto_node) { add_error_note(ira->codegen, msg, fn_proto_node, buf_sprintf("declared here")); } - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (fn_type_id->is_var_args) { @@ -18188,7 +19208,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i add_error_note(ira->codegen, msg, fn_proto_node, buf_sprintf("declared here")); } - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } else if (src_param_count != call_param_count) { ErrorMsg *msg = ir_add_error_node(ira, source_node, @@ -18197,18 +19217,18 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i add_error_note(ira->codegen, msg, fn_proto_node, buf_sprintf("declared here")); } - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (modifier == CallModifierCompileTime) { // No special handling is needed for compile time evaluation of generic functions. if (!fn_entry || fn_entry->body_node == nullptr) { - ir_add_error(ira, fn_ref, buf_sprintf("unable to evaluate constant expression")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &fn_ref->base, buf_sprintf("unable to evaluate constant expression")); + return ira->codegen->invalid_inst_gen; } if (!ir_emit_backward_branch(ira, source_instr)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; // Fork a scope of the function with known values for the parameters. Scope *exec_scope = &fn_entry->fndef_scope->base; @@ -18221,40 +19241,40 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i if (fn_type_id->next_param_index >= 1) { ZigType *param_type = fn_type_id->param_info[next_proto_i].type; if (type_is_invalid(param_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; first_arg_known_bare = param_type->id != ZigTypeIdPointer; } - IrInstruction *first_arg; + IrInstGen *first_arg; if (!first_arg_known_bare && handle_is_ptr(first_arg_ptr->value->type->data.pointer.child_type)) { first_arg = first_arg_ptr; } else { - first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr, nullptr); + first_arg = ir_get_deref(ira, &first_arg_ptr->base, first_arg_ptr, nullptr); if (type_is_invalid(first_arg->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (!ir_analyze_fn_call_inline_arg(ira, fn_proto_node, first_arg, &exec_scope, &next_proto_i)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } for (size_t call_i = 0; call_i < args_len; call_i += 1) { - IrInstruction *old_arg = args_ptr[call_i]; + IrInstGen *old_arg = args_ptr[call_i]; if (!ir_analyze_fn_call_inline_arg(ira, fn_proto_node, old_arg, &exec_scope, &next_proto_i)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; ZigType *specified_return_type = ir_analyze_type_expr(ira, exec_scope, return_type_node); if (type_is_invalid(specified_return_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *return_type; ZigType *inferred_err_set_type = nullptr; if (fn_proto_node->data.fn_proto.auto_err_set) { inferred_err_set_type = get_auto_err_set_type(ira->codegen, fn_entry); if ((err = type_resolve(ira->codegen, specified_return_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return_type = get_error_union_type(ira->codegen, inferred_err_set_type, specified_return_type); } else { return_type = specified_return_type; @@ -18278,7 +19298,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i fn_entry, nullptr, source_instr->source_node, nullptr, ira->new_irb.exec, return_type_node, UndefOk))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } destroy(result_ptr, "ZigValue"); result_ptr = nullptr; @@ -18306,24 +19326,24 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i } if (type_is_invalid(result->type)) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } - IrInstruction *new_instruction = ir_const_move(ira, source_instr, result); + IrInstGen *new_instruction = ir_const_move(ira, source_instr, result); return ir_finish_anal(ira, new_instruction); } if (fn_type->data.fn.is_generic) { if (!fn_entry) { - ir_add_error(ira, fn_ref, + ir_add_error(ira, &fn_ref->base, buf_sprintf("calling a generic function requires compile-time known function value")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } size_t new_fn_arg_count = first_arg_1_or_0 + args_len; - IrInstruction **casted_args = allocate(new_fn_arg_count); + IrInstGen **casted_args = allocate(new_fn_arg_count); // Fork a scope of the function with known values for the parameters. Scope *parent_scope = fn_entry->fndef_scope->base.parent; @@ -18352,30 +19372,30 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i if (fn_type_id->next_param_index >= 1) { ZigType *param_type = fn_type_id->param_info[next_proto_i].type; if (type_is_invalid(param_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; first_arg_known_bare = param_type->id != ZigTypeIdPointer; } - IrInstruction *first_arg; + IrInstGen *first_arg; if (!first_arg_known_bare && handle_is_ptr(first_arg_ptr->value->type->data.pointer.child_type)) { first_arg = first_arg_ptr; } else { - first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr, nullptr); + first_arg = ir_get_deref(ira, &first_arg_ptr->base, first_arg_ptr, nullptr); if (type_is_invalid(first_arg->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (!ir_analyze_fn_call_generic_arg(ira, fn_proto_node, first_arg, &impl_fn->child_scope, &next_proto_i, generic_id, &inst_fn_type_id, casted_args, impl_fn)) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } - ZigFn *parent_fn_entry = exec_fn_entry(ira->new_irb.exec); + ZigFn *parent_fn_entry = ira->new_irb.exec->fn_entry; assert(parent_fn_entry); for (size_t call_i = 0; call_i < args_len; call_i += 1) { - IrInstruction *arg = args_ptr[call_i]; + IrInstGen *arg = args_ptr[call_i]; AstNode *param_decl_node = fn_proto_node->data.fn_proto.params.at(next_proto_i); assert(param_decl_node->type == NodeTypeParamDecl); @@ -18383,7 +19403,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i if (!ir_analyze_fn_call_generic_arg(ira, fn_proto_node, arg, &impl_fn->child_scope, &next_proto_i, generic_id, &inst_fn_type_id, casted_args, impl_fn)) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } @@ -18397,9 +19417,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr, UndefBad))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstructionConst *const_instruction = ir_create_instruction_noval(&ira->new_irb, + IrInstGenConst *const_instruction = ir_create_inst_noval(&ira->new_irb, impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr); const_instruction->base.value = align_result; destroy(result_ptr, "ZigValue"); @@ -18414,11 +19434,11 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; ZigType *specified_return_type = ir_analyze_type_expr(ira, impl_fn->child_scope, return_type_node); if (type_is_invalid(specified_return_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (fn_proto_node->data.fn_proto.auto_err_set) { ZigType *inferred_err_set_type = get_auto_err_set_type(ira->codegen, impl_fn); if ((err = type_resolve(ira->codegen, specified_return_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; inst_fn_type_id.return_type = get_error_union_type(ira->codegen, inferred_err_set_type, specified_return_type); } else { inst_fn_type_id.return_type = specified_return_type; @@ -18431,7 +19451,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i CallModifierCompileTime, new_stack, is_async_call_builtin, args_ptr, args_len, ret_ptr, call_result_loc); case ReqCompTimeInvalid: - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case ReqCompTimeNo: break; } @@ -18445,7 +19465,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i // finish instantiating the function impl_fn->type_entry = get_fn_type(ira->codegen, &inst_fn_type_id); if (type_is_invalid(impl_fn->type_entry)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; impl_fn->ir_executable->source_node = source_instr->source_node; impl_fn->ir_executable->parent_exec = ira->new_irb.exec; @@ -18463,25 +19483,25 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i parent_fn_entry->calls_or_awaits_errorable_fn = true; } - IrInstruction *casted_new_stack = analyze_casted_new_stack(ira, source_instr, new_stack, + IrInstGen *casted_new_stack = analyze_casted_new_stack(ira, source_instr, new_stack, is_async_call_builtin, impl_fn); if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; size_t impl_param_count = impl_fn_type_id->param_count; if (modifier == CallModifierAsync) { - IrInstruction *result = ir_analyze_async_call(ira, source_instr, impl_fn, impl_fn->type_entry, + IrInstGen *result = ir_analyze_async_call(ira, source_instr, impl_fn, impl_fn->type_entry, nullptr, casted_args, impl_param_count, casted_new_stack, is_async_call_builtin, ret_ptr, call_result_loc); return ir_finish_anal(ira, result); } - IrInstruction *result_loc; + IrInstGen *result_loc; if (handle_is_ptr(impl_fn_type_id->return_type)) { result_loc = ir_resolve_result(ira, source_instr, call_result_loc, impl_fn_type_id->return_type, nullptr, true, false); if (result_loc != nullptr) { - if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) { + if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) { return result_loc; } ZigType *res_child_type = result_loc->value->type->data.pointer.child_type; @@ -18497,7 +19517,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i result_loc = get_async_call_result_loc(ira, source_instr, impl_fn_type_id->return_type, is_async_call_builtin, args_ptr, args_len, ret_ptr); if (result_loc != nullptr && type_is_invalid(result_loc->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else { result_loc = nullptr; } @@ -18506,11 +19526,11 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i parent_fn_entry->inferred_async_node == nullptr && modifier != CallModifierNoAsync) { - parent_fn_entry->inferred_async_node = fn_ref->source_node; + parent_fn_entry->inferred_async_node = fn_ref->base.source_node; parent_fn_entry->inferred_async_fn = impl_fn; } - IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, source_instr, + IrInstGenCall *new_call_instruction = ir_build_call_gen(ira, source_instr, impl_fn, nullptr, impl_param_count, casted_args, modifier, casted_new_stack, is_async_call_builtin, result_loc, impl_fn_type_id->return_type); @@ -18521,7 +19541,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i return ir_finish_anal(ira, &new_call_instruction->base); } - ZigFn *parent_fn_entry = exec_fn_entry(ira->new_irb.exec); + ZigFn *parent_fn_entry = ira->new_irb.exec->fn_entry; assert(fn_type_id->return_type != nullptr); assert(parent_fn_entry != nullptr); if (fn_type_can_fail(fn_type_id)) { @@ -18529,46 +19549,46 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i } - IrInstruction **casted_args = allocate(call_param_count); + IrInstGen **casted_args = allocate(call_param_count); size_t next_arg_index = 0; if (first_arg_ptr) { assert(first_arg_ptr->value->type->id == ZigTypeIdPointer); ZigType *param_type = fn_type_id->param_info[next_arg_index].type; if (type_is_invalid(param_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *first_arg; + IrInstGen *first_arg; if (param_type->id == ZigTypeIdPointer && handle_is_ptr(first_arg_ptr->value->type->data.pointer.child_type)) { first_arg = first_arg_ptr; } else { - first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr, nullptr); + first_arg = ir_get_deref(ira, &first_arg_ptr->base, first_arg_ptr, nullptr); if (type_is_invalid(first_arg->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *casted_arg = ir_implicit_cast(ira, first_arg, param_type); + IrInstGen *casted_arg = ir_implicit_cast(ira, first_arg, param_type); if (type_is_invalid(casted_arg->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; casted_args[next_arg_index] = casted_arg; next_arg_index += 1; } for (size_t call_i = 0; call_i < args_len; call_i += 1) { - IrInstruction *old_arg = args_ptr[call_i]; + IrInstGen *old_arg = args_ptr[call_i]; if (type_is_invalid(old_arg->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_arg; + IrInstGen *casted_arg; if (next_arg_index < src_param_count) { ZigType *param_type = fn_type_id->param_info[next_arg_index].type; if (type_is_invalid(param_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; casted_arg = ir_implicit_cast(ira, old_arg, param_type); if (type_is_invalid(casted_arg->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else { casted_arg = old_arg; } @@ -18581,21 +19601,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i ZigType *return_type = fn_type_id->return_type; if (type_is_invalid(return_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (fn_entry != nullptr && fn_entry->fn_inline == FnInlineAlways && modifier == CallModifierNeverInline) { ir_add_error(ira, source_instr, buf_sprintf("no-inline call of inline function")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *casted_new_stack = analyze_casted_new_stack(ira, source_instr, new_stack, + IrInstGen *casted_new_stack = analyze_casted_new_stack(ira, source_instr, new_stack, is_async_call_builtin, fn_entry); if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (modifier == CallModifierAsync) { - IrInstruction *result = ir_analyze_async_call(ira, source_instr, fn_entry, fn_type, fn_ref, + IrInstGen *result = ir_analyze_async_call(ira, source_instr, fn_entry, fn_type, fn_ref, casted_args, call_param_count, casted_new_stack, is_async_call_builtin, ret_ptr, call_result_loc); return ir_finish_anal(ira, result); } @@ -18604,16 +19624,16 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i parent_fn_entry->inferred_async_node == nullptr && modifier != CallModifierNoAsync) { - parent_fn_entry->inferred_async_node = fn_ref->source_node; + parent_fn_entry->inferred_async_node = fn_ref->base.source_node; parent_fn_entry->inferred_async_fn = fn_entry; } - IrInstruction *result_loc; + IrInstGen *result_loc; if (handle_is_ptr(return_type)) { result_loc = ir_resolve_result(ira, source_instr, call_result_loc, return_type, nullptr, true, false); if (result_loc != nullptr) { - if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) { + if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) { return result_loc; } ZigType *res_child_type = result_loc->value->type->data.pointer.child_type; @@ -18629,12 +19649,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i result_loc = get_async_call_result_loc(ira, source_instr, return_type, is_async_call_builtin, args_ptr, args_len, ret_ptr); if (result_loc != nullptr && type_is_invalid(result_loc->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else { result_loc = nullptr; } - IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, source_instr, fn_entry, fn_ref, + IrInstGenCall *new_call_instruction = ir_build_call_gen(ira, source_instr, fn_entry, fn_ref, call_param_count, casted_args, modifier, casted_new_stack, is_async_call_builtin, result_loc, return_type); if (get_scope_typeof(source_instr->scope) == nullptr) { @@ -18643,62 +19663,62 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_i return ir_finish_anal(ira, &new_call_instruction->base); } -static IrInstruction *ir_analyze_fn_call_src(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, - ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref, - IrInstruction *first_arg_ptr, CallModifier modifier) +static IrInstGen *ir_analyze_fn_call_src(IrAnalyze *ira, IrInstSrcCall *call_instruction, + ZigFn *fn_entry, ZigType *fn_type, IrInstGen *fn_ref, + IrInstGen *first_arg_ptr, CallModifier modifier) { - IrInstruction *new_stack = nullptr; + IrInstGen *new_stack = nullptr; if (call_instruction->new_stack) { new_stack = call_instruction->new_stack->child; if (type_is_invalid(new_stack->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction **args_ptr = allocate(call_instruction->arg_count, "IrInstruction *"); + IrInstGen **args_ptr = allocate(call_instruction->arg_count, "IrInstGen *"); for (size_t i = 0; i < call_instruction->arg_count; i += 1) { args_ptr[i] = call_instruction->args[i]->child; if (type_is_invalid(args_ptr[i]->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *ret_ptr = nullptr; + IrInstGen *ret_ptr = nullptr; if (call_instruction->ret_ptr != nullptr) { ret_ptr = call_instruction->ret_ptr->child; if (type_is_invalid(ret_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *result = ir_analyze_fn_call(ira, &call_instruction->base, fn_entry, fn_type, fn_ref, + IrInstGen *result = ir_analyze_fn_call(ira, &call_instruction->base.base, fn_entry, fn_type, fn_ref, first_arg_ptr, modifier, new_stack, call_instruction->is_async_call_builtin, args_ptr, call_instruction->arg_count, ret_ptr, call_instruction->result_loc); - deallocate(args_ptr, call_instruction->arg_count, "IrInstruction *"); + deallocate(args_ptr, call_instruction->arg_count, "IrInstGen *"); return result; } -static IrInstruction *ir_analyze_call_extra(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *pass1_options, IrInstruction *pass1_fn_ref, IrInstruction **args_ptr, size_t args_len, +static IrInstGen *ir_analyze_call_extra(IrAnalyze *ira, IrInst* source_instr, + IrInstSrc *pass1_options, IrInstSrc *pass1_fn_ref, IrInstGen **args_ptr, size_t args_len, ResultLoc *result_loc) { - IrInstruction *options = pass1_options->child; + IrInstGen *options = pass1_options->child; if (type_is_invalid(options->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *fn_ref = pass1_fn_ref->child; + IrInstGen *fn_ref = pass1_fn_ref->child; if (type_is_invalid(fn_ref->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; TypeStructField *modifier_field = find_struct_type_field(options->value->type, buf_create_from_str("modifier")); ir_assert(modifier_field != nullptr, source_instr); - IrInstruction *modifier_inst = ir_analyze_struct_value_field_value(ira, source_instr, options, modifier_field); + IrInstGen *modifier_inst = ir_analyze_struct_value_field_value(ira, source_instr, options, modifier_field); ZigValue *modifier_val = ir_resolve_const(ira, modifier_inst, UndefBad); if (modifier_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; CallModifier modifier = (CallModifier)bigint_as_u32(&modifier_val->data.x_enum_tag); - if (ir_should_inline(ira->new_irb.exec, source_instr->scope)) { + if (ir_should_inline(ira->old_irb.exec, source_instr->scope)) { switch (modifier) { case CallModifierBuiltin: zig_unreachable(); case CallModifierAsync: ir_add_error(ira, source_instr, buf_sprintf("TODO: comptime @call with async modifier")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case CallModifierCompileTime: case CallModifierNone: case CallModifierAlwaysInline: @@ -18709,15 +19729,15 @@ static IrInstruction *ir_analyze_call_extra(IrAnalyze *ira, IrInstruction *sourc case CallModifierNeverInline: ir_add_error(ira, source_instr, buf_sprintf("unable to perform 'never_inline' call at compile-time")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case CallModifierNeverTail: ir_add_error(ira, source_instr, buf_sprintf("unable to perform 'never_tail' call at compile-time")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } - IrInstruction *first_arg_ptr = nullptr; + IrInstGen *first_arg_ptr = nullptr; ZigFn *fn = nullptr; if (instr_is_comptime(fn_ref)) { if (fn_ref->value->type->id == ZigTypeIdBoundFn) { @@ -18725,7 +19745,7 @@ static IrInstruction *ir_analyze_call_extra(IrAnalyze *ira, IrInstruction *sourc fn = fn_ref->value->data.x_bound_fn.fn; first_arg_ptr = fn_ref->value->data.x_bound_fn.first_arg; if (type_is_invalid(first_arg_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else { fn = ir_resolve_fn(ira, fn_ref); } @@ -18737,9 +19757,9 @@ static IrInstruction *ir_analyze_call_extra(IrAnalyze *ira, IrInstruction *sourc case CallModifierAlwaysInline: case CallModifierAsync: if (fn == nullptr) { - ir_add_error(ira, modifier_inst, + ir_add_error(ira, &modifier_inst->base, buf_sprintf("the specified modifier requires a comptime-known function")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } default: break; @@ -18749,93 +19769,93 @@ static IrInstruction *ir_analyze_call_extra(IrAnalyze *ira, IrInstruction *sourc TypeStructField *stack_field = find_struct_type_field(options->value->type, buf_create_from_str("stack")); ir_assert(stack_field != nullptr, source_instr); - IrInstruction *opt_stack = ir_analyze_struct_value_field_value(ira, source_instr, options, stack_field); + IrInstGen *opt_stack = ir_analyze_struct_value_field_value(ira, source_instr, options, stack_field); if (type_is_invalid(opt_stack->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *stack_is_non_null_inst = ir_analyze_test_non_null(ira, source_instr, opt_stack); + IrInstGen *stack_is_non_null_inst = ir_analyze_test_non_null(ira, source_instr, opt_stack); bool stack_is_non_null; if (!ir_resolve_bool(ira, stack_is_non_null_inst, &stack_is_non_null)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *stack = nullptr; + IrInstGen *stack = nullptr; if (stack_is_non_null) { stack = ir_analyze_optional_value_payload_value(ira, source_instr, opt_stack, false); if (type_is_invalid(stack->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } return ir_analyze_fn_call(ira, source_instr, fn, fn_type, fn_ref, first_arg_ptr, modifier, stack, false, args_ptr, args_len, nullptr, result_loc); } -static IrInstruction *ir_analyze_instruction_call_extra(IrAnalyze *ira, IrInstructionCallExtra *instruction) { - IrInstruction *args = instruction->args->child; +static IrInstGen *ir_analyze_instruction_call_extra(IrAnalyze *ira, IrInstSrcCallExtra *instruction) { + IrInstGen *args = instruction->args->child; ZigType *args_type = args->value->type; if (type_is_invalid(args_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (args_type->id != ZigTypeIdStruct) { - ir_add_error(ira, args, + ir_add_error(ira, &args->base, buf_sprintf("expected tuple or struct, found '%s'", buf_ptr(&args_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction **args_ptr = nullptr; + IrInstGen **args_ptr = nullptr; size_t args_len = 0; if (is_tuple(args_type)) { args_len = args_type->data.structure.src_field_count; - args_ptr = allocate(args_len, "IrInstruction *"); + args_ptr = allocate(args_len, "IrInstGen *"); for (size_t i = 0; i < args_len; i += 1) { TypeStructField *arg_field = args_type->data.structure.fields[i]; - args_ptr[i] = ir_analyze_struct_value_field_value(ira, &instruction->base, args, arg_field); + args_ptr[i] = ir_analyze_struct_value_field_value(ira, &instruction->base.base, args, arg_field); if (type_is_invalid(args_ptr[i]->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } else { - ir_add_error(ira, args, buf_sprintf("TODO: struct args")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &args->base, buf_sprintf("TODO: struct args")); + return ira->codegen->invalid_inst_gen; } - IrInstruction *result = ir_analyze_call_extra(ira, &instruction->base, instruction->options, + IrInstGen *result = ir_analyze_call_extra(ira, &instruction->base.base, instruction->options, instruction->fn_ref, args_ptr, args_len, instruction->result_loc); - deallocate(args_ptr, args_len, "IrInstruction *"); + deallocate(args_ptr, args_len, "IrInstGen *"); return result; } -static IrInstruction *ir_analyze_instruction_call_args(IrAnalyze *ira, IrInstructionCallSrcArgs *instruction) { - IrInstruction **args_ptr = allocate(instruction->args_len, "IrInstruction *"); +static IrInstGen *ir_analyze_instruction_call_args(IrAnalyze *ira, IrInstSrcCallArgs *instruction) { + IrInstGen **args_ptr = allocate(instruction->args_len, "IrInstGen *"); for (size_t i = 0; i < instruction->args_len; i += 1) { args_ptr[i] = instruction->args_ptr[i]->child; if (type_is_invalid(args_ptr[i]->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *result = ir_analyze_call_extra(ira, &instruction->base, instruction->options, + IrInstGen *result = ir_analyze_call_extra(ira, &instruction->base.base, instruction->options, instruction->fn_ref, args_ptr, instruction->args_len, instruction->result_loc); - deallocate(args_ptr, instruction->args_len, "IrInstruction *"); + deallocate(args_ptr, instruction->args_len, "IrInstGen *"); return result; } -static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction) { - IrInstruction *fn_ref = call_instruction->fn_ref->child; +static IrInstGen *ir_analyze_instruction_call(IrAnalyze *ira, IrInstSrcCall *call_instruction) { + IrInstGen *fn_ref = call_instruction->fn_ref->child; if (type_is_invalid(fn_ref->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; bool is_comptime = (call_instruction->modifier == CallModifierCompileTime) || - ir_should_inline(ira->new_irb.exec, call_instruction->base.scope); + ir_should_inline(ira->old_irb.exec, call_instruction->base.base.scope); CallModifier modifier = is_comptime ? CallModifierCompileTime : call_instruction->modifier; if (is_comptime || instr_is_comptime(fn_ref)) { if (fn_ref->value->type->id == ZigTypeIdMetaType) { ZigType *ty = ir_resolve_type(ira, fn_ref); if (ty == nullptr) - return ira->codegen->invalid_instruction; - ErrorMsg *msg = ir_add_error_node(ira, fn_ref->source_node, + return ira->codegen->invalid_inst_gen; + ErrorMsg *msg = ir_add_error(ira, &fn_ref->base, buf_sprintf("type '%s' not a function", buf_ptr(&ty->name))); - add_error_note(ira->codegen, msg, call_instruction->base.source_node, + add_error_note(ira->codegen, msg, call_instruction->base.base.source_node, buf_sprintf("use @as builtin for type coercion")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else if (fn_ref->value->type->id == ZigTypeIdFn) { ZigFn *fn_table_entry = ir_resolve_fn(ira, fn_ref); ZigType *fn_type = fn_table_entry ? fn_table_entry->type_entry : fn_ref->value->type; @@ -18845,14 +19865,14 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC } else if (fn_ref->value->type->id == ZigTypeIdBoundFn) { assert(fn_ref->value->special == ConstValSpecialStatic); ZigFn *fn_table_entry = fn_ref->value->data.x_bound_fn.fn; - IrInstruction *first_arg_ptr = fn_ref->value->data.x_bound_fn.first_arg; + IrInstGen *first_arg_ptr = fn_ref->value->data.x_bound_fn.first_arg; CallModifier modifier = is_comptime ? CallModifierCompileTime : call_instruction->modifier; return ir_analyze_fn_call_src(ira, call_instruction, fn_table_entry, fn_table_entry->type_entry, fn_ref, first_arg_ptr, modifier); } else { - ir_add_error_node(ira, fn_ref->source_node, + ir_add_error(ira, &fn_ref->base, buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } @@ -18860,9 +19880,9 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC return ir_analyze_fn_call_src(ira, call_instruction, nullptr, fn_ref->value->type, fn_ref, nullptr, modifier); } else { - ir_add_error_node(ira, fn_ref->source_node, + ir_add_error(ira, &fn_ref->base, buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } @@ -18951,8 +19971,8 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source zig_unreachable(); } -static IrInstruction *ir_analyze_optional_type(IrAnalyze *ira, IrInstructionUnOp *instruction) { - IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type); +static IrInstGen *ir_analyze_optional_type(IrAnalyze *ira, IrInstSrcUnOp *instruction) { + IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_type); result->value->special = ConstValSpecialLazy; LazyValueOptType *lazy_opt_type = allocate(1, "LazyValueOptType"); @@ -18962,12 +19982,12 @@ static IrInstruction *ir_analyze_optional_type(IrAnalyze *ira, IrInstructionUnOp lazy_opt_type->payload_type = instruction->value->child; if (ir_resolve_type_lazy(ira, lazy_opt_type->payload_type) == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return result; } -static ErrorMsg *ir_eval_negation_scalar(IrAnalyze *ira, IrInstruction *source_instr, ZigType *scalar_type, +static ErrorMsg *ir_eval_negation_scalar(IrAnalyze *ira, IrInst* source_instr, ZigType *scalar_type, ZigValue *operand_val, ZigValue *scalar_out_val, bool is_wrap_op) { bool is_float = (scalar_type->id == ZigTypeIdFloat || scalar_type->id == ZigTypeIdComptimeFloat); @@ -19002,19 +20022,19 @@ static ErrorMsg *ir_eval_negation_scalar(IrAnalyze *ira, IrInstruction *source_i return nullptr; } -static IrInstruction *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *instruction) { - IrInstruction *value = instruction->value->child; +static IrInstGen *ir_analyze_negation(IrAnalyze *ira, IrInstSrcUnOp *instruction) { + IrInstGen *value = instruction->value->child; ZigType *expr_type = value->value->type; if (type_is_invalid(expr_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (!(expr_type->id == ZigTypeIdInt || expr_type->id == ZigTypeIdComptimeInt || expr_type->id == ZigTypeIdFloat || expr_type->id == ZigTypeIdComptimeFloat || expr_type->id == ZigTypeIdVector)) { - ir_add_error(ira, &instruction->base, + ir_add_error(ira, &instruction->base.base, buf_sprintf("negation of type '%s'", buf_ptr(&expr_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } bool is_wrap_op = (instruction->op_id == IrUnOpNegationWrap); @@ -19024,9 +20044,9 @@ static IrInstruction *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *ins if (instr_is_comptime(value)) { ZigValue *operand_val = ir_resolve_const(ira, value, UndefBad); if (!operand_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *result_instruction = ir_const(ira, &instruction->base, expr_type); + IrInstGen *result_instruction = ir_const(ira, &instruction->base.base, expr_type); ZigValue *out_val = result_instruction->value; if (expr_type->id == ZigTypeIdVector) { expand_undef_array(ira->codegen, operand_val); @@ -19038,63 +20058,60 @@ static IrInstruction *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *ins ZigValue *scalar_out_val = &out_val->data.x_array.data.s_none.elements[i]; assert(scalar_operand_val->type == scalar_type); assert(scalar_out_val->type == scalar_type); - ErrorMsg *msg = ir_eval_negation_scalar(ira, &instruction->base, scalar_type, + ErrorMsg *msg = ir_eval_negation_scalar(ira, &instruction->base.base, scalar_type, scalar_operand_val, scalar_out_val, is_wrap_op); if (msg != nullptr) { - add_error_note(ira->codegen, msg, instruction->base.source_node, + add_error_note(ira->codegen, msg, instruction->base.base.source_node, buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } out_val->type = expr_type; out_val->special = ConstValSpecialStatic; } else { - if (ir_eval_negation_scalar(ira, &instruction->base, scalar_type, operand_val, out_val, + if (ir_eval_negation_scalar(ira, &instruction->base.base, scalar_type, operand_val, out_val, is_wrap_op) != nullptr) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } return result_instruction; } - IrInstruction *result = ir_build_un_op(&ira->new_irb, - instruction->base.scope, instruction->base.source_node, - instruction->op_id, value); - result->value->type = expr_type; - return result; + if (is_wrap_op) { + return ir_build_negation_wrapping(ira, &instruction->base.base, value, expr_type); + } else { + return ir_build_negation(ira, &instruction->base.base, value, expr_type); + } } -static IrInstruction *ir_analyze_bin_not(IrAnalyze *ira, IrInstructionUnOp *instruction) { - IrInstruction *value = instruction->value->child; +static IrInstGen *ir_analyze_bin_not(IrAnalyze *ira, IrInstSrcUnOp *instruction) { + IrInstGen *value = instruction->value->child; ZigType *expr_type = value->value->type; if (type_is_invalid(expr_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (expr_type->id == ZigTypeIdInt) { if (instr_is_comptime(value)) { ZigValue *target_const_val = ir_resolve_const(ira, value, UndefBad); if (target_const_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *result = ir_const(ira, &instruction->base, expr_type); + IrInstGen *result = ir_const(ira, &instruction->base.base, expr_type); bigint_not(&result->value->data.x_bigint, &target_const_val->data.x_bigint, expr_type->data.integral.bit_count, expr_type->data.integral.is_signed); return result; } - IrInstruction *result = ir_build_un_op(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, IrUnOpBinNot, value); - result->value->type = expr_type; - return result; + return ir_build_binary_not(ira, &instruction->base.base, value, expr_type); } - ir_add_error(ira, &instruction->base, + ir_add_error(ira, &instruction->base.base, buf_sprintf("unable to perform binary not operation on type '%s'", buf_ptr(&expr_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } -static IrInstruction *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp *instruction) { +static IrInstGen *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstSrcUnOp *instruction) { IrUnOp op_id = instruction->op_id; switch (op_id) { case IrUnOpInvalid: @@ -19105,26 +20122,26 @@ static IrInstruction *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstruction case IrUnOpNegationWrap: return ir_analyze_negation(ira, instruction); case IrUnOpDereference: { - IrInstruction *ptr = instruction->value->child; + IrInstGen *ptr = instruction->value->child; if (type_is_invalid(ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *ptr_type = ptr->value->type; if (ptr_type->id == ZigTypeIdPointer && ptr_type->data.pointer.ptr_len == PtrLenUnknown) { - ir_add_error_node(ira, instruction->base.source_node, + ir_add_error_node(ira, instruction->base.base.source_node, buf_sprintf("index syntax required for unknown-length pointer type '%s'", buf_ptr(&ptr_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *result = ir_get_deref(ira, &instruction->base, ptr, instruction->result_loc); - if (result == ira->codegen->invalid_instruction) - return ira->codegen->invalid_instruction; + IrInstGen *result = ir_get_deref(ira, &instruction->base.base, ptr, instruction->result_loc); + if (type_is_invalid(result->value->type)) + return ira->codegen->invalid_inst_gen; // If the result needs to be an lvalue, type check it if (instruction->lval == LValPtr && result->value->type->id != ZigTypeIdPointer) { - ir_add_error(ira, &instruction->base, + ir_add_error(ira, &instruction->base.base, buf_sprintf("attempt to dereference non-pointer type '%s'", buf_ptr(&result->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } return result; @@ -19136,42 +20153,40 @@ static IrInstruction *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstruction } static void ir_push_resume(IrAnalyze *ira, IrSuspendPosition pos) { - IrBasicBlock *old_bb = ira->old_irb.exec->basic_block_list.at(pos.basic_block_index); + IrBasicBlockSrc *old_bb = ira->old_irb.exec->basic_block_list.at(pos.basic_block_index); if (old_bb->in_resume_stack) return; ira->resume_stack.append(pos); old_bb->in_resume_stack = true; } -static void ir_push_resume_block(IrAnalyze *ira, IrBasicBlock *old_bb) { +static void ir_push_resume_block(IrAnalyze *ira, IrBasicBlockSrc *old_bb) { if (ira->resume_stack.length != 0) { ir_push_resume(ira, {old_bb->index, 0}); } } -static IrInstruction *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) { - IrBasicBlock *old_dest_block = br_instruction->dest_block; +static IrInstGen *ir_analyze_instruction_br(IrAnalyze *ira, IrInstSrcBr *br_instruction) { + IrBasicBlockSrc *old_dest_block = br_instruction->dest_block; bool is_comptime; if (!ir_resolve_comptime(ira, br_instruction->is_comptime->child, &is_comptime)) return ir_unreach_error(ira); if (is_comptime || (old_dest_block->ref_count == 1 && old_dest_block->suspend_instruction_ref == nullptr)) - return ir_inline_bb(ira, &br_instruction->base, old_dest_block); + return ir_inline_bb(ira, &br_instruction->base.base, old_dest_block); - IrBasicBlock *new_bb = ir_get_new_bb_runtime(ira, old_dest_block, &br_instruction->base); + IrBasicBlockGen *new_bb = ir_get_new_bb_runtime(ira, old_dest_block, &br_instruction->base.base); if (new_bb == nullptr) return ir_unreach_error(ira); ir_push_resume_block(ira, old_dest_block); - IrInstruction *result = ir_build_br(&ira->new_irb, - br_instruction->base.scope, br_instruction->base.source_node, new_bb, nullptr); - result->value->type = ira->codegen->builtin_types.entry_unreachable; + IrInstGen *result = ir_build_br_gen(ira, &br_instruction->base.base, new_bb); return ir_finish_anal(ira, result); } -static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) { - IrInstruction *condition = cond_br_instruction->condition->child; +static IrInstGen *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstSrcCondBr *cond_br_instruction) { + IrInstGen *condition = cond_br_instruction->condition->child; if (type_is_invalid(condition->value->type)) return ir_unreach_error(ira); @@ -19180,7 +20195,7 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi return ir_unreach_error(ira); ZigType *bool_type = ira->codegen->builtin_types.entry_bool; - IrInstruction *casted_condition = ir_implicit_cast(ira, condition, bool_type); + IrInstGen *casted_condition = ir_implicit_cast(ira, condition, bool_type); if (type_is_invalid(casted_condition->value->type)) return ir_unreach_error(ira); @@ -19189,67 +20204,61 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi if (!ir_resolve_bool(ira, casted_condition, &cond_is_true)) return ir_unreach_error(ira); - IrBasicBlock *old_dest_block = cond_is_true ? + IrBasicBlockSrc *old_dest_block = cond_is_true ? cond_br_instruction->then_block : cond_br_instruction->else_block; if (is_comptime || (old_dest_block->ref_count == 1 && old_dest_block->suspend_instruction_ref == nullptr)) - return ir_inline_bb(ira, &cond_br_instruction->base, old_dest_block); + return ir_inline_bb(ira, &cond_br_instruction->base.base, old_dest_block); - IrBasicBlock *new_dest_block = ir_get_new_bb_runtime(ira, old_dest_block, &cond_br_instruction->base); + IrBasicBlockGen *new_dest_block = ir_get_new_bb_runtime(ira, old_dest_block, &cond_br_instruction->base.base); if (new_dest_block == nullptr) return ir_unreach_error(ira); ir_push_resume_block(ira, old_dest_block); - IrInstruction *result = ir_build_br(&ira->new_irb, - cond_br_instruction->base.scope, cond_br_instruction->base.source_node, new_dest_block, nullptr); - result->value->type = ira->codegen->builtin_types.entry_unreachable; + IrInstGen *result = ir_build_br_gen(ira, &cond_br_instruction->base.base, new_dest_block); return ir_finish_anal(ira, result); } assert(cond_br_instruction->then_block != cond_br_instruction->else_block); - IrBasicBlock *new_then_block = ir_get_new_bb_runtime(ira, cond_br_instruction->then_block, &cond_br_instruction->base); + IrBasicBlockGen *new_then_block = ir_get_new_bb_runtime(ira, cond_br_instruction->then_block, &cond_br_instruction->base.base); if (new_then_block == nullptr) return ir_unreach_error(ira); - IrBasicBlock *new_else_block = ir_get_new_bb_runtime(ira, cond_br_instruction->else_block, &cond_br_instruction->base); + IrBasicBlockGen *new_else_block = ir_get_new_bb_runtime(ira, cond_br_instruction->else_block, &cond_br_instruction->base.base); if (new_else_block == nullptr) return ir_unreach_error(ira); ir_push_resume_block(ira, cond_br_instruction->else_block); ir_push_resume_block(ira, cond_br_instruction->then_block); - IrInstruction *result = ir_build_cond_br(&ira->new_irb, - cond_br_instruction->base.scope, cond_br_instruction->base.source_node, - casted_condition, new_then_block, new_else_block, nullptr); - result->value->type = ira->codegen->builtin_types.entry_unreachable; + IrInstGen *result = ir_build_cond_br_gen(ira, &cond_br_instruction->base.base, + casted_condition, new_then_block, new_else_block); return ir_finish_anal(ira, result); } -static IrInstruction *ir_analyze_instruction_unreachable(IrAnalyze *ira, - IrInstructionUnreachable *unreachable_instruction) +static IrInstGen *ir_analyze_instruction_unreachable(IrAnalyze *ira, + IrInstSrcUnreachable *unreachable_instruction) { - IrInstruction *result = ir_build_unreachable(&ira->new_irb, - unreachable_instruction->base.scope, unreachable_instruction->base.source_node); - result->value->type = ira->codegen->builtin_types.entry_unreachable; + IrInstGen *result = ir_build_unreachable_gen(ira, &unreachable_instruction->base.base); return ir_finish_anal(ira, result); } -static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi_instruction) { +static IrInstGen *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstSrcPhi *phi_instruction) { Error err; if (ira->const_predecessor_bb) { for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) { - IrBasicBlock *predecessor = phi_instruction->incoming_blocks[i]; + IrBasicBlockSrc *predecessor = phi_instruction->incoming_blocks[i]; if (predecessor != ira->const_predecessor_bb) continue; - IrInstruction *value = phi_instruction->incoming_values[i]->child; + IrInstGen *value = phi_instruction->incoming_values[i]->child; assert(value->value->type); if (type_is_invalid(value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (value->value->special != ConstValSpecialRuntime) { - IrInstruction *result = ir_const(ira, &phi_instruction->base, nullptr); + IrInstGen *result = ir_const(ira, &phi_instruction->base.base, nullptr); copy_const_val(result->value, value->value); return result; } else { @@ -19264,17 +20273,17 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh peer_parent->peers.length >= 2) { if (peer_parent->resolved_type == nullptr) { - IrInstruction **instructions = allocate(peer_parent->peers.length); + IrInstGen **instructions = allocate(peer_parent->peers.length); for (size_t i = 0; i < peer_parent->peers.length; i += 1) { ResultLocPeer *this_peer = peer_parent->peers.at(i); - IrInstruction *gen_instruction = this_peer->base.gen_instruction; + IrInstGen *gen_instruction = this_peer->base.gen_instruction; if (gen_instruction == nullptr) { // unreachable instructions will cause implicit_elem_type to be null if (this_peer->base.implicit_elem_type == nullptr) { - instructions[i] = ir_const_unreachable(ira, this_peer->base.source_instruction); + instructions[i] = ir_const_unreachable(ira, &this_peer->base.source_instruction->base); } else { - instructions[i] = ir_const(ira, this_peer->base.source_instruction, + instructions[i] = ir_const(ira, &this_peer->base.source_instruction->base, this_peer->base.implicit_elem_type); instructions[i]->value->special = ConstValSpecialRuntime; } @@ -19283,34 +20292,34 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh } } - ZigType *expected_type = ir_result_loc_expected_type(ira, &phi_instruction->base, peer_parent->parent); + ZigType *expected_type = ir_result_loc_expected_type(ira, &phi_instruction->base.base, peer_parent->parent); peer_parent->resolved_type = ir_resolve_peer_types(ira, - peer_parent->base.source_instruction->source_node, expected_type, instructions, + peer_parent->base.source_instruction->base.source_node, expected_type, instructions, peer_parent->peers.length); if (type_is_invalid(peer_parent->resolved_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; // the logic below assumes there are no instructions in the new current basic block yet - ir_assert(ira->new_irb.current_basic_block->instruction_list.length == 0, &phi_instruction->base); + ir_assert(ira->new_irb.current_basic_block->instruction_list.length == 0, &phi_instruction->base.base); // In case resolving the parent activates a suspend, do it now - IrInstruction *parent_result_loc = ir_resolve_result(ira, &phi_instruction->base, peer_parent->parent, + IrInstGen *parent_result_loc = ir_resolve_result(ira, &phi_instruction->base.base, peer_parent->parent, peer_parent->resolved_type, nullptr, false, true); if (parent_result_loc != nullptr && - (type_is_invalid(parent_result_loc->value->type) || instr_is_unreachable(parent_result_loc))) + (type_is_invalid(parent_result_loc->value->type) || parent_result_loc->value->type->id == ZigTypeIdUnreachable)) { return parent_result_loc; } // If the above code generated any instructions in the current basic block, we need // to move them to the peer parent predecessor. - ZigList instrs_to_move = {}; + ZigList instrs_to_move = {}; while (ira->new_irb.current_basic_block->instruction_list.length != 0) { instrs_to_move.append(ira->new_irb.current_basic_block->instruction_list.pop()); } if (instrs_to_move.length != 0) { - IrBasicBlock *predecessor = peer_parent->base.source_instruction->child->owner_bb; - IrInstruction *branch_instruction = predecessor->instruction_list.pop(); - ir_assert(branch_instruction->value->type->id == ZigTypeIdUnreachable, &phi_instruction->base); + IrBasicBlockGen *predecessor = peer_parent->base.source_instruction->child->owner_bb; + IrInstGen *branch_instruction = predecessor->instruction_list.pop(); + ir_assert(branch_instruction->value->type->id == ZigTypeIdUnreachable, &phi_instruction->base.base); while (instrs_to_move.length != 0) { predecessor->instruction_list.append(instrs_to_move.pop()); } @@ -19319,7 +20328,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh } IrSuspendPosition suspend_pos; - ira_suspend(ira, &phi_instruction->base, nullptr, &suspend_pos); + ira_suspend(ira, &phi_instruction->base.base, nullptr, &suspend_pos); ir_push_resume(ira, suspend_pos); for (size_t i = 0; i < peer_parent->peers.length; i += 1) { @@ -19335,34 +20344,32 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh return ira_resume(ira); } - ZigList new_incoming_blocks = {0}; - ZigList new_incoming_values = {0}; + ZigList new_incoming_blocks = {0}; + ZigList new_incoming_values = {0}; for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) { - IrBasicBlock *predecessor = phi_instruction->incoming_blocks[i]; + IrBasicBlockSrc *predecessor = phi_instruction->incoming_blocks[i]; if (predecessor->ref_count == 0) continue; - IrInstruction *old_value = phi_instruction->incoming_values[i]; + IrInstSrc *old_value = phi_instruction->incoming_values[i]; assert(old_value); - IrInstruction *new_value = old_value->child; - if (!new_value || new_value->value->type->id == ZigTypeIdUnreachable || predecessor->other == nullptr) + IrInstGen *new_value = old_value->child; + if (!new_value || new_value->value->type->id == ZigTypeIdUnreachable || predecessor->child == nullptr) continue; if (type_is_invalid(new_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - assert(predecessor->other); - new_incoming_blocks.append(predecessor->other); + assert(predecessor->child); + new_incoming_blocks.append(predecessor->child); new_incoming_values.append(new_value); } if (new_incoming_blocks.length == 0) { - IrInstruction *result = ir_build_unreachable(&ira->new_irb, - phi_instruction->base.scope, phi_instruction->base.source_node); - result->value->type = ira->codegen->builtin_types.entry_unreachable; + IrInstGen *result = ir_build_unreachable_gen(ira, &phi_instruction->base.base); return ir_finish_anal(ira, result); } @@ -19374,7 +20381,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh if (peer_parent != nullptr) { bool peer_parent_has_type; if ((err = ir_result_has_type(ira, peer_parent->parent, &peer_parent_has_type))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (peer_parent_has_type) { if (peer_parent->parent->id == ResultLocIdReturn) { resolved_type = ira->explicit_return_type; @@ -19382,27 +20389,27 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh resolved_type = ir_resolve_type(ira, peer_parent->parent->source_instruction->child); } else if (peer_parent->parent->resolved_loc) { ZigType *resolved_loc_ptr_type = peer_parent->parent->resolved_loc->value->type; - ir_assert(resolved_loc_ptr_type->id == ZigTypeIdPointer, &phi_instruction->base); + ir_assert(resolved_loc_ptr_type->id == ZigTypeIdPointer, &phi_instruction->base.base); resolved_type = resolved_loc_ptr_type->data.pointer.child_type; } if (resolved_type != nullptr && type_is_invalid(resolved_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } if (resolved_type == nullptr) { - resolved_type = ir_resolve_peer_types(ira, phi_instruction->base.source_node, nullptr, + resolved_type = ir_resolve_peer_types(ira, phi_instruction->base.base.source_node, nullptr, new_incoming_values.items, new_incoming_values.length); if (type_is_invalid(resolved_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } switch (type_has_one_possible_value(ira->codegen, resolved_type)) { case OnePossibleValueInvalid: - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case OnePossibleValueYes: - return ir_const_move(ira, &phi_instruction->base, + return ir_const_move(ira, &phi_instruction->base.base, get_the_one_possible_value(ira->codegen, resolved_type)); case OnePossibleValueNo: break; @@ -19410,11 +20417,11 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh switch (type_requires_comptime(ira->codegen, resolved_type)) { case ReqCompTimeInvalid: - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case ReqCompTimeYes: - ir_add_error_node(ira, phi_instruction->base.source_node, + ir_add_error(ira, &phi_instruction->base.base, buf_sprintf("values of type '%s' must be comptime known", buf_ptr(&resolved_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case ReqCompTimeNo: break; } @@ -19424,16 +20431,16 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh // cast all values to the resolved type. however we can't put cast instructions in front of the phi instruction. // so we go back and insert the casts as the last instruction in the corresponding predecessor blocks, and // then make sure the branch instruction is preserved. - IrBasicBlock *cur_bb = ira->new_irb.current_basic_block; + IrBasicBlockGen *cur_bb = ira->new_irb.current_basic_block; for (size_t i = 0; i < new_incoming_values.length; i += 1) { - IrInstruction *new_value = new_incoming_values.at(i); - IrBasicBlock *predecessor = new_incoming_blocks.at(i); - ir_assert(predecessor->instruction_list.length != 0, &phi_instruction->base); - IrInstruction *branch_instruction = predecessor->instruction_list.pop(); - ir_set_cursor_at_end(&ira->new_irb, predecessor); - IrInstruction *casted_value = ir_implicit_cast(ira, new_value, resolved_type); + IrInstGen *new_value = new_incoming_values.at(i); + IrBasicBlockGen *predecessor = new_incoming_blocks.at(i); + ir_assert(predecessor->instruction_list.length != 0, &phi_instruction->base.base); + IrInstGen *branch_instruction = predecessor->instruction_list.pop(); + ir_set_cursor_at_end_gen(&ira->new_irb, predecessor); + IrInstGen *casted_value = ir_implicit_cast(ira, new_value, resolved_type); if (type_is_invalid(casted_value->value->type)) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } new_incoming_values.items[i] = casted_value; predecessor->instruction_list.append(branch_instruction); @@ -19444,12 +20451,10 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh all_stack_ptrs = false; } } - ir_set_cursor_at_end(&ira->new_irb, cur_bb); + ir_set_cursor_at_end_gen(&ira->new_irb, cur_bb); - IrInstruction *result = ir_build_phi(&ira->new_irb, - phi_instruction->base.scope, phi_instruction->base.source_node, - new_incoming_blocks.length, new_incoming_blocks.items, new_incoming_values.items, nullptr); - result->value->type = resolved_type; + IrInstGen *result = ir_build_phi_gen(ira, &phi_instruction->base.base, + new_incoming_blocks.length, new_incoming_blocks.items, new_incoming_values.items, resolved_type); if (all_stack_ptrs) { assert(result->value->special == ConstValSpecialRuntime); @@ -19459,17 +20464,17 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh return result; } -static IrInstruction *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructionVarPtr *instruction) { +static IrInstGen *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstSrcVarPtr *instruction) { ZigVar *var = instruction->var; - IrInstruction *result = ir_get_var_ptr(ira, &instruction->base, var); + IrInstGen *result = ir_get_var_ptr(ira, &instruction->base.base, var); if (instruction->crossed_fndef_scope != nullptr && !instr_is_comptime(result)) { - ErrorMsg *msg = ir_add_error(ira, &instruction->base, + ErrorMsg *msg = ir_add_error(ira, &instruction->base.base, buf_sprintf("'%s' not accessible from inner function", var->name)); add_error_note(ira->codegen, msg, instruction->crossed_fndef_scope->base.source_node, buf_sprintf("crossed function definition here")); add_error_note(ira->codegen, msg, var->decl_node, buf_sprintf("declared here")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } return result; } @@ -19520,17 +20525,17 @@ static ZigType *adjust_ptr_len(CodeGen *g, ZigType *ptr_type, PtrLen ptr_len) { ptr_type->data.pointer.allow_zero); } -static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) { +static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemPtr *elem_ptr_instruction) { Error err; - IrInstruction *array_ptr = elem_ptr_instruction->array_ptr->child; + IrInstGen *array_ptr = elem_ptr_instruction->array_ptr->child; if (type_is_invalid(array_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *orig_array_ptr_val = array_ptr->value; - IrInstruction *elem_index = elem_ptr_instruction->elem_index->child; + IrInstGen *elem_index = elem_ptr_instruction->elem_index->child; if (type_is_invalid(elem_index->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *ptr_type = orig_array_ptr_val->type; assert(ptr_type->id == ZigTypeIdPointer); @@ -19542,7 +20547,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct ZigType *return_type; if (type_is_invalid(array_type)) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else if (array_type->id == ZigTypeIdArray || (array_type->id == ZigTypeIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle && @@ -19553,15 +20558,15 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct ptr_type = ptr_type->data.pointer.child_type; if (orig_array_ptr_val->special != ConstValSpecialRuntime) { orig_array_ptr_val = const_ptr_pointee(ira, ira->codegen, orig_array_ptr_val, - elem_ptr_instruction->base.source_node); + elem_ptr_instruction->base.base.source_node); if (orig_array_ptr_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } if (array_type->data.array.len == 0) { - ir_add_error_node(ira, elem_ptr_instruction->base.source_node, + ir_add_error_node(ira, elem_ptr_instruction->base.base.source_node, buf_sprintf("index 0 outside array of size 0")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *child_type = array_type->data.array.child_type; if (ptr_type->data.pointer.host_int_bytes == 0) { @@ -19572,7 +20577,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct } else { uint64_t elem_val_scalar; if (!ir_resolve_usize(ira, elem_index, &elem_val_scalar)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; size_t bit_width = type_size_bits(ira->codegen, child_type); size_t bit_offset = bit_width * elem_val_scalar; @@ -19584,9 +20589,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct } } else if (array_type->id == ZigTypeIdPointer) { if (array_type->data.pointer.ptr_len == PtrLenSingle) { - ir_add_error_node(ira, elem_ptr_instruction->base.source_node, + ir_add_error_node(ira, elem_ptr_instruction->base.base.source_node, buf_sprintf("index of single-item pointer")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } return_type = adjust_ptr_len(ira->codegen, array_type, elem_ptr_instruction->ptr_len); } else if (is_slice(array_type)) { @@ -19600,38 +20605,38 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct array_type->data.structure.resolve_status == ResolveStatusBeingInferred) { ZigType *usize = ira->codegen->builtin_types.entry_usize; - IrInstruction *casted_elem_index = ir_implicit_cast(ira, elem_index, usize); + IrInstGen *casted_elem_index = ir_implicit_cast(ira, elem_index, usize); if (type_is_invalid(casted_elem_index->value->type)) - return ira->codegen->invalid_instruction; - ir_assert(instr_is_comptime(casted_elem_index), &elem_ptr_instruction->base); + return ira->codegen->invalid_inst_gen; + ir_assert(instr_is_comptime(casted_elem_index), &elem_ptr_instruction->base.base); Buf *field_name = buf_alloc(); bigint_append_buf(field_name, &casted_elem_index->value->data.x_bigint, 10); - return ir_analyze_inferred_field_ptr(ira, field_name, &elem_ptr_instruction->base, + return ir_analyze_inferred_field_ptr(ira, field_name, &elem_ptr_instruction->base.base, array_ptr, array_type); } else if (is_tuple(array_type)) { uint64_t elem_index_scalar; if (!ir_resolve_usize(ira, elem_index, &elem_index_scalar)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (elem_index_scalar >= array_type->data.structure.src_field_count) { - ir_add_error(ira, &elem_ptr_instruction->base, buf_sprintf( + ir_add_error(ira, &elem_ptr_instruction->base.base, buf_sprintf( "field index %" ZIG_PRI_u64 " outside tuple '%s' which has %" PRIu32 " fields", elem_index_scalar, buf_ptr(&array_type->name), array_type->data.structure.src_field_count)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } TypeStructField *field = array_type->data.structure.fields[elem_index_scalar]; - return ir_analyze_struct_field_ptr(ira, &elem_ptr_instruction->base, field, array_ptr, + return ir_analyze_struct_field_ptr(ira, &elem_ptr_instruction->base.base, field, array_ptr, array_type, false); } else { - ir_add_error_node(ira, elem_ptr_instruction->base.source_node, + ir_add_error_node(ira, elem_ptr_instruction->base.base.source_node, buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *usize = ira->codegen->builtin_types.entry_usize; - IrInstruction *casted_elem_index = ir_implicit_cast(ira, elem_index, usize); - if (casted_elem_index == ira->codegen->invalid_instruction) - return ira->codegen->invalid_instruction; + IrInstGen *casted_elem_index = ir_implicit_cast(ira, elem_index, usize); + if (type_is_invalid(casted_elem_index->value->type)) + return ira->codegen->invalid_inst_gen; bool safety_check_on = elem_ptr_instruction->safety_check_on; if (instr_is_comptime(casted_elem_index)) { @@ -19640,15 +20645,15 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct uint64_t array_len = array_type->data.array.len; if (index == array_len && array_type->data.array.sentinel != nullptr) { ZigType *elem_type = array_type->data.array.child_type; - IrInstruction *sentinel_elem = ir_const(ira, &elem_ptr_instruction->base, elem_type); + IrInstGen *sentinel_elem = ir_const(ira, &elem_ptr_instruction->base.base, elem_type); copy_const_val(sentinel_elem->value, array_type->data.array.sentinel); - return ir_get_ref(ira, &elem_ptr_instruction->base, sentinel_elem, true, false); + return ir_get_ref(ira, &elem_ptr_instruction->base.base, sentinel_elem, true, false); } if (index >= array_len) { - ir_add_error_node(ira, elem_ptr_instruction->base.source_node, + ir_add_error_node(ira, elem_ptr_instruction->base.base.source_node, buf_sprintf("index %" ZIG_PRI_u64 " outside array of size %" ZIG_PRI_u64, index, array_len)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } safety_check_on = false; } @@ -19664,7 +20669,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct // figure out the largest alignment possible if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type); uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type); @@ -19696,9 +20701,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct (orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar || array_type->id == ZigTypeIdArray)) { ZigValue *array_ptr_val = const_ptr_pointee(ira, ira->codegen, orig_array_ptr_val, - elem_ptr_instruction->base.source_node); + elem_ptr_instruction->base.base.source_node); if (array_ptr_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (array_ptr_val->special == ConstValSpecialUndef && elem_ptr_instruction->init_array_type_source_node != nullptr) @@ -19716,16 +20721,16 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct elem_val->parent.data.p_array.elem_index = i; } } else if (is_slice(array_type)) { - ir_assert(array_ptr->value->type->id == ZigTypeIdPointer, &elem_ptr_instruction->base); + ir_assert(array_ptr->value->type->id == ZigTypeIdPointer, &elem_ptr_instruction->base.base); ZigType *actual_array_type = array_ptr->value->type->data.pointer.child_type; if (type_is_invalid(actual_array_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (actual_array_type->id != ZigTypeIdArray) { ir_add_error_node(ira, elem_ptr_instruction->init_array_type_source_node, buf_sprintf("array literal requires address-of operator to coerce to slice type '%s'", buf_ptr(&actual_array_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigValue *array_init_val = create_const_vals(1); @@ -19750,7 +20755,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct ir_add_error_node(ira, elem_ptr_instruction->init_array_type_source_node, buf_sprintf("expected array type or [_], found '%s'", buf_ptr(&array_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } @@ -19759,12 +20764,12 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr)) { if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, - elem_ptr_instruction->base.source_node, array_ptr_val, UndefOk))) + elem_ptr_instruction->base.base.source_node, array_ptr_val, UndefOk))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (array_type->id == ZigTypeIdPointer) { - IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type); + IrInstGen *result = ir_const(ira, &elem_ptr_instruction->base.base, return_type); ZigValue *out_val = result->value; out_val->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut; size_t new_index; @@ -19833,33 +20838,31 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct zig_panic("TODO elem ptr on a null pointer"); } if (new_index >= mem_size) { - ir_add_error_node(ira, elem_ptr_instruction->base.source_node, + ir_add_error_node(ira, elem_ptr_instruction->base.base.source_node, buf_sprintf("index %" ZIG_PRI_u64 " outside pointer of size %" ZIG_PRI_usize "", index, old_size)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } return result; } else if (is_slice(array_type)) { ZigValue *ptr_field = array_ptr_val->data.x_struct.fields[slice_ptr_index]; - ir_assert(ptr_field != nullptr, &elem_ptr_instruction->base); + ir_assert(ptr_field != nullptr, &elem_ptr_instruction->base.base); if (ptr_field->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { - IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, - elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, false, - elem_ptr_instruction->ptr_len, nullptr); - result->value->type = return_type; - return result; + return ir_build_elem_ptr_gen(ira, elem_ptr_instruction->base.base.scope, + elem_ptr_instruction->base.base.source_node, array_ptr, casted_elem_index, false, + return_type); } ZigValue *len_field = array_ptr_val->data.x_struct.fields[slice_len_index]; - IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type); + IrInstGen *result = ir_const(ira, &elem_ptr_instruction->base.base, return_type); ZigValue *out_val = result->value; ZigType *slice_ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry; uint64_t slice_len = bigint_as_u64(&len_field->data.x_bigint); uint64_t full_slice_len = slice_len + ((slice_ptr_type->data.pointer.sentinel != nullptr) ? 1 : 0); if (index >= full_slice_len) { - ir_add_error_node(ira, elem_ptr_instruction->base.source_node, + ir_add_error_node(ira, elem_ptr_instruction->base.base.source_node, buf_sprintf("index %" ZIG_PRI_u64 " outside slice of size %" ZIG_PRI_u64, index, slice_len)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } out_val->data.x_ptr.mut = ptr_field->data.x_ptr.mut; switch (ptr_field->data.x_ptr.special) { @@ -19879,7 +20882,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct { ir_assert(new_index < ptr_field->data.x_ptr.data.base_array.array_val->type->data.array.len, - &elem_ptr_instruction->base); + &elem_ptr_instruction->base.base); } out_val->data.x_ptr.special = ConstPtrSpecialBaseArray; out_val->data.x_ptr.data.base_array.array_val = @@ -19904,15 +20907,14 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct } return result; } else if (array_type->id == ZigTypeIdArray || array_type->id == ZigTypeIdVector) { - IrInstruction *result; + IrInstGen *result; if (orig_array_ptr_val->data.x_ptr.mut == ConstPtrMutInfer) { - result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, - elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, - false, elem_ptr_instruction->ptr_len, nullptr); - result->value->type = return_type; + result = ir_build_elem_ptr_gen(ira, elem_ptr_instruction->base.base.scope, + elem_ptr_instruction->base.base.source_node, array_ptr, casted_elem_index, + false, return_type); result->value->special = ConstValSpecialStatic; } else { - result = ir_const(ira, &elem_ptr_instruction->base, return_type); + result = ir_const(ira, &elem_ptr_instruction->base.base, return_type); } ZigValue *out_val = result->value; out_val->data.x_ptr.special = ConstPtrSpecialBaseArray; @@ -19938,19 +20940,19 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct // runtime known element index switch (type_requires_comptime(ira->codegen, return_type)) { case ReqCompTimeYes: - ir_add_error(ira, elem_index, + ir_add_error(ira, &elem_index->base, buf_sprintf("values of type '%s' must be comptime known, but index value is runtime known", buf_ptr(&return_type->data.pointer.child_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case ReqCompTimeInvalid: - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case ReqCompTimeNo: break; } if (return_type->data.pointer.explicit_alignment != 0) { if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type); uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type); @@ -19968,16 +20970,13 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct } } - IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, - elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, safety_check_on, - elem_ptr_instruction->ptr_len, nullptr); - result->value->type = return_type; - return result; + return ir_build_elem_ptr_gen(ira, elem_ptr_instruction->base.base.scope, + elem_ptr_instruction->base.base.source_node, array_ptr, casted_elem_index, safety_check_on, return_type); } -static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira, - ZigType *bare_struct_type, Buf *field_name, IrInstruction *source_instr, - IrInstruction *container_ptr, ZigType *container_type) +static IrInstGen *ir_analyze_container_member_access_inner(IrAnalyze *ira, + ZigType *bare_struct_type, Buf *field_name, IrInst* source_instr, + IrInstGen *container_ptr, ZigType *container_type) { if (!is_slice(bare_struct_type)) { ScopeDecls *container_scope = get_container_scope(bare_struct_type); @@ -19987,29 +20986,37 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira, if (tld->id == TldIdFn) { resolve_top_level_decl(ira->codegen, tld, source_instr->source_node, false); if (tld->resolution == TldResolutionInvalid) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; + if (tld->resolution == TldResolutionResolving) + return ir_error_dependency_loop(ira, source_instr); + TldFn *tld_fn = (TldFn *)tld; ZigFn *fn_entry = tld_fn->fn_entry; - if (type_is_invalid(fn_entry->type_entry)) - return ira->codegen->invalid_instruction; + assert(fn_entry != nullptr); - IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, source_instr->scope, - source_instr->source_node, fn_entry, container_ptr); + if (type_is_invalid(fn_entry->type_entry)) + return ira->codegen->invalid_inst_gen; + + IrInstGen *bound_fn_value = ir_const_bound_fn(ira, source_instr, fn_entry, container_ptr); return ir_get_ref(ira, source_instr, bound_fn_value, true, false); } else if (tld->id == TldIdVar) { resolve_top_level_decl(ira->codegen, tld, source_instr->source_node, false); if (tld->resolution == TldResolutionInvalid) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; + if (tld->resolution == TldResolutionResolving) + return ir_error_dependency_loop(ira, source_instr); + TldVar *tld_var = (TldVar *)tld; ZigVar *var = tld_var->var; + assert(var != nullptr); + if (type_is_invalid(var->var_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (var->const_value->type->id == ZigTypeIdFn) { ir_assert(var->const_value->data.x_ptr.special == ConstPtrSpecialFunction, source_instr); ZigFn *fn = var->const_value->data.x_ptr.data.fn.fn_entry; - IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, source_instr->scope, - source_instr->source_node, fn, container_ptr); + IrInstGen *bound_fn_value = ir_const_bound_fn(ira, source_instr, fn, container_ptr); return ir_get_ref(ira, source_instr, bound_fn_value, true, false); } } @@ -20029,7 +21036,7 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira, } ir_add_error_node(ira, source_instr->source_node, buf_sprintf("no member named '%s' in %s'%s'", buf_ptr(field_name), prefix_name, buf_ptr(&bare_struct_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } static void memoize_field_init_val(CodeGen *codegen, ZigType *container_type, TypeStructField *field) { @@ -20044,24 +21051,24 @@ static void memoize_field_init_val(CodeGen *codegen, ZigType *container_type, Ty field->type_entry, nullptr, UndefOk); } -static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction *source_instr, - TypeStructField *field, IrInstruction *struct_ptr, ZigType *struct_type, bool initializing) +static IrInstGen *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInst* source_instr, + TypeStructField *field, IrInstGen *struct_ptr, ZigType *struct_type, bool initializing) { Error err; ZigType *field_type = resolve_struct_field_type(ira->codegen, field); if (field_type == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (field->is_comptime) { - IrInstruction *elem = ir_const(ira, source_instr, field_type); + IrInstGen *elem = ir_const(ira, source_instr, field_type); memoize_field_init_val(ira->codegen, struct_type, field); copy_const_val(elem->value, field->init_val); return ir_get_ref(ira, source_instr, elem, true, false); } switch (type_has_one_possible_value(ira->codegen, field_type)) { case OnePossibleValueInvalid: - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case OnePossibleValueYes: { - IrInstruction *elem = ir_const_move(ira, source_instr, + IrInstGen *elem = ir_const_move(ira, source_instr, get_the_one_possible_value(ira->codegen, field_type)); return ir_get_ref(ira, source_instr, elem, false, false); } @@ -20079,7 +21086,7 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction (struct_type->data.structure.layout == ContainerLayoutAuto) ? ResolveStatusZeroBitsKnown : ResolveStatusSizeKnown; if ((err = type_resolve(ira->codegen, struct_type, needed_resolve_status))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; assert(struct_ptr->value->type->id == ZigTypeIdPointer); uint32_t ptr_bit_offset = struct_ptr->value->type->data.pointer.bit_offset_in_host; uint32_t ptr_host_int_bytes = struct_ptr->value->type->data.pointer.host_int_bytes; @@ -20093,14 +21100,14 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction if (instr_is_comptime(struct_ptr)) { ZigValue *ptr_val = ir_resolve_const(ira, struct_ptr, UndefBad); if (!ptr_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { ZigValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); if (struct_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (type_is_invalid(struct_val->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (initializing && struct_val->special == ConstValSpecialUndef) { struct_val->data.x_struct.fields = alloc_const_vals_ptrs(struct_type->data.structure.src_field_count); struct_val->special = ConstValSpecialStatic; @@ -20114,11 +21121,9 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction field_val->parent.data.p_struct.field_index = i; } } - IrInstruction *result; + IrInstGen *result; if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) { - result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope, - source_instr->source_node, struct_ptr, field); - result->value->type = ptr_type; + result = ir_build_struct_field_ptr(ira, source_instr, struct_ptr, field, ptr_type); result->value->special = ConstValSpecialStatic; } else { result = ir_const(ira, source_instr, ptr_type); @@ -20131,14 +21136,11 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction return result; } } - IrInstruction *result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, - struct_ptr, field); - result->value->type = ptr_type; - return result; + return ir_build_struct_field_ptr(ira, source_instr, struct_ptr, field, ptr_type); } -static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name, - IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type) +static IrInstGen *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name, + IrInst* source_instr, IrInstGen *container_ptr, ZigType *container_type) { // The type of the field is not available until a store using this pointer happens. // So, here we create a special pointer type which has the inferred struct type and @@ -20161,12 +21163,11 @@ static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_n if (instr_is_comptime(container_ptr)) { ZigValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad); if (ptr_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *result; + IrInstGen *result; if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) { - result = ir_build_cast(&ira->new_irb, source_instr->scope, - source_instr->source_node, container_ptr_type, container_ptr, CastOpNoop); + result = ir_build_cast(ira, source_instr, container_ptr_type, container_ptr, CastOpNoop); } else { result = ir_const(ira, source_instr, field_ptr_type); } @@ -20175,14 +21176,11 @@ static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_n return result; } - IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, - source_instr->source_node, field_ptr_type, container_ptr, CastOpNoop); - result->value->type = field_ptr_type; - return result; + return ir_build_cast(ira, source_instr, field_ptr_type, container_ptr, CastOpNoop); } -static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name, - IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing) +static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name, + IrInst* source_instr, IrInstGen *container_ptr, ZigType *container_type, bool initializing) { Error err; @@ -20195,7 +21193,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ } if ((err = type_resolve(ira->codegen, bare_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; assert(container_ptr->value->type->id == ZigTypeIdPointer); if (bare_type->id == ZigTypeIdStruct) { @@ -20225,22 +21223,22 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ ZigType *field_type = resolve_union_field_type(ira->codegen, field); if (field_type == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type, is_const, is_volatile, PtrLenSingle, 0, 0, 0, false); if (instr_is_comptime(container_ptr)) { ZigValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad); if (!ptr_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar && ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { ZigValue *union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); if (union_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (type_is_invalid(union_val->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (initializing) { ZigValue *payload_val = create_const_vals(1); @@ -20261,17 +21259,16 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ ir_add_error_node(ira, source_instr->source_node, buf_sprintf("accessing union field '%s' while field '%s' is set", buf_ptr(field_name), buf_ptr(actual_field->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } ZigValue *payload_val = union_val->data.x_union.payload; - IrInstruction *result; + IrInstGen *result; if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) { - result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope, - source_instr->source_node, container_ptr, field, true, initializing); - result->value->type = ptr_type; + result = ir_build_union_field_ptr(ira, source_instr, container_ptr, field, true, + initializing, ptr_type); result->value->special = ConstValSpecialStatic; } else { result = ir_const(ira, source_instr, ptr_type); @@ -20284,10 +21281,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ } } - IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope, - source_instr->source_node, container_ptr, field, true, initializing); - result->value->type = ptr_type; - return result; + return ir_build_union_field_ptr(ira, source_instr, container_ptr, field, true, initializing, ptr_type); } zig_unreachable(); @@ -20328,16 +21322,18 @@ static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, link_lib->symbols.append(symbol_name); } -static IrInstruction *ir_error_dependency_loop(IrAnalyze *ira, IrInstruction *source_instr) { +static IrInstGen *ir_error_dependency_loop(IrAnalyze *ira, IrInst* source_instr) { ir_add_error(ira, source_instr, buf_sprintf("dependency loop detected")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } -static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instruction, Tld *tld) { +static IrInstGen *ir_analyze_decl_ref(IrAnalyze *ira, IrInst* source_instruction, Tld *tld) { resolve_top_level_decl(ira->codegen, tld, source_instruction->source_node, true); if (tld->resolution == TldResolutionInvalid) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } + if (tld->resolution == TldResolutionResolving) + return ir_error_dependency_loop(ira, source_instruction); switch (tld->id) { case TldIdContainer: @@ -20347,9 +21343,8 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_ case TldIdVar: { TldVar *tld_var = (TldVar *)tld; ZigVar *var = tld_var->var; - if (var == nullptr) { - return ir_error_dependency_loop(ira, source_instruction); - } + assert(var != nullptr); + if (tld_var->extern_lib_name != nullptr) { add_link_lib_symbol(ira, tld_var->extern_lib_name, buf_create_from_str(var->name), source_instruction->source_node); @@ -20360,17 +21355,16 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_ case TldIdFn: { TldFn *tld_fn = (TldFn *)tld; ZigFn *fn_entry = tld_fn->fn_entry; - assert(fn_entry->type_entry); + assert(fn_entry->type_entry != nullptr); if (type_is_invalid(fn_entry->type_entry)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (tld_fn->extern_lib_name != nullptr) { add_link_lib_symbol(ira, tld_fn->extern_lib_name, &fn_entry->symbol_name, source_instruction->source_node); } - IrInstruction *fn_inst = ir_create_const_fn(&ira->new_irb, source_instruction->scope, - source_instruction->source_node, fn_entry); + IrInstGen *fn_inst = ir_const_fn(ira, source_instruction, fn_entry); return ir_get_ref(ira, source_instruction, fn_inst, true, false); } } @@ -20388,40 +21382,40 @@ static ErrorTableEntry *find_err_table_entry(ZigType *err_set_type, Buf *field_n return nullptr; } -static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFieldPtr *field_ptr_instruction) { +static IrInstGen *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstSrcFieldPtr *field_ptr_instruction) { Error err; - IrInstruction *container_ptr = field_ptr_instruction->container_ptr->child; + IrInstGen *container_ptr = field_ptr_instruction->container_ptr->child; if (type_is_invalid(container_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *container_type = container_ptr->value->type->data.pointer.child_type; Buf *field_name = field_ptr_instruction->field_name_buffer; if (!field_name) { - IrInstruction *field_name_expr = field_ptr_instruction->field_name_expr->child; + IrInstGen *field_name_expr = field_ptr_instruction->field_name_expr->child; field_name = ir_resolve_str(ira, field_name_expr); if (!field_name) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - AstNode *source_node = field_ptr_instruction->base.source_node; + AstNode *source_node = field_ptr_instruction->base.base.source_node; if (type_is_invalid(container_type)) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else if (is_tuple(container_type) && !field_ptr_instruction->initializing && buf_eql_str(field_name, "len")) { - IrInstruction *len_inst = ir_const_unsigned(ira, &field_ptr_instruction->base, + IrInstGen *len_inst = ir_const_unsigned(ira, &field_ptr_instruction->base.base, container_type->data.structure.src_field_count); - return ir_get_ref(ira, &field_ptr_instruction->base, len_inst, true, false); + return ir_get_ref(ira, &field_ptr_instruction->base.base, len_inst, true, false); } else if (is_slice(container_type) || is_container_ref(container_type)) { assert(container_ptr->value->type->id == ZigTypeIdPointer); if (container_type->id == ZigTypeIdPointer) { ZigType *bare_type = container_ref_type(container_type); - IrInstruction *container_child = ir_get_deref(ira, &field_ptr_instruction->base, container_ptr, nullptr); - IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_child, bare_type, field_ptr_instruction->initializing); + IrInstGen *container_child = ir_get_deref(ira, &field_ptr_instruction->base.base, container_ptr, nullptr); + IrInstGen *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base.base, container_child, bare_type, field_ptr_instruction->initializing); return result; } else { - IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_ptr, container_type, field_ptr_instruction->initializing); + IrInstGen *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base.base, container_ptr, container_type, field_ptr_instruction->initializing); return result; } } else if (is_array_ref(container_type) && !field_ptr_instruction->initializing) { @@ -20436,42 +21430,42 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc ZigType *usize = ira->codegen->builtin_types.entry_usize; bool ptr_is_const = true; bool ptr_is_volatile = false; - return ir_get_const_ptr(ira, &field_ptr_instruction->base, len_val, + return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, len_val, usize, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); } else { ir_add_error_node(ira, source_node, buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&container_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } else if (container_type->id == ZigTypeIdMetaType) { ZigValue *container_ptr_val = ir_resolve_const(ira, container_ptr, UndefBad); if (!container_ptr_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; assert(container_ptr->value->type->id == ZigTypeIdPointer); ZigValue *child_val = const_ptr_pointee(ira, ira->codegen, container_ptr_val, source_node); if (child_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, - field_ptr_instruction->base.source_node, child_val, UndefBad))) + field_ptr_instruction->base.base.source_node, child_val, UndefBad))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *child_type = child_val->data.x_type; if (type_is_invalid(child_type)) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else if (is_container(child_type)) { if (child_type->id == ZigTypeIdEnum) { if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; TypeEnumField *field = find_enum_type_field(child_type, field_name); if (field) { bool ptr_is_const = true; bool ptr_is_volatile = false; - return ir_get_const_ptr(ira, &field_ptr_instruction->base, + return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, create_const_enum(child_type, &field->value), child_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); } @@ -20480,37 +21474,37 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc Tld *tld = find_container_decl(ira->codegen, container_scope, field_name); if (tld) { if (tld->visib_mod == VisibModPrivate && - tld->import != get_scope_import(field_ptr_instruction->base.scope)) + tld->import != get_scope_import(field_ptr_instruction->base.base.scope)) { - ErrorMsg *msg = ir_add_error(ira, &field_ptr_instruction->base, + ErrorMsg *msg = ir_add_error(ira, &field_ptr_instruction->base.base, buf_sprintf("'%s' is private", buf_ptr(field_name))); add_error_note(ira->codegen, msg, tld->source_node, buf_sprintf("declared here")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - return ir_analyze_decl_ref(ira, &field_ptr_instruction->base, tld); + return ir_analyze_decl_ref(ira, &field_ptr_instruction->base.base, tld); } if (child_type->id == ZigTypeIdUnion && (child_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr || child_type->data.unionation.decl_node->data.container_decl.auto_enum)) { if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; TypeUnionField *field = find_union_type_field(child_type, field_name); if (field) { ZigType *enum_type = child_type->data.unionation.tag_type; bool ptr_is_const = true; bool ptr_is_volatile = false; - return ir_get_const_ptr(ira, &field_ptr_instruction->base, + return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, create_const_enum(enum_type, &field->enum_field->value), enum_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); } } const char *container_name = (child_type == ira->codegen->root_import) ? "root source file" : buf_ptr(buf_sprintf("container '%s'", buf_ptr(&child_type->name))); - ir_add_error(ira, &field_ptr_instruction->base, + ir_add_error(ira, &field_ptr_instruction->base.base, buf_sprintf("%s has no member called '%s'", container_name, buf_ptr(field_name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else if (child_type->id == ZigTypeIdErrorSet) { ErrorTableEntry *err_entry; ZigType *err_set_type; @@ -20520,7 +21514,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc err_entry = existing_entry->value; } else { err_entry = allocate(1); - err_entry->decl_node = field_ptr_instruction->base.source_node; + err_entry->decl_node = field_ptr_instruction->base.base.source_node; buf_init_from_buf(&err_entry->name, field_name); size_t error_value_count = ira->codegen->errors_by_index.length; assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)ira->codegen->err_tag_type->data.integral.bit_count)); @@ -20530,19 +21524,19 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc } if (err_entry->set_with_only_this_in_it == nullptr) { err_entry->set_with_only_this_in_it = make_err_set_with_one_item(ira->codegen, - field_ptr_instruction->base.scope, field_ptr_instruction->base.source_node, + field_ptr_instruction->base.base.scope, field_ptr_instruction->base.base.source_node, err_entry); } err_set_type = err_entry->set_with_only_this_in_it; } else { - if (!resolve_inferred_error_set(ira->codegen, child_type, field_ptr_instruction->base.source_node)) { - return ira->codegen->invalid_instruction; + if (!resolve_inferred_error_set(ira->codegen, child_type, field_ptr_instruction->base.base.source_node)) { + return ira->codegen->invalid_inst_gen; } err_entry = find_err_table_entry(child_type, field_name); if (err_entry == nullptr) { - ir_add_error(ira, &field_ptr_instruction->base, + ir_add_error(ira, &field_ptr_instruction->base.base, buf_sprintf("no error named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&child_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } err_set_type = child_type; } @@ -20553,13 +21547,13 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc bool ptr_is_const = true; bool ptr_is_volatile = false; - return ir_get_const_ptr(ira, &field_ptr_instruction->base, const_val, + return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, const_val, err_set_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); } else if (child_type->id == ZigTypeIdInt) { if (buf_eql_str(field_name, "bit_count")) { bool ptr_is_const = true; bool ptr_is_volatile = false; - return ir_get_const_ptr(ira, &field_ptr_instruction->base, + return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int, child_type->data.integral.bit_count, false), ira->codegen->builtin_types.entry_num_lit_int, @@ -20567,36 +21561,36 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc } else if (buf_eql_str(field_name, "is_signed")) { bool ptr_is_const = true; bool ptr_is_volatile = false; - return ir_get_const_ptr(ira, &field_ptr_instruction->base, + return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, create_const_bool(ira->codegen, child_type->data.integral.is_signed), ira->codegen->builtin_types.entry_bool, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); } else { - ir_add_error(ira, &field_ptr_instruction->base, + ir_add_error(ira, &field_ptr_instruction->base.base, buf_sprintf("type '%s' has no member called '%s'", buf_ptr(&child_type->name), buf_ptr(field_name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } else if (child_type->id == ZigTypeIdFloat) { if (buf_eql_str(field_name, "bit_count")) { bool ptr_is_const = true; bool ptr_is_volatile = false; - return ir_get_const_ptr(ira, &field_ptr_instruction->base, + return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int, child_type->data.floating.bit_count, false), ira->codegen->builtin_types.entry_num_lit_int, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); } else { - ir_add_error(ira, &field_ptr_instruction->base, + ir_add_error(ira, &field_ptr_instruction->base.base, buf_sprintf("type '%s' has no member called '%s'", buf_ptr(&child_type->name), buf_ptr(field_name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } else if (child_type->id == ZigTypeIdPointer) { if (buf_eql_str(field_name, "Child")) { bool ptr_is_const = true; bool ptr_is_volatile = false; - return ir_get_const_ptr(ira, &field_ptr_instruction->base, + return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, create_const_type(ira->codegen, child_type->data.pointer.child_type), ira->codegen->builtin_types.entry_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); @@ -20606,75 +21600,75 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc if ((err = type_resolve(ira->codegen, child_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - return ir_get_const_ptr(ira, &field_ptr_instruction->base, + return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int, get_ptr_align(ira->codegen, child_type), false), ira->codegen->builtin_types.entry_num_lit_int, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); } else { - ir_add_error(ira, &field_ptr_instruction->base, + ir_add_error(ira, &field_ptr_instruction->base.base, buf_sprintf("type '%s' has no member called '%s'", buf_ptr(&child_type->name), buf_ptr(field_name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } else if (child_type->id == ZigTypeIdArray) { if (buf_eql_str(field_name, "Child")) { bool ptr_is_const = true; bool ptr_is_volatile = false; - return ir_get_const_ptr(ira, &field_ptr_instruction->base, + return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, create_const_type(ira->codegen, child_type->data.array.child_type), ira->codegen->builtin_types.entry_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); } else if (buf_eql_str(field_name, "len")) { bool ptr_is_const = true; bool ptr_is_volatile = false; - return ir_get_const_ptr(ira, &field_ptr_instruction->base, + return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int, child_type->data.array.len, false), ira->codegen->builtin_types.entry_num_lit_int, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); } else { - ir_add_error(ira, &field_ptr_instruction->base, + ir_add_error(ira, &field_ptr_instruction->base.base, buf_sprintf("type '%s' has no member called '%s'", buf_ptr(&child_type->name), buf_ptr(field_name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } else if (child_type->id == ZigTypeIdErrorUnion) { if (buf_eql_str(field_name, "Payload")) { bool ptr_is_const = true; bool ptr_is_volatile = false; - return ir_get_const_ptr(ira, &field_ptr_instruction->base, + return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, create_const_type(ira->codegen, child_type->data.error_union.payload_type), ira->codegen->builtin_types.entry_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); } else if (buf_eql_str(field_name, "ErrorSet")) { bool ptr_is_const = true; bool ptr_is_volatile = false; - return ir_get_const_ptr(ira, &field_ptr_instruction->base, + return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, create_const_type(ira->codegen, child_type->data.error_union.err_set_type), ira->codegen->builtin_types.entry_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); } else { - ir_add_error(ira, &field_ptr_instruction->base, + ir_add_error(ira, &field_ptr_instruction->base.base, buf_sprintf("type '%s' has no member called '%s'", buf_ptr(&child_type->name), buf_ptr(field_name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } else if (child_type->id == ZigTypeIdOptional) { if (buf_eql_str(field_name, "Child")) { bool ptr_is_const = true; bool ptr_is_volatile = false; - return ir_get_const_ptr(ira, &field_ptr_instruction->base, + return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, create_const_type(ira->codegen, child_type->data.maybe.child_type), ira->codegen->builtin_types.entry_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); } else { - ir_add_error(ira, &field_ptr_instruction->base, + ir_add_error(ira, &field_ptr_instruction->base.base, buf_sprintf("type '%s' has no member called '%s'", buf_ptr(&child_type->name), buf_ptr(field_name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } else if (child_type->id == ZigTypeIdFn) { if (buf_eql_str(field_name, "ReturnType")) { @@ -20682,121 +21676,121 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc // Return type can only ever be null, if the function is generic assert(child_type->data.fn.is_generic); - ir_add_error(ira, &field_ptr_instruction->base, + ir_add_error(ira, &field_ptr_instruction->base.base, buf_sprintf("ReturnType has not been resolved because '%s' is generic", buf_ptr(&child_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } bool ptr_is_const = true; bool ptr_is_volatile = false; - return ir_get_const_ptr(ira, &field_ptr_instruction->base, + return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, create_const_type(ira->codegen, child_type->data.fn.fn_type_id.return_type), ira->codegen->builtin_types.entry_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); } else if (buf_eql_str(field_name, "is_var_args")) { bool ptr_is_const = true; bool ptr_is_volatile = false; - return ir_get_const_ptr(ira, &field_ptr_instruction->base, + return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, create_const_bool(ira->codegen, child_type->data.fn.fn_type_id.is_var_args), ira->codegen->builtin_types.entry_bool, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); } else if (buf_eql_str(field_name, "arg_count")) { bool ptr_is_const = true; bool ptr_is_volatile = false; - return ir_get_const_ptr(ira, &field_ptr_instruction->base, + return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, create_const_usize(ira->codegen, child_type->data.fn.fn_type_id.param_count), ira->codegen->builtin_types.entry_usize, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0); } else { - ir_add_error(ira, &field_ptr_instruction->base, + ir_add_error(ira, &field_ptr_instruction->base.base, buf_sprintf("type '%s' has no member called '%s'", buf_ptr(&child_type->name), buf_ptr(field_name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } else { - ir_add_error(ira, &field_ptr_instruction->base, + ir_add_error(ira, &field_ptr_instruction->base.base, buf_sprintf("type '%s' does not support field access", buf_ptr(&child_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } else if (field_ptr_instruction->initializing) { - ir_add_error(ira, &field_ptr_instruction->base, + ir_add_error(ira, &field_ptr_instruction->base.base, buf_sprintf("type '%s' does not support struct initialization syntax", buf_ptr(&container_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else { - ir_add_error_node(ira, field_ptr_instruction->base.source_node, + ir_add_error_node(ira, field_ptr_instruction->base.base.source_node, buf_sprintf("type '%s' does not support field access", buf_ptr(&container_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } -static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *instruction) { - IrInstruction *ptr = instruction->ptr->child; +static IrInstGen *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstSrcStorePtr *instruction) { + IrInstGen *ptr = instruction->ptr->child; if (type_is_invalid(ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *value = instruction->value->child; + IrInstGen *value = instruction->value->child; if (type_is_invalid(value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_analyze_store_ptr(ira, &instruction->base, ptr, value, instruction->allow_write_through_const); + return ir_analyze_store_ptr(ira, &instruction->base.base, ptr, value, instruction->allow_write_through_const); } -static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *instruction) { - IrInstruction *ptr = instruction->ptr->child; +static IrInstGen *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstSrcLoadPtr *instruction) { + IrInstGen *ptr = instruction->ptr->child; if (type_is_invalid(ptr->value->type)) - return ira->codegen->invalid_instruction; - return ir_get_deref(ira, &instruction->base, ptr, nullptr); + return ira->codegen->invalid_inst_gen; + return ir_get_deref(ira, &instruction->base.base, ptr, nullptr); } -static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) { - IrInstruction *expr_value = typeof_instruction->value->child; +static IrInstGen *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstSrcTypeOf *typeof_instruction) { + IrInstGen *expr_value = typeof_instruction->value->child; ZigType *type_entry = expr_value->value->type; if (type_is_invalid(type_entry)) - return ira->codegen->invalid_instruction; - return ir_const_type(ira, &typeof_instruction->base, type_entry); + return ira->codegen->invalid_inst_gen; + return ir_const_type(ira, &typeof_instruction->base.base, type_entry); } -static IrInstruction *ir_analyze_instruction_set_cold(IrAnalyze *ira, IrInstructionSetCold *instruction) { +static IrInstGen *ir_analyze_instruction_set_cold(IrAnalyze *ira, IrInstSrcSetCold *instruction) { if (ira->new_irb.exec->is_inline) { // ignore setCold when running functions at compile time - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } - IrInstruction *is_cold_value = instruction->is_cold->child; + IrInstGen *is_cold_value = instruction->is_cold->child; bool want_cold; if (!ir_resolve_bool(ira, is_cold_value, &want_cold)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - ZigFn *fn_entry = scope_fn_entry(instruction->base.scope); + ZigFn *fn_entry = scope_fn_entry(instruction->base.base.scope); if (fn_entry == nullptr) { - ir_add_error(ira, &instruction->base, buf_sprintf("@setCold outside function")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("@setCold outside function")); + return ira->codegen->invalid_inst_gen; } if (fn_entry->set_cold_node != nullptr) { - ErrorMsg *msg = ir_add_error(ira, &instruction->base, buf_sprintf("cold set twice in same function")); + ErrorMsg *msg = ir_add_error(ira, &instruction->base.base, buf_sprintf("cold set twice in same function")); add_error_note(ira->codegen, msg, fn_entry->set_cold_node, buf_sprintf("first set here")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - fn_entry->set_cold_node = instruction->base.source_node; + fn_entry->set_cold_node = instruction->base.base.source_node; fn_entry->is_cold = want_cold; - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } -static IrInstruction *ir_analyze_instruction_set_runtime_safety(IrAnalyze *ira, - IrInstructionSetRuntimeSafety *set_runtime_safety_instruction) +static IrInstGen *ir_analyze_instruction_set_runtime_safety(IrAnalyze *ira, + IrInstSrcSetRuntimeSafety *set_runtime_safety_instruction) { if (ira->new_irb.exec->is_inline) { // ignore setRuntimeSafety when running functions at compile time - return ir_const_void(ira, &set_runtime_safety_instruction->base); + return ir_const_void(ira, &set_runtime_safety_instruction->base.base); } bool *safety_off_ptr; AstNode **safety_set_node_ptr; - Scope *scope = set_runtime_safety_instruction->base.scope; + Scope *scope = set_runtime_safety_instruction->base.base.scope; while (scope != nullptr) { if (scope->id == ScopeIdBlock) { ScopeBlock *block_scope = (ScopeBlock *)scope; @@ -20822,36 +21816,36 @@ static IrInstruction *ir_analyze_instruction_set_runtime_safety(IrAnalyze *ira, } assert(scope != nullptr); - IrInstruction *safety_on_value = set_runtime_safety_instruction->safety_on->child; + IrInstGen *safety_on_value = set_runtime_safety_instruction->safety_on->child; bool want_runtime_safety; if (!ir_resolve_bool(ira, safety_on_value, &want_runtime_safety)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - AstNode *source_node = set_runtime_safety_instruction->base.source_node; + AstNode *source_node = set_runtime_safety_instruction->base.base.source_node; if (*safety_set_node_ptr) { ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("runtime safety set twice for same scope")); add_error_note(ira->codegen, msg, *safety_set_node_ptr, buf_sprintf("first set here")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } *safety_set_node_ptr = source_node; *safety_off_ptr = !want_runtime_safety; - return ir_const_void(ira, &set_runtime_safety_instruction->base); + return ir_const_void(ira, &set_runtime_safety_instruction->base.base); } -static IrInstruction *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, - IrInstructionSetFloatMode *instruction) +static IrInstGen *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, + IrInstSrcSetFloatMode *instruction) { if (ira->new_irb.exec->is_inline) { // ignore setFloatMode when running functions at compile time - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } bool *fast_math_on_ptr; AstNode **fast_math_set_node_ptr; - Scope *scope = instruction->base.scope; + Scope *scope = instruction->base.base.scope; while (scope != nullptr) { if (scope->id == ScopeIdBlock) { ScopeBlock *block_scope = (ScopeBlock *)scope; @@ -20877,42 +21871,38 @@ static IrInstruction *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, } assert(scope != nullptr); - IrInstruction *float_mode_value = instruction->mode_value->child; + IrInstGen *float_mode_value = instruction->mode_value->child; FloatMode float_mode_scalar; if (!ir_resolve_float_mode(ira, float_mode_value, &float_mode_scalar)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - AstNode *source_node = instruction->base.source_node; + AstNode *source_node = instruction->base.base.source_node; if (*fast_math_set_node_ptr) { ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("float mode set twice for same scope")); add_error_note(ira->codegen, msg, *fast_math_set_node_ptr, buf_sprintf("first set here")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } *fast_math_set_node_ptr = source_node; *fast_math_on_ptr = (float_mode_scalar == FloatModeOptimized); - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } -static IrInstruction *ir_analyze_instruction_any_frame_type(IrAnalyze *ira, - IrInstructionAnyFrameType *instruction) -{ +static IrInstGen *ir_analyze_instruction_any_frame_type(IrAnalyze *ira, IrInstSrcAnyFrameType *instruction) { ZigType *payload_type = nullptr; if (instruction->payload_type != nullptr) { payload_type = ir_resolve_type(ira, instruction->payload_type->child); if (type_is_invalid(payload_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *any_frame_type = get_any_frame_type(ira->codegen, payload_type); - return ir_const_type(ira, &instruction->base, any_frame_type); + return ir_const_type(ira, &instruction->base.base, any_frame_type); } -static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, - IrInstructionSliceType *slice_type_instruction) -{ - IrInstruction *result = ir_const(ira, &slice_type_instruction->base, ira->codegen->builtin_types.entry_type); +static IrInstGen *ir_analyze_instruction_slice_type(IrAnalyze *ira, IrInstSrcSliceType *slice_type_instruction) { + IrInstGen *result = ir_const(ira, &slice_type_instruction->base.base, ira->codegen->builtin_types.entry_type); result->value->special = ConstValSpecialLazy; LazyValueSliceType *lazy_slice_type = allocate(1, "LazyValueSliceType"); @@ -20923,18 +21913,18 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, if (slice_type_instruction->align_value != nullptr) { lazy_slice_type->align_inst = slice_type_instruction->align_value->child; if (ir_resolve_const(ira, lazy_slice_type->align_inst, LazyOk) == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (slice_type_instruction->sentinel != nullptr) { lazy_slice_type->sentinel = slice_type_instruction->sentinel->child; if (ir_resolve_const(ira, lazy_slice_type->sentinel, LazyOk) == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } lazy_slice_type->elem_type = slice_type_instruction->child_type->child; if (ir_resolve_type_lazy(ira, lazy_slice_type->elem_type) == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; lazy_slice_type->is_const = slice_type_instruction->is_const; lazy_slice_type->is_volatile = slice_type_instruction->is_volatile; @@ -20943,31 +21933,31 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, return result; } -static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAsmSrc *asm_instruction) { +static IrInstGen *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstSrcAsm *asm_instruction) { Error err; - assert(asm_instruction->base.source_node->type == NodeTypeAsmExpr); + assert(asm_instruction->base.base.source_node->type == NodeTypeAsmExpr); - AstNode *node = asm_instruction->base.source_node; - AstNodeAsmExpr *asm_expr = &asm_instruction->base.source_node->data.asm_expr; + AstNode *node = asm_instruction->base.base.source_node; + AstNodeAsmExpr *asm_expr = &asm_instruction->base.base.source_node->data.asm_expr; Buf *template_buf = ir_resolve_str(ira, asm_instruction->asm_template->child); if (template_buf == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (asm_instruction->is_global) { buf_append_char(&ira->codegen->global_asm, '\n'); buf_append_buf(&ira->codegen->global_asm, template_buf); - return ir_const_void(ira, &asm_instruction->base); + return ir_const_void(ira, &asm_instruction->base.base); } - if (!ir_emit_global_runtime_side_effect(ira, &asm_instruction->base)) - return ira->codegen->invalid_instruction; + if (!ir_emit_global_runtime_side_effect(ira, &asm_instruction->base.base)) + return ira->codegen->invalid_inst_gen; ZigList tok_list = {}; if ((err = parse_asm_template(ira, node, template_buf, &tok_list))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } for (size_t token_i = 0; token_i < tok_list.length; token_i += 1) { @@ -20981,15 +21971,15 @@ static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAs add_node_error(ira->codegen, node, buf_sprintf("could not find '%.*s' in the inputs or outputs", len, ptr)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } } // TODO validate the output types and variable types - IrInstruction **input_list = allocate(asm_expr->input_list.length); - IrInstruction **output_types = allocate(asm_expr->output_list.length); + IrInstGen **input_list = allocate(asm_expr->input_list.length); + IrInstGen **output_types = allocate(asm_expr->output_list.length); ZigType *return_type = ira->codegen->builtin_types.entry_void; for (size_t i = 0; i < asm_expr->output_list.length; i += 1) { @@ -20998,39 +21988,34 @@ static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAs output_types[i] = asm_instruction->output_types[i]->child; return_type = ir_resolve_type(ira, output_types[i]); if (type_is_invalid(return_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } for (size_t i = 0; i < asm_expr->input_list.length; i += 1) { - IrInstruction *const input_value = asm_instruction->input_list[i]->child; + IrInstGen *const input_value = asm_instruction->input_list[i]->child; if (type_is_invalid(input_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (instr_is_comptime(input_value) && (input_value->value->type->id == ZigTypeIdComptimeInt || input_value->value->type->id == ZigTypeIdComptimeFloat)) { - ir_add_error_node(ira, input_value->source_node, + ir_add_error(ira, &input_value->base, buf_sprintf("expected sized integer or sized float, found %s", buf_ptr(&input_value->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } input_list[i] = input_value; } - IrInstruction *result = ir_build_asm_gen(ira, - asm_instruction->base.scope, asm_instruction->base.source_node, + return ir_build_asm_gen(ira, &asm_instruction->base.base, template_buf, tok_list.items, tok_list.length, input_list, output_types, asm_instruction->output_vars, asm_instruction->return_count, - asm_instruction->has_side_effects); - result->value->type = return_type; - return result; + asm_instruction->has_side_effects, return_type); } -static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira, - IrInstructionArrayType *array_type_instruction) -{ - IrInstruction *result = ir_const(ira, &array_type_instruction->base, ira->codegen->builtin_types.entry_type); +static IrInstGen *ir_analyze_instruction_array_type(IrAnalyze *ira, IrInstSrcArrayType *array_type_instruction) { + IrInstGen *result = ir_const(ira, &array_type_instruction->base.base, ira->codegen->builtin_types.entry_type); result->value->special = ConstValSpecialLazy; LazyValueArrayType *lazy_array_type = allocate(1, "LazyValueArrayType"); @@ -21040,22 +22025,22 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira, lazy_array_type->elem_type = array_type_instruction->child_type->child; if (ir_resolve_type_lazy(ira, lazy_array_type->elem_type) == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (!ir_resolve_usize(ira, array_type_instruction->size->child, &lazy_array_type->length)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (array_type_instruction->sentinel != nullptr) { lazy_array_type->sentinel = array_type_instruction->sentinel->child; if (ir_resolve_const(ira, lazy_array_type->sentinel, LazyOk) == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } return result; } -static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, IrInstructionSizeOf *instruction) { - IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_num_lit_int); +static IrInstGen *ir_analyze_instruction_size_of(IrAnalyze *ira, IrInstSrcSizeOf *instruction) { + IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_num_lit_int); result->value->special = ConstValSpecialLazy; LazyValueSizeOf *lazy_size_of = allocate(1, "LazyValueSizeOf"); @@ -21066,19 +22051,19 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, IrInstructi lazy_size_of->target_type = instruction->type_value->child; if (ir_resolve_type_lazy(ira, lazy_size_of->target_type) == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return result; } -static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value) { +static IrInstGen *ir_analyze_test_non_null(IrAnalyze *ira, IrInst *source_inst, IrInstGen *value) { ZigType *type_entry = value->value->type; if (type_entry->id == ZigTypeIdPointer && type_entry->data.pointer.allow_zero) { if (instr_is_comptime(value)) { ZigValue *c_ptr_val = ir_resolve_const(ira, value, UndefOk); if (c_ptr_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (c_ptr_val->special == ConstValSpecialUndef) return ir_const_undef(ira, source_inst, ira->codegen->builtin_types.entry_bool); bool is_null = c_ptr_val->data.x_ptr.special == ConstPtrSpecialNull || @@ -21087,25 +22072,19 @@ static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *so return ir_const_bool(ira, source_inst, !is_null); } - IrInstruction *result = ir_build_test_nonnull(&ira->new_irb, - source_inst->scope, source_inst->source_node, value); - result->value->type = ira->codegen->builtin_types.entry_bool; - return result; + return ir_build_test_non_null_gen(ira, source_inst, value); } else if (type_entry->id == ZigTypeIdOptional) { if (instr_is_comptime(value)) { ZigValue *maybe_val = ir_resolve_const(ira, value, UndefOk); if (maybe_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (maybe_val->special == ConstValSpecialUndef) return ir_const_undef(ira, source_inst, ira->codegen->builtin_types.entry_bool); return ir_const_bool(ira, source_inst, !optional_value_is_null(maybe_val)); } - IrInstruction *result = ir_build_test_nonnull(&ira->new_irb, - source_inst->scope, source_inst->source_node, value); - result->value->type = ira->codegen->builtin_types.entry_bool; - return result; + return ir_build_test_non_null_gen(ira, source_inst, value); } else if (type_entry->id == ZigTypeIdNull) { return ir_const_bool(ira, source_inst, false); } else { @@ -21113,53 +22092,53 @@ static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *so } } -static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) { - IrInstruction *value = instruction->value->child; +static IrInstGen *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstSrcTestNonNull *instruction) { + IrInstGen *value = instruction->value->child; if (type_is_invalid(value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_analyze_test_non_null(ira, &instruction->base, value); + return ir_analyze_test_non_null(ira, &instruction->base.base, value); } -static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *base_ptr, bool safety_check_on, bool initializing) +static IrInstGen *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *base_ptr, bool safety_check_on, bool initializing) { Error err; ZigType *type_entry = get_ptr_elem_type(ira->codegen, base_ptr); if (type_is_invalid(type_entry)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (type_entry->id == ZigTypeIdPointer && type_entry->data.pointer.ptr_len == PtrLenC) { if (instr_is_comptime(base_ptr)) { ZigValue *val = ir_resolve_const(ira, base_ptr, UndefBad); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) { ZigValue *c_ptr_val = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node); if (c_ptr_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; bool is_null = c_ptr_val->data.x_ptr.special == ConstPtrSpecialNull || (c_ptr_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr && c_ptr_val->data.x_ptr.data.hard_coded_addr.addr == 0); if (is_null) { ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } return base_ptr; } } if (!safety_check_on) return base_ptr; - IrInstruction *c_ptr_val = ir_get_deref(ira, source_instr, base_ptr, nullptr); + IrInstGen *c_ptr_val = ir_get_deref(ira, source_instr, base_ptr, nullptr); ir_build_assert_non_null(ira, source_instr, c_ptr_val); return base_ptr; } if (type_entry->id != ZigTypeIdOptional) { - ir_add_error_node(ira, base_ptr->source_node, + ir_add_error(ira, &base_ptr->base, buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *child_type = type_entry->data.maybe.child_type; @@ -21172,16 +22151,16 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr if (instr_is_comptime(base_ptr)) { ZigValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad); if (ptr_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) { ZigValue *optional_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); if (optional_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (initializing) { switch (type_has_one_possible_value(ira->codegen, child_type)) { case OnePossibleValueInvalid: - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case OnePossibleValueNo: if (!same_comptime_repr) { ZigValue *payload_val = create_const_vals(1); @@ -21209,18 +22188,17 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr } else { if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, source_instr->source_node, optional_val, UndefBad))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (optional_value_is_null(optional_val)) { ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } - IrInstruction *result; + IrInstGen *result; if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) { - result = ir_build_optional_unwrap_ptr(&ira->new_irb, source_instr->scope, - source_instr->source_node, base_ptr, false, initializing); - result->value->type = result_type; + result = ir_build_optional_unwrap_ptr_gen(ira, source_instr, base_ptr, false, + initializing, result_type); result->value->special = ConstValSpecialStatic; } else { result = ir_const(ira, source_instr, result_type); @@ -21230,7 +22208,7 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr result_val->data.x_ptr.mut = ptr_val->data.x_ptr.mut; switch (type_has_one_possible_value(ira->codegen, child_type)) { case OnePossibleValueInvalid: - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case OnePossibleValueNo: if (same_comptime_repr) { result_val->data.x_ptr.data.ref.pointee = optional_val; @@ -21248,135 +22226,120 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr } } - IrInstruction *result = ir_build_optional_unwrap_ptr(&ira->new_irb, source_instr->scope, - source_instr->source_node, base_ptr, safety_check_on, initializing); - result->value->type = result_type; - return result; + return ir_build_optional_unwrap_ptr_gen(ira, source_instr, base_ptr, safety_check_on, + initializing, result_type); } -static IrInstruction *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira, - IrInstructionOptionalUnwrapPtr *instruction) +static IrInstGen *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira, + IrInstSrcOptionalUnwrapPtr *instruction) { - IrInstruction *base_ptr = instruction->base_ptr->child; + IrInstGen *base_ptr = instruction->base_ptr->child; if (type_is_invalid(base_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_analyze_unwrap_optional_payload(ira, &instruction->base, base_ptr, + return ir_analyze_unwrap_optional_payload(ira, &instruction->base.base, base_ptr, instruction->safety_check_on, false); } -static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *instruction) { +static IrInstGen *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstSrcCtz *instruction) { ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); if (type_is_invalid(int_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *op = ir_implicit_cast(ira, instruction->op->child, int_type); + IrInstGen *op = ir_implicit_cast(ira, instruction->op->child, int_type); if (type_is_invalid(op->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (int_type->data.integral.bit_count == 0) - return ir_const_unsigned(ira, &instruction->base, 0); + return ir_const_unsigned(ira, &instruction->base.base, 0); if (instr_is_comptime(op)) { ZigValue *val = ir_resolve_const(ira, op, UndefOk); if (val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (val->special == ConstValSpecialUndef) - return ir_const_undef(ira, &instruction->base, ira->codegen->builtin_types.entry_num_lit_int); + return ir_const_undef(ira, &instruction->base.base, ira->codegen->builtin_types.entry_num_lit_int); size_t result_usize = bigint_ctz(&op->value->data.x_bigint, int_type->data.integral.bit_count); - return ir_const_unsigned(ira, &instruction->base, result_usize); + return ir_const_unsigned(ira, &instruction->base.base, result_usize); } ZigType *return_type = get_smallest_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count); - IrInstruction *result = ir_build_ctz(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, nullptr, op); - result->value->type = return_type; - return result; + return ir_build_ctz_gen(ira, &instruction->base.base, return_type, op); } -static IrInstruction *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstructionClz *instruction) { +static IrInstGen *ir_analyze_instruction_clz(IrAnalyze *ira, IrInstSrcClz *instruction) { ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); if (type_is_invalid(int_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *op = ir_implicit_cast(ira, instruction->op->child, int_type); + IrInstGen *op = ir_implicit_cast(ira, instruction->op->child, int_type); if (type_is_invalid(op->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (int_type->data.integral.bit_count == 0) - return ir_const_unsigned(ira, &instruction->base, 0); + return ir_const_unsigned(ira, &instruction->base.base, 0); if (instr_is_comptime(op)) { ZigValue *val = ir_resolve_const(ira, op, UndefOk); if (val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (val->special == ConstValSpecialUndef) - return ir_const_undef(ira, &instruction->base, ira->codegen->builtin_types.entry_num_lit_int); + return ir_const_undef(ira, &instruction->base.base, ira->codegen->builtin_types.entry_num_lit_int); size_t result_usize = bigint_clz(&op->value->data.x_bigint, int_type->data.integral.bit_count); - return ir_const_unsigned(ira, &instruction->base, result_usize); + return ir_const_unsigned(ira, &instruction->base.base, result_usize); } ZigType *return_type = get_smallest_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count); - IrInstruction *result = ir_build_clz(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, nullptr, op); - result->value->type = return_type; - return result; + return ir_build_clz_gen(ira, &instruction->base.base, return_type, op); } -static IrInstruction *ir_analyze_instruction_pop_count(IrAnalyze *ira, IrInstructionPopCount *instruction) { +static IrInstGen *ir_analyze_instruction_pop_count(IrAnalyze *ira, IrInstSrcPopCount *instruction) { ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); if (type_is_invalid(int_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *op = ir_implicit_cast(ira, instruction->op->child, int_type); + IrInstGen *op = ir_implicit_cast(ira, instruction->op->child, int_type); if (type_is_invalid(op->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (int_type->data.integral.bit_count == 0) - return ir_const_unsigned(ira, &instruction->base, 0); + return ir_const_unsigned(ira, &instruction->base.base, 0); if (instr_is_comptime(op)) { ZigValue *val = ir_resolve_const(ira, op, UndefOk); if (val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (val->special == ConstValSpecialUndef) - return ir_const_undef(ira, &instruction->base, ira->codegen->builtin_types.entry_num_lit_int); + return ir_const_undef(ira, &instruction->base.base, ira->codegen->builtin_types.entry_num_lit_int); if (bigint_cmp_zero(&val->data.x_bigint) != CmpLT) { size_t result = bigint_popcount_unsigned(&val->data.x_bigint); - return ir_const_unsigned(ira, &instruction->base, result); + return ir_const_unsigned(ira, &instruction->base.base, result); } size_t result = bigint_popcount_signed(&val->data.x_bigint, int_type->data.integral.bit_count); - return ir_const_unsigned(ira, &instruction->base, result); + return ir_const_unsigned(ira, &instruction->base.base, result); } ZigType *return_type = get_smallest_unsigned_int_type(ira->codegen, int_type->data.integral.bit_count); - IrInstruction *result = ir_build_pop_count(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, nullptr, op); - result->value->type = return_type; - return result; + return ir_build_pop_count_gen(ira, &instruction->base.base, return_type, op); } -static IrInstruction *ir_analyze_union_tag(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value) { +static IrInstGen *ir_analyze_union_tag(IrAnalyze *ira, IrInst* source_instr, IrInstGen *value, bool is_gen) { if (type_is_invalid(value->value->type)) - return ira->codegen->invalid_instruction; - - if (value->value->type->id == ZigTypeIdEnum) { - return value; - } + return ira->codegen->invalid_inst_gen; if (value->value->type->id != ZigTypeIdUnion) { - ir_add_error(ira, value, + ir_add_error(ira, &value->base, buf_sprintf("expected enum or union type, found '%s'", buf_ptr(&value->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - if (!value->value->type->data.unionation.have_explicit_tag_type && !source_instr->is_gen) { + if (!value->value->type->data.unionation.have_explicit_tag_type && !is_gen) { ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("union has no associated enum")); if (value->value->type->data.unionation.decl_node != nullptr) { add_error_note(ira->codegen, msg, value->value->type->data.unionation.decl_node, buf_sprintf("declared here")); } - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *tag_type = value->value->type->data.unionation.tag_type; @@ -21385,9 +22348,9 @@ static IrInstruction *ir_analyze_union_tag(IrAnalyze *ira, IrInstruction *source if (instr_is_comptime(value)) { ZigValue *val = ir_resolve_const(ira, value, UndefBad); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, + IrInstGenConst *const_instruction = ir_create_inst_gen(&ira->new_irb, source_instr->scope, source_instr->source_node); const_instruction->base.value->type = tag_type; const_instruction->base.value->special = ConstValSpecialStatic; @@ -21395,15 +22358,13 @@ static IrInstruction *ir_analyze_union_tag(IrAnalyze *ira, IrInstruction *source return &const_instruction->base; } - IrInstruction *result = ir_build_union_tag(&ira->new_irb, source_instr->scope, source_instr->source_node, value); - result->value->type = tag_type; - return result; + return ir_build_union_tag(ira, source_instr, value, tag_type); } -static IrInstruction *ir_analyze_instruction_switch_br(IrAnalyze *ira, - IrInstructionSwitchBr *switch_br_instruction) +static IrInstGen *ir_analyze_instruction_switch_br(IrAnalyze *ira, + IrInstSrcSwitchBr *switch_br_instruction) { - IrInstruction *target_value = switch_br_instruction->target_value->child; + IrInstGen *target_value = switch_br_instruction->target_value->child; if (type_is_invalid(target_value->value->type)) return ir_unreach_error(ira); @@ -21418,27 +22379,21 @@ static IrInstruction *ir_analyze_instruction_switch_br(IrAnalyze *ira, bool is_comptime; if (!ir_resolve_comptime(ira, switch_br_instruction->is_comptime->child, &is_comptime)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (is_comptime || instr_is_comptime(target_value)) { ZigValue *target_val = ir_resolve_const(ira, target_value, UndefBad); if (!target_val) return ir_unreach_error(ira); - IrBasicBlock *old_dest_block = switch_br_instruction->else_block; + IrBasicBlockSrc *old_dest_block = switch_br_instruction->else_block; for (size_t i = 0; i < case_count; i += 1) { - IrInstructionSwitchBrCase *old_case = &switch_br_instruction->cases[i]; - IrInstruction *case_value = old_case->value->child; + IrInstSrcSwitchBrCase *old_case = &switch_br_instruction->cases[i]; + IrInstGen *case_value = old_case->value->child; if (type_is_invalid(case_value->value->type)) return ir_unreach_error(ira); - if (case_value->value->type->id == ZigTypeIdEnum) { - case_value = ir_analyze_union_tag(ira, &switch_br_instruction->base, case_value); - if (type_is_invalid(case_value->value->type)) - return ir_unreach_error(ira); - } - - IrInstruction *casted_case_value = ir_implicit_cast(ira, case_value, target_value->value->type); + IrInstGen *casted_case_value = ir_implicit_cast(ira, case_value, target_value->value->type); if (type_is_invalid(casted_case_value->value->type)) return ir_unreach_error(ira); @@ -21453,23 +22408,20 @@ static IrInstruction *ir_analyze_instruction_switch_br(IrAnalyze *ira, } if (is_comptime || old_dest_block->ref_count == 1) { - return ir_inline_bb(ira, &switch_br_instruction->base, old_dest_block); + return ir_inline_bb(ira, &switch_br_instruction->base.base, old_dest_block); } else { - IrBasicBlock *new_dest_block = ir_get_new_bb(ira, old_dest_block, &switch_br_instruction->base); - IrInstruction *result = ir_build_br(&ira->new_irb, - switch_br_instruction->base.scope, switch_br_instruction->base.source_node, - new_dest_block, nullptr); - result->value->type = ira->codegen->builtin_types.entry_unreachable; + IrBasicBlockGen *new_dest_block = ir_get_new_bb(ira, old_dest_block, &switch_br_instruction->base.base); + IrInstGen *result = ir_build_br_gen(ira, &switch_br_instruction->base.base, new_dest_block); return ir_finish_anal(ira, result); } } - IrInstructionSwitchBrCase *cases = allocate(case_count); + IrInstGenSwitchBrCase *cases = allocate(case_count); for (size_t i = 0; i < case_count; i += 1) { - IrInstructionSwitchBrCase *old_case = &switch_br_instruction->cases[i]; - IrInstructionSwitchBrCase *new_case = &cases[i]; - new_case->block = ir_get_new_bb(ira, old_case->block, &switch_br_instruction->base); - new_case->value = ira->codegen->invalid_instruction; + IrInstSrcSwitchBrCase *old_case = &switch_br_instruction->cases[i]; + IrInstGenSwitchBrCase *new_case = &cases[i]; + new_case->block = ir_get_new_bb(ira, old_case->block, &switch_br_instruction->base.base); + new_case->value = ira->codegen->invalid_inst_gen; // Calling ir_get_new_bb set the ref_instruction on the new basic block. // However a switch br may branch to the same basic block which would trigger an @@ -21477,18 +22429,12 @@ static IrInstruction *ir_analyze_instruction_switch_br(IrAnalyze *ira, // it back after the loop. new_case->block->ref_instruction = nullptr; - IrInstruction *old_value = old_case->value; - IrInstruction *new_value = old_value->child; + IrInstSrc *old_value = old_case->value; + IrInstGen *new_value = old_value->child; if (type_is_invalid(new_value->value->type)) continue; - if (new_value->value->type->id == ZigTypeIdEnum) { - new_value = ir_analyze_union_tag(ira, &switch_br_instruction->base, new_value); - if (type_is_invalid(new_value->value->type)) - continue; - } - - IrInstruction *casted_new_value = ir_implicit_cast(ira, new_value, target_value->value->type); + IrInstGen *casted_new_value = ir_implicit_cast(ira, new_value, target_value->value->type); if (type_is_invalid(casted_new_value->value->type)) continue; @@ -21499,47 +22445,45 @@ static IrInstruction *ir_analyze_instruction_switch_br(IrAnalyze *ira, } for (size_t i = 0; i < case_count; i += 1) { - IrInstructionSwitchBrCase *new_case = &cases[i]; - if (new_case->value == ira->codegen->invalid_instruction) + IrInstGenSwitchBrCase *new_case = &cases[i]; + if (type_is_invalid(new_case->value->value->type)) return ir_unreach_error(ira); - new_case->block->ref_instruction = &switch_br_instruction->base; + new_case->block->ref_instruction = &switch_br_instruction->base.base; } - IrBasicBlock *new_else_block = ir_get_new_bb(ira, switch_br_instruction->else_block, &switch_br_instruction->base); - IrInstructionSwitchBr *switch_br = ir_build_switch_br(&ira->new_irb, - switch_br_instruction->base.scope, switch_br_instruction->base.source_node, - target_value, new_else_block, case_count, cases, nullptr, nullptr); - switch_br->base.value->type = ira->codegen->builtin_types.entry_unreachable; + IrBasicBlockGen *new_else_block = ir_get_new_bb(ira, switch_br_instruction->else_block, &switch_br_instruction->base.base); + IrInstGenSwitchBr *switch_br = ir_build_switch_br_gen(ira, &switch_br_instruction->base.base, + target_value, new_else_block, case_count, cases); return ir_finish_anal(ira, &switch_br->base); } -static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, - IrInstructionSwitchTarget *switch_target_instruction) +static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira, + IrInstSrcSwitchTarget *switch_target_instruction) { Error err; - IrInstruction *target_value_ptr = switch_target_instruction->target_value_ptr->child; + IrInstGen *target_value_ptr = switch_target_instruction->target_value_ptr->child; if (type_is_invalid(target_value_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (target_value_ptr->value->type->id == ZigTypeIdMetaType) { assert(instr_is_comptime(target_value_ptr)); ZigType *ptr_type = target_value_ptr->value->data.x_type; assert(ptr_type->id == ZigTypeIdPointer); - return ir_const_type(ira, &switch_target_instruction->base, ptr_type->data.pointer.child_type); + return ir_const_type(ira, &switch_target_instruction->base.base, ptr_type->data.pointer.child_type); } ZigType *target_type = target_value_ptr->value->type->data.pointer.child_type; ZigValue *pointee_val = nullptr; if (instr_is_comptime(target_value_ptr) && target_value_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar) { - pointee_val = const_ptr_pointee(ira, ira->codegen, target_value_ptr->value, target_value_ptr->source_node); + pointee_val = const_ptr_pointee(ira, ira->codegen, target_value_ptr->value, target_value_ptr->base.source_node); if (pointee_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (pointee_val->special == ConstValSpecialRuntime) pointee_val = nullptr; } if ((err = type_resolve(ira->codegen, target_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; switch (target_type->id) { case ZigTypeIdInvalid: @@ -21556,13 +22500,13 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, case ZigTypeIdFn: case ZigTypeIdErrorSet: { if (pointee_val) { - IrInstruction *result = ir_const(ira, &switch_target_instruction->base, nullptr); + IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, nullptr); copy_const_val(result->value, pointee_val); result->value->type = target_type; return result; } - IrInstruction *result = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr, nullptr); + IrInstGen *result = ir_get_deref(ira, &switch_target_instruction->base.base, target_value_ptr, nullptr); result->value->type = target_type; return result; } @@ -21571,52 +22515,49 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, if (!decl_node->data.container_decl.auto_enum && decl_node->data.container_decl.init_arg_expr == nullptr) { - ErrorMsg *msg = ir_add_error(ira, target_value_ptr, + ErrorMsg *msg = ir_add_error(ira, &target_value_ptr->base, buf_sprintf("switch on union which has no attached enum")); add_error_note(ira->codegen, msg, decl_node, buf_sprintf("consider 'union(enum)' here")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *tag_type = target_type->data.unionation.tag_type; assert(tag_type != nullptr); assert(tag_type->id == ZigTypeIdEnum); if (pointee_val) { - IrInstruction *result = ir_const(ira, &switch_target_instruction->base, tag_type); + IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, tag_type); bigint_init_bigint(&result->value->data.x_enum_tag, &pointee_val->data.x_union.tag); return result; } if (tag_type->data.enumeration.src_field_count == 1) { - IrInstruction *result = ir_const(ira, &switch_target_instruction->base, tag_type); + IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, tag_type); TypeEnumField *only_field = &tag_type->data.enumeration.fields[0]; bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value); return result; } - IrInstruction *union_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr, nullptr); + IrInstGen *union_value = ir_get_deref(ira, &switch_target_instruction->base.base, target_value_ptr, nullptr); union_value->value->type = target_type; - IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope, - switch_target_instruction->base.source_node, union_value); - union_tag_inst->value->type = tag_type; - return union_tag_inst; + return ir_build_union_tag(ira, &switch_target_instruction->base.base, union_value, tag_type); } case ZigTypeIdEnum: { if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; - if (target_type->data.enumeration.src_field_count < 2) { + return ira->codegen->invalid_inst_gen; + if (target_type->data.enumeration.src_field_count == 1) { TypeEnumField *only_field = &target_type->data.enumeration.fields[0]; - IrInstruction *result = ir_const(ira, &switch_target_instruction->base, target_type); + IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, target_type); bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value); return result; } if (pointee_val) { - IrInstruction *result = ir_const(ira, &switch_target_instruction->base, target_type); + IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, target_type); bigint_init_bigint(&result->value->data.x_enum_tag, &pointee_val->data.x_enum_tag); return result; } - IrInstruction *enum_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr, nullptr); + IrInstGen *enum_value = ir_get_deref(ira, &switch_target_instruction->base.base, target_value_ptr, nullptr); enum_value->value->type = target_type; return enum_value; } @@ -21632,17 +22573,17 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, case ZigTypeIdVector: case ZigTypeIdFnFrame: case ZigTypeIdAnyFrame: - ir_add_error(ira, &switch_target_instruction->base, + ir_add_error(ira, &switch_target_instruction->base.base, buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } zig_unreachable(); } -static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstructionSwitchVar *instruction) { - IrInstruction *target_value_ptr = instruction->target_value_ptr->child; +static IrInstGen *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstSrcSwitchVar *instruction) { + IrInstGen *target_value_ptr = instruction->target_value_ptr->child; if (type_is_invalid(target_value_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *ref_type = target_value_ptr->value->type; assert(ref_type->id == ZigTypeIdPointer); @@ -21653,62 +22594,62 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru assert(enum_type->id == ZigTypeIdEnum); assert(instruction->prongs_len > 0); - IrInstruction *first_prong_value = instruction->prongs_ptr[0]->child; + IrInstGen *first_prong_value = instruction->prongs_ptr[0]->child; if (type_is_invalid(first_prong_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *first_casted_prong_value = ir_implicit_cast(ira, first_prong_value, enum_type); + IrInstGen *first_casted_prong_value = ir_implicit_cast(ira, first_prong_value, enum_type); if (type_is_invalid(first_casted_prong_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *first_prong_val = ir_resolve_const(ira, first_casted_prong_value, UndefBad); if (first_prong_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; TypeUnionField *first_field = find_union_field_by_tag(target_type, &first_prong_val->data.x_enum_tag); ErrorMsg *invalid_payload_msg = nullptr; for (size_t prong_i = 1; prong_i < instruction->prongs_len; prong_i += 1) { - IrInstruction *this_prong_inst = instruction->prongs_ptr[prong_i]->child; + IrInstGen *this_prong_inst = instruction->prongs_ptr[prong_i]->child; if (type_is_invalid(this_prong_inst->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *this_casted_prong_value = ir_implicit_cast(ira, this_prong_inst, enum_type); + IrInstGen *this_casted_prong_value = ir_implicit_cast(ira, this_prong_inst, enum_type); if (type_is_invalid(this_casted_prong_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *this_prong = ir_resolve_const(ira, this_casted_prong_value, UndefBad); if (this_prong == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; TypeUnionField *payload_field = find_union_field_by_tag(target_type, &this_prong->data.x_enum_tag); ZigType *payload_type = payload_field->type_entry; if (first_field->type_entry != payload_type) { if (invalid_payload_msg == nullptr) { - invalid_payload_msg = ir_add_error(ira, &instruction->base, + invalid_payload_msg = ir_add_error(ira, &instruction->base.base, buf_sprintf("capture group with incompatible types")); - add_error_note(ira->codegen, invalid_payload_msg, first_prong_value->source_node, + add_error_note(ira->codegen, invalid_payload_msg, first_prong_value->base.source_node, buf_sprintf("type '%s' here", buf_ptr(&first_field->type_entry->name))); } - add_error_note(ira->codegen, invalid_payload_msg, this_prong_inst->source_node, + add_error_note(ira->codegen, invalid_payload_msg, this_prong_inst->base.source_node, buf_sprintf("type '%s' here", buf_ptr(&payload_field->type_entry->name))); } } if (invalid_payload_msg != nullptr) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (instr_is_comptime(target_value_ptr)) { ZigValue *target_val_ptr = ir_resolve_const(ira, target_value_ptr, UndefBad); if (!target_value_ptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - ZigValue *pointee_val = const_ptr_pointee(ira, ira->codegen, target_val_ptr, instruction->base.source_node); + ZigValue *pointee_val = const_ptr_pointee(ira, ira->codegen, target_val_ptr, instruction->base.base.source_node); if (pointee_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *result = ir_const(ira, &instruction->base, + IrInstGen *result = ir_const(ira, &instruction->base.base, get_pointer_to_type(ira->codegen, first_field->type_entry, target_val_ptr->type->data.pointer.is_const)); ZigValue *out_val = result->value; @@ -21718,11 +22659,10 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru return result; } - IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, - instruction->base.scope, instruction->base.source_node, target_value_ptr, first_field, false, false); - result->value->type = get_pointer_to_type(ira->codegen, first_field->type_entry, + ZigType *result_type = get_pointer_to_type(ira->codegen, first_field->type_entry, target_value_ptr->value->type->data.pointer.is_const); - return result; + return ir_build_union_field_ptr(ira, &instruction->base.base, target_value_ptr, first_field, + false, false, result_type); } else if (target_type->id == ZigTypeIdErrorSet) { // construct an error set from the prong values ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet); @@ -21735,7 +22675,7 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru for (size_t i = 0; i < instruction->prongs_len; i += 1) { ErrorTableEntry *err = ir_resolve_error(ira, instruction->prongs_ptr[i]->child); if (err == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; error_list.append(err); buf_appendf(&err_set_type->name, "%s,", buf_ptr(&err->name)); } @@ -21751,29 +22691,29 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru ref_type->data.pointer.explicit_alignment, ref_type->data.pointer.bit_offset_in_host, ref_type->data.pointer.host_int_bytes, ref_type->data.pointer.allow_zero); - return ir_analyze_ptr_cast(ira, &instruction->base, target_value_ptr, new_target_value_ptr_type, - &instruction->base, false); + return ir_analyze_ptr_cast(ira, &instruction->base.base, target_value_ptr, new_target_value_ptr_type, + &instruction->base.base, false); } else { - ir_add_error(ira, &instruction->base, + ir_add_error(ira, &instruction->base.base, buf_sprintf("switch on type '%s' provides no expression parameter", buf_ptr(&target_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } -static IrInstruction *ir_analyze_instruction_switch_else_var(IrAnalyze *ira, - IrInstructionSwitchElseVar *instruction) +static IrInstGen *ir_analyze_instruction_switch_else_var(IrAnalyze *ira, + IrInstSrcSwitchElseVar *instruction) { - IrInstruction *target_value_ptr = instruction->target_value_ptr->child; + IrInstGen *target_value_ptr = instruction->target_value_ptr->child; if (type_is_invalid(target_value_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *ref_type = target_value_ptr->value->type; assert(ref_type->id == ZigTypeIdPointer); ZigType *target_type = target_value_ptr->value->type->data.pointer.child_type; if (target_type->id == ZigTypeIdErrorSet) { // make a new set that has the other cases removed - if (!resolve_inferred_error_set(ira->codegen, target_type, instruction->base.source_node)) { - return ira->codegen->invalid_instruction; + if (!resolve_inferred_error_set(ira->codegen, target_type, instruction->base.base.source_node)) { + return ira->codegen->invalid_inst_gen; } if (type_is_global_error_set(target_type)) { // the type of the else capture variable still has to be the global error set. @@ -21783,17 +22723,17 @@ static IrInstruction *ir_analyze_instruction_switch_else_var(IrAnalyze *ira, // Make note of the errors handled by other cases ErrorTableEntry **errors = allocate(ira->codegen->errors_by_index.length); for (size_t case_i = 0; case_i < instruction->switch_br->case_count; case_i += 1) { - IrInstructionSwitchBrCase *br_case = &instruction->switch_br->cases[case_i]; - IrInstruction *case_expr = br_case->value->child; + IrInstSrcSwitchBrCase *br_case = &instruction->switch_br->cases[case_i]; + IrInstGen *case_expr = br_case->value->child; if (case_expr->value->type->id == ZigTypeIdErrorSet) { ErrorTableEntry *err = ir_resolve_error(ira, case_expr); if (err == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; errors[err->value] = err; } else if (case_expr->value->type->id == ZigTypeIdMetaType) { ZigType *err_set_type = ir_resolve_type(ira, case_expr); if (type_is_invalid(err_set_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; populate_error_set_table(errors, err_set_type); } else { zig_unreachable(); @@ -21832,27 +22772,22 @@ static IrInstruction *ir_analyze_instruction_switch_else_var(IrAnalyze *ira, ref_type->data.pointer.explicit_alignment, ref_type->data.pointer.bit_offset_in_host, ref_type->data.pointer.host_int_bytes, ref_type->data.pointer.allow_zero); - return ir_analyze_ptr_cast(ira, &instruction->base, target_value_ptr, new_target_value_ptr_type, - &instruction->base, false); + return ir_analyze_ptr_cast(ira, &instruction->base.base, target_value_ptr, new_target_value_ptr_type, + &instruction->base.base, false); } return target_value_ptr; } -static IrInstruction *ir_analyze_instruction_union_tag(IrAnalyze *ira, IrInstructionUnionTag *instruction) { - IrInstruction *value = instruction->value->child; - return ir_analyze_union_tag(ira, &instruction->base, value); -} - -static IrInstruction *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImport *import_instruction) { +static IrInstGen *ir_analyze_instruction_import(IrAnalyze *ira, IrInstSrcImport *import_instruction) { Error err; - IrInstruction *name_value = import_instruction->name->child; + IrInstGen *name_value = import_instruction->name->child; Buf *import_target_str = ir_resolve_str(ira, name_value); if (!import_target_str) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - AstNode *source_node = import_instruction->base.source_node; + AstNode *source_node = import_instruction->base.base.source_node; ZigType *import = source_node->owner; ZigType *target_import; @@ -21865,48 +22800,48 @@ static IrInstruction *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructio ir_add_error_node(ira, source_node, buf_sprintf("import of file outside package path: '%s'", buf_ptr(import_target_path))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else if (err == ErrorFileNotFound) { ir_add_error_node(ira, source_node, buf_sprintf("unable to find '%s'", buf_ptr(import_target_path))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else { ir_add_error_node(ira, source_node, buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } - return ir_const_type(ira, &import_instruction->base, target_import); + return ir_const_type(ira, &import_instruction->base.base, target_import); } -static IrInstruction *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRef *ref_instruction) { - IrInstruction *value = ref_instruction->value->child; +static IrInstGen *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstSrcRef *ref_instruction) { + IrInstGen *value = ref_instruction->value->child; if (type_is_invalid(value->value->type)) - return ira->codegen->invalid_instruction; - return ir_get_ref(ira, &ref_instruction->base, value, ref_instruction->is_const, ref_instruction->is_volatile); + return ira->codegen->invalid_inst_gen; + return ir_get_ref(ira, &ref_instruction->base.base, value, ref_instruction->is_const, ref_instruction->is_volatile); } -static IrInstruction *ir_analyze_union_init(IrAnalyze *ira, IrInstruction *source_instruction, - AstNode *field_source_node, ZigType *union_type, Buf *field_name, IrInstruction *field_result_loc, - IrInstruction *result_loc) +static IrInstGen *ir_analyze_union_init(IrAnalyze *ira, IrInst* source_instruction, + AstNode *field_source_node, ZigType *union_type, Buf *field_name, IrInstGen *field_result_loc, + IrInstGen *result_loc) { Error err; assert(union_type->id == ZigTypeIdUnion); if ((err = type_resolve(ira->codegen, union_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; TypeUnionField *type_field = find_union_type_field(union_type, field_name); if (type_field == nullptr) { ir_add_error_node(ira, field_source_node, buf_sprintf("no member named '%s' in union '%s'", buf_ptr(field_name), buf_ptr(&union_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (type_is_invalid(type_field->type_entry)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (result_loc->value->data.x_ptr.mut == ConstPtrMutInfer) { if (instr_is_comptime(field_result_loc) && @@ -21918,42 +22853,42 @@ static IrInstruction *ir_analyze_union_init(IrAnalyze *ira, IrInstruction *sourc } } - bool is_comptime = ir_should_inline(ira->new_irb.exec, source_instruction->scope) + bool is_comptime = ir_should_inline(ira->old_irb.exec, source_instruction->scope) || type_requires_comptime(ira->codegen, union_type) == ReqCompTimeYes; - IrInstruction *result = ir_get_deref(ira, source_instruction, result_loc, nullptr); + IrInstGen *result = ir_get_deref(ira, source_instruction, result_loc, nullptr); if (is_comptime && !instr_is_comptime(result)) { - ir_add_error(ira, field_result_loc, + ir_add_error(ira, &field_result_loc->base, buf_sprintf("unable to evaluate constant expression")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } return result; } -static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction, - ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields, - IrInstruction *result_loc) +static IrInstGen *ir_analyze_container_init_fields(IrAnalyze *ira, IrInst *source_instr, + ZigType *container_type, size_t instr_field_count, IrInstSrcContainerInitFieldsField *fields, + IrInstGen *result_loc) { Error err; if (container_type->id == ZigTypeIdUnion) { if (instr_field_count != 1) { - ir_add_error(ira, instruction, + ir_add_error(ira, source_instr, buf_sprintf("union initialization expects exactly one field")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstructionContainerInitFieldsField *field = &fields[0]; - IrInstruction *field_result_loc = field->result_loc->child; + IrInstSrcContainerInitFieldsField *field = &fields[0]; + IrInstGen *field_result_loc = field->result_loc->child; if (type_is_invalid(field_result_loc->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_analyze_union_init(ira, instruction, field->source_node, container_type, field->name, + return ir_analyze_union_init(ira, source_instr, field->source_node, container_type, field->name, field_result_loc, result_loc); } if (container_type->id != ZigTypeIdStruct || is_slice(container_type)) { - ir_add_error(ira, instruction, + ir_add_error(ira, source_instr, buf_sprintf("type '%s' does not support struct initialization syntax", buf_ptr(&container_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (container_type->data.structure.resolve_status == ResolveStatusBeingInferred) { @@ -21962,16 +22897,16 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc } if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; size_t actual_field_count = container_type->data.structure.src_field_count; - IrInstruction *first_non_const_instruction = nullptr; + IrInstGen *first_non_const_instruction = nullptr; AstNode **field_assign_nodes = allocate(actual_field_count); - ZigList const_ptrs = {}; + ZigList const_ptrs = {}; - bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope) + bool is_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope) || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes; @@ -21987,29 +22922,29 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc // comptime-known values. for (size_t i = 0; i < instr_field_count; i += 1) { - IrInstructionContainerInitFieldsField *field = &fields[i]; + IrInstSrcContainerInitFieldsField *field = &fields[i]; - IrInstruction *field_result_loc = field->result_loc->child; + IrInstGen *field_result_loc = field->result_loc->child; if (type_is_invalid(field_result_loc->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; TypeStructField *type_field = find_struct_type_field(container_type, field->name); if (!type_field) { ir_add_error_node(ira, field->source_node, buf_sprintf("no member named '%s' in struct '%s'", buf_ptr(field->name), buf_ptr(&container_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (type_is_invalid(type_field->type_entry)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; size_t field_index = type_field->src_index; AstNode *existing_assign_node = field_assign_nodes[field_index]; if (existing_assign_node) { ErrorMsg *msg = ir_add_error_node(ira, field->source_node, buf_sprintf("duplicate field")); add_error_note(ira->codegen, msg, existing_assign_node, buf_sprintf("other field here")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } field_assign_nodes[field_index] = field->source_node; @@ -22030,20 +22965,20 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc TypeStructField *field = container_type->data.structure.fields[i]; memoize_field_init_val(ira->codegen, container_type, field); if (field->init_val == nullptr) { - ir_add_error_node(ira, instruction->source_node, + ir_add_error(ira, source_instr, buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i]->name))); any_missing = true; continue; } if (type_is_invalid(field->init_val->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *runtime_inst = ir_const(ira, instruction, field->init_val->type); + IrInstGen *runtime_inst = ir_const(ira, source_instr, field->init_val->type); copy_const_val(runtime_inst->value, field->init_val); - IrInstruction *field_ptr = ir_analyze_struct_field_ptr(ira, instruction, field, result_loc, + IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, field, result_loc, container_type, true); - ir_analyze_store_ptr(ira, instruction, field_ptr, runtime_inst, false); + ir_analyze_store_ptr(ira, source_instr, field_ptr, runtime_inst, false); if (instr_is_comptime(field_ptr) && field_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar) { const_ptrs.append(field_ptr); } else { @@ -22051,39 +22986,39 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc } } if (any_missing) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (result_loc->value->data.x_ptr.mut == ConstPtrMutInfer) { if (const_ptrs.length != actual_field_count) { result_loc->value->special = ConstValSpecialRuntime; for (size_t i = 0; i < const_ptrs.length; i += 1) { - IrInstruction *field_result_loc = const_ptrs.at(i); - IrInstruction *deref = ir_get_deref(ira, field_result_loc, field_result_loc, nullptr); + IrInstGen *field_result_loc = const_ptrs.at(i); + IrInstGen *deref = ir_get_deref(ira, &field_result_loc->base, field_result_loc, nullptr); field_result_loc->value->special = ConstValSpecialRuntime; - ir_analyze_store_ptr(ira, field_result_loc, field_result_loc, deref, false); + ir_analyze_store_ptr(ira, &field_result_loc->base, field_result_loc, deref, false); } } } - IrInstruction *result = ir_get_deref(ira, instruction, result_loc, nullptr); + IrInstGen *result = ir_get_deref(ira, source_instr, result_loc, nullptr); if (is_comptime && !instr_is_comptime(result)) { - ir_add_error_node(ira, first_non_const_instruction->source_node, + ir_add_error_node(ira, first_non_const_instruction->base.source_node, buf_sprintf("unable to evaluate constant expression")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } return result; } -static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, - IrInstructionContainerInitList *instruction) +static IrInstGen *ir_analyze_instruction_container_init_list(IrAnalyze *ira, + IrInstSrcContainerInitList *instruction) { - ir_assert(instruction->result_loc != nullptr, &instruction->base); - IrInstruction *result_loc = instruction->result_loc->child; + ir_assert(instruction->result_loc != nullptr, &instruction->base.base); + IrInstGen *result_loc = instruction->result_loc->child; if (type_is_invalid(result_loc->value->type)) return result_loc; - ir_assert(result_loc->value->type->id == ZigTypeIdPointer, &instruction->base); + ir_assert(result_loc->value->type->id == ZigTypeIdPointer, &instruction->base.base); ZigType *container_type = result_loc->value->type->data.pointer.child_type; @@ -22093,24 +23028,24 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, ir_add_error_node(ira, instruction->init_array_type_source_node, buf_sprintf("array literal requires address-of operator to coerce to slice type '%s'", buf_ptr(&container_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (container_type->id == ZigTypeIdVoid) { if (elem_count != 0) { - ir_add_error_node(ira, instruction->base.source_node, + ir_add_error_node(ira, instruction->base.base.source_node, buf_sprintf("void expression expects no arguments")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } if (container_type->id == ZigTypeIdStruct && elem_count == 0) { - ir_assert(instruction->result_loc != nullptr, &instruction->base); - IrInstruction *result_loc = instruction->result_loc->child; + ir_assert(instruction->result_loc != nullptr, &instruction->base.base); + IrInstGen *result_loc = instruction->result_loc->child; if (type_is_invalid(result_loc->value->type)) return result_loc; - return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, result_loc); + return ir_analyze_container_init_fields(ira, &instruction->base.base, container_type, 0, nullptr, result_loc); } if (container_type->id == ZigTypeIdArray) { @@ -22118,10 +23053,10 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, if (container_type->data.array.len != elem_count) { ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count, nullptr); - ir_add_error(ira, &instruction->base, + ir_add_error(ira, &instruction->base.base, buf_sprintf("expected %s literal, found %s literal", buf_ptr(&container_type->name), buf_ptr(&literal_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } else if (container_type->id == ZigTypeIdStruct && container_type->data.structure.resolve_status == ResolveStatusBeingInferred) @@ -22131,17 +23066,17 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, } else if (container_type->id == ZigTypeIdVector) { // OK } else { - ir_add_error_node(ira, instruction->base.source_node, + ir_add_error(ira, &instruction->base.base, buf_sprintf("type '%s' does not support array initialization", buf_ptr(&container_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } switch (type_has_one_possible_value(ira->codegen, container_type)) { case OnePossibleValueInvalid: - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case OnePossibleValueYes: - return ir_const_move(ira, &instruction->base, + return ir_const_move(ira, &instruction->base.base, get_the_one_possible_value(ira->codegen, container_type)); case OnePossibleValueNo: break; @@ -22150,16 +23085,16 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, bool is_comptime; switch (type_requires_comptime(ira->codegen, container_type)) { case ReqCompTimeInvalid: - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; case ReqCompTimeNo: - is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope); + is_comptime = ir_should_inline(ira->old_irb.exec, instruction->base.base.scope); break; case ReqCompTimeYes: is_comptime = true; break; } - IrInstruction *first_non_const_instruction = nullptr; + IrInstGen *first_non_const_instruction = nullptr; // The Result Location Mechanism has already emitted runtime instructions to // initialize runtime elements and has omitted instructions for the comptime @@ -22168,12 +23103,12 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, // array initialization can be a comptime value, overwrite ConstPtrMutInfer with // ConstPtrMutComptimeConst. Otherwise, emit instructions to runtime-initialize the // elements that have comptime-known values. - ZigList const_ptrs = {}; + ZigList const_ptrs = {}; for (size_t i = 0; i < elem_count; i += 1) { - IrInstruction *elem_result_loc = instruction->elem_result_loc_list[i]->child; + IrInstGen *elem_result_loc = instruction->elem_result_loc_list[i]->child; if (type_is_invalid(elem_result_loc->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; assert(elem_result_loc->value->type->id == ZigTypeIdPointer); @@ -22190,81 +23125,79 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, if (const_ptrs.length != elem_count) { result_loc->value->special = ConstValSpecialRuntime; for (size_t i = 0; i < const_ptrs.length; i += 1) { - IrInstruction *elem_result_loc = const_ptrs.at(i); + IrInstGen *elem_result_loc = const_ptrs.at(i); assert(elem_result_loc->value->special == ConstValSpecialStatic); if (elem_result_loc->value->type->data.pointer.inferred_struct_field != nullptr) { // This field will be generated comptime; no need to do this. continue; } - IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr); + IrInstGen *deref = ir_get_deref(ira, &elem_result_loc->base, elem_result_loc, nullptr); elem_result_loc->value->special = ConstValSpecialRuntime; - ir_analyze_store_ptr(ira, elem_result_loc, elem_result_loc, deref, false); + ir_analyze_store_ptr(ira, &elem_result_loc->base, elem_result_loc, deref, false); } } } - IrInstruction *result = ir_get_deref(ira, &instruction->base, result_loc, nullptr); + IrInstGen *result = ir_get_deref(ira, &instruction->base.base, result_loc, nullptr); if (instr_is_comptime(result)) return result; if (is_comptime) { - ir_add_error_node(ira, first_non_const_instruction->source_node, + ir_add_error(ira, &first_non_const_instruction->base, buf_sprintf("unable to evaluate constant expression")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *result_elem_type = result_loc->value->type->data.pointer.child_type; if (is_slice(result_elem_type)) { - ErrorMsg *msg = ir_add_error(ira, &instruction->base, + ErrorMsg *msg = ir_add_error(ira, &instruction->base.base, buf_sprintf("runtime-initialized array cannot be casted to slice type '%s'", buf_ptr(&result_elem_type->name))); - add_error_note(ira->codegen, msg, first_non_const_instruction->source_node, + add_error_note(ira->codegen, msg, first_non_const_instruction->base.source_node, buf_sprintf("this value is not comptime-known")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } return result; } -static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, - IrInstructionContainerInitFields *instruction) +static IrInstGen *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, + IrInstSrcContainerInitFields *instruction) { - ir_assert(instruction->result_loc != nullptr, &instruction->base); - IrInstruction *result_loc = instruction->result_loc->child; + ir_assert(instruction->result_loc != nullptr, &instruction->base.base); + IrInstGen *result_loc = instruction->result_loc->child; if (type_is_invalid(result_loc->value->type)) return result_loc; - ir_assert(result_loc->value->type->id == ZigTypeIdPointer, &instruction->base); + ir_assert(result_loc->value->type->id == ZigTypeIdPointer, &instruction->base.base); ZigType *container_type = result_loc->value->type->data.pointer.child_type; - return ir_analyze_container_init_fields(ira, &instruction->base, container_type, + return ir_analyze_container_init_fields(ira, &instruction->base.base, container_type, instruction->field_count, instruction->fields, result_loc); } -static IrInstruction *ir_analyze_instruction_compile_err(IrAnalyze *ira, - IrInstructionCompileErr *instruction) -{ - IrInstruction *msg_value = instruction->msg->child; +static IrInstGen *ir_analyze_instruction_compile_err(IrAnalyze *ira, IrInstSrcCompileErr *instruction) { + IrInstGen *msg_value = instruction->msg->child; Buf *msg_buf = ir_resolve_str(ira, msg_value); if (!msg_buf) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - ir_add_error(ira, &instruction->base, msg_buf); + ir_add_error(ira, &instruction->base.base, msg_buf); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } -static IrInstruction *ir_analyze_instruction_compile_log(IrAnalyze *ira, IrInstructionCompileLog *instruction) { +static IrInstGen *ir_analyze_instruction_compile_log(IrAnalyze *ira, IrInstSrcCompileLog *instruction) { Buf buf = BUF_INIT; fprintf(stderr, "| "); for (size_t i = 0; i < instruction->msg_count; i += 1) { - IrInstruction *msg = instruction->msg_list[i]->child; + IrInstGen *msg = instruction->msg_list[i]->child; if (type_is_invalid(msg->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; buf_resize(&buf, 0); if (msg->value->special == ConstValSpecialLazy) { // Resolve any lazy value that's passed, we need its value - if (ir_resolve_lazy(ira->codegen, msg->source_node, msg->value)) - return ira->codegen->invalid_instruction; + if (ir_resolve_lazy(ira->codegen, msg->base.source_node, msg->value)) + return ira->codegen->invalid_inst_gen; } render_const_value(ira->codegen, &buf, msg->value); const char *comma_str = (i != 0) ? ", " : ""; @@ -22272,25 +23205,25 @@ static IrInstruction *ir_analyze_instruction_compile_log(IrAnalyze *ira, IrInstr } fprintf(stderr, "\n"); - auto *expr = &instruction->base.source_node->data.fn_call_expr; + auto *expr = &instruction->base.base.source_node->data.fn_call_expr; if (!expr->seen) { // Here we bypass higher level functions such as ir_add_error because we do not want // invalidate_exec to be called. - add_node_error(ira->codegen, instruction->base.source_node, buf_sprintf("found compile log statement")); + add_node_error(ira->codegen, instruction->base.base.source_node, buf_sprintf("found compile log statement")); } expr->seen = true; - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } -static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstructionErrName *instruction) { - IrInstruction *value = instruction->value->child; +static IrInstGen *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstSrcErrName *instruction) { + IrInstGen *value = instruction->value->child; if (type_is_invalid(value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->codegen->builtin_types.entry_global_error_set); + IrInstGen *casted_value = ir_implicit_cast(ira, value, ira->codegen->builtin_types.entry_global_error_set); if (type_is_invalid(casted_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8, true, false, PtrLenUnknown, 0, 0, 0, false); @@ -22298,13 +23231,13 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct if (instr_is_comptime(casted_value)) { ZigValue *val = ir_resolve_const(ira, casted_value, UndefBad); if (val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ErrorTableEntry *err = casted_value->value->data.x_err_set; if (!err->cached_error_name_val) { ZigValue *array_val = create_const_str_lit(ira->codegen, &err->name)->data.x_ptr.data.ref.pointee; err->cached_error_name_val = create_const_slice(ira->codegen, array_val, 0, buf_len(&err->name), true); } - IrInstruction *result = ir_const(ira, &instruction->base, nullptr); + IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); copy_const_val(result->value, err->cached_error_name_val); result->value->type = str_type; return result; @@ -22312,79 +23245,106 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct ira->codegen->generate_error_name_table = true; - IrInstruction *result = ir_build_err_name(&ira->new_irb, - instruction->base.scope, instruction->base.source_node, value); - result->value->type = str_type; - return result; + return ir_build_err_name_gen(ira, &instruction->base.base, value, str_type); } -static IrInstruction *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstructionTagName *instruction) { +static IrInstGen *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstSrcTagName *instruction) { Error err; - IrInstruction *target = instruction->target->child; + IrInstGen *target = instruction->target->child; if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - assert(target->value->type->id == ZigTypeIdEnum); + if (target->value->type->id == ZigTypeIdEnumLiteral) { + IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); + Buf *field_name = target->value->data.x_enum_literal; + ZigValue *array_val = create_const_str_lit(ira->codegen, field_name)->data.x_ptr.data.ref.pointee; + init_const_slice(ira->codegen, result->value, array_val, 0, buf_len(field_name), true); + return result; + } + + if (target->value->type->id == ZigTypeIdUnion) { + target = ir_analyze_union_tag(ira, &instruction->base.base, target, instruction->base.is_gen); + if (type_is_invalid(target->value->type)) + return ira->codegen->invalid_inst_gen; + } + + if (target->value->type->id != ZigTypeIdEnum) { + ir_add_error(ira, &target->base, + buf_sprintf("expected enum tag, found '%s'", buf_ptr(&target->value->type->name))); + return ira->codegen->invalid_inst_gen; + } + + if (target->value->type->data.enumeration.src_field_count == 1 && + !target->value->type->data.enumeration.non_exhaustive) { + TypeEnumField *only_field = &target->value->type->data.enumeration.fields[0]; + ZigValue *array_val = create_const_str_lit(ira->codegen, only_field->name)->data.x_ptr.data.ref.pointee; + IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); + init_const_slice(ira->codegen, result->value, array_val, 0, buf_len(only_field->name), true); + return result; + } if (instr_is_comptime(target)) { if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; + if (target->value->type->data.enumeration.non_exhaustive) { + ir_add_error(ira, &instruction->base.base, + buf_sprintf("TODO @tagName on non-exhaustive enum https://github.com/ziglang/zig/issues/3991")); + return ira->codegen->invalid_inst_gen; + } TypeEnumField *field = find_enum_field_by_tag(target->value->type, &target->value->data.x_bigint); ZigValue *array_val = create_const_str_lit(ira->codegen, field->name)->data.x_ptr.data.ref.pointee; - IrInstruction *result = ir_const(ira, &instruction->base, nullptr); + IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); init_const_slice(ira->codegen, result->value, array_val, 0, buf_len(field->name), true); return result; } - IrInstruction *result = ir_build_tag_name(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, target); ZigType *u8_ptr_type = get_pointer_to_type_extra( ira->codegen, ira->codegen->builtin_types.entry_u8, true, false, PtrLenUnknown, 0, 0, 0, false); - result->value->type = get_slice_type(ira->codegen, u8_ptr_type); - return result; + ZigType *result_type = get_slice_type(ira->codegen, u8_ptr_type); + return ir_build_tag_name_gen(ira, &instruction->base.base, target, result_type); } -static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira, - IrInstructionFieldParentPtr *instruction) +static IrInstGen *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira, + IrInstSrcFieldParentPtr *instruction) { Error err; - IrInstruction *type_value = instruction->type_value->child; + IrInstGen *type_value = instruction->type_value->child; ZigType *container_type = ir_resolve_type(ira, type_value); if (type_is_invalid(container_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *field_name_value = instruction->field_name->child; + IrInstGen *field_name_value = instruction->field_name->child; Buf *field_name = ir_resolve_str(ira, field_name_value); if (!field_name) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *field_ptr = instruction->field_ptr->child; + IrInstGen *field_ptr = instruction->field_ptr->child; if (type_is_invalid(field_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (container_type->id != ZigTypeIdStruct) { - ir_add_error(ira, type_value, + ir_add_error(ira, &type_value->base, buf_sprintf("expected struct type, found '%s'", buf_ptr(&container_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; TypeStructField *field = find_struct_type_field(container_type, field_name); if (field == nullptr) { - ir_add_error(ira, field_name_value, + ir_add_error(ira, &field_name_value->base, buf_sprintf("struct '%s' has no field '%s'", buf_ptr(&container_type->name), buf_ptr(field_name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (field_ptr->value->type->id != ZigTypeIdPointer) { - ir_add_error(ira, field_ptr, + ir_add_error(ira, &field_ptr->base, buf_sprintf("expected pointer, found '%s'", buf_ptr(&field_ptr->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } bool is_packed = (container_type->data.structure.layout == ContainerLayoutPacked); @@ -22396,9 +23356,9 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira, field_ptr->value->type->data.pointer.is_volatile, PtrLenSingle, field_ptr_align, 0, 0, false); - IrInstruction *casted_field_ptr = ir_implicit_cast(ira, field_ptr, field_ptr_type); + IrInstGen *casted_field_ptr = ir_implicit_cast(ira, field_ptr, field_ptr_type); if (type_is_invalid(casted_field_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *result_type = get_pointer_to_type_extra(ira->codegen, container_type, casted_field_ptr->value->type->data.pointer.is_const, @@ -22409,23 +23369,23 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira, if (instr_is_comptime(casted_field_ptr)) { ZigValue *field_ptr_val = ir_resolve_const(ira, casted_field_ptr, UndefBad); if (!field_ptr_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (field_ptr_val->data.x_ptr.special != ConstPtrSpecialBaseStruct) { - ir_add_error(ira, field_ptr, buf_sprintf("pointer value not based on parent struct")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &field_ptr->base, buf_sprintf("pointer value not based on parent struct")); + return ira->codegen->invalid_inst_gen; } size_t ptr_field_index = field_ptr_val->data.x_ptr.data.base_struct.field_index; if (ptr_field_index != field->src_index) { - ir_add_error(ira, &instruction->base, + ir_add_error(ira, &instruction->base.base, buf_sprintf("field '%s' has index %" ZIG_PRI_usize " but pointer value is index %" ZIG_PRI_usize " of struct '%s'", buf_ptr(field->name), field->src_index, ptr_field_index, buf_ptr(&container_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *result = ir_const(ira, &instruction->base, result_type); + IrInstGen *result = ir_const(ira, &instruction->base.base, result_type); ZigValue *out_val = result->value; out_val->data.x_ptr.special = ConstPtrSpecialRef; out_val->data.x_ptr.data.ref.pointee = field_ptr_val->data.x_ptr.data.base_struct.struct_val; @@ -22433,15 +23393,12 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira, return result; } - IrInstruction *result = ir_build_field_parent_ptr(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, type_value, field_name_value, casted_field_ptr, field); - result->value->type = result_type; - return result; + return ir_build_field_parent_ptr_gen(ira, &instruction->base.base, casted_field_ptr, field, result_type); } static TypeStructField *validate_byte_offset(IrAnalyze *ira, - IrInstruction *type_value, - IrInstruction *field_name_value, + IrInstGen *type_value, + IrInstGen *field_name_value, size_t *byte_offset) { ZigType *container_type = ir_resolve_type(ira, type_value); @@ -22457,21 +23414,21 @@ static TypeStructField *validate_byte_offset(IrAnalyze *ira, return nullptr; if (container_type->id != ZigTypeIdStruct) { - ir_add_error(ira, type_value, + ir_add_error(ira, &type_value->base, buf_sprintf("expected struct type, found '%s'", buf_ptr(&container_type->name))); return nullptr; } TypeStructField *field = find_struct_type_field(container_type, field_name); if (field == nullptr) { - ir_add_error(ira, field_name_value, + ir_add_error(ira, &field_name_value->base, buf_sprintf("struct '%s' has no field '%s'", buf_ptr(&container_type->name), buf_ptr(field_name))); return nullptr; } if (!type_has_bits(field->type_entry)) { - ir_add_error(ira, field_name_value, + ir_add_error(ira, &field_name_value->base, buf_sprintf("zero-bit field '%s' in struct '%s' has no offset", buf_ptr(field_name), buf_ptr(&container_type->name))); return nullptr; @@ -22481,36 +23438,32 @@ static TypeStructField *validate_byte_offset(IrAnalyze *ira, return field; } -static IrInstruction *ir_analyze_instruction_byte_offset_of(IrAnalyze *ira, - IrInstructionByteOffsetOf *instruction) -{ - IrInstruction *type_value = instruction->type_value->child; +static IrInstGen *ir_analyze_instruction_byte_offset_of(IrAnalyze *ira, IrInstSrcByteOffsetOf *instruction) { + IrInstGen *type_value = instruction->type_value->child; if (type_is_invalid(type_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *field_name_value = instruction->field_name->child; + IrInstGen *field_name_value = instruction->field_name->child; size_t byte_offset = 0; if (!validate_byte_offset(ira, type_value, field_name_value, &byte_offset)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_const_unsigned(ira, &instruction->base, byte_offset); + return ir_const_unsigned(ira, &instruction->base.base, byte_offset); } -static IrInstruction *ir_analyze_instruction_bit_offset_of(IrAnalyze *ira, - IrInstructionBitOffsetOf *instruction) -{ - IrInstruction *type_value = instruction->type_value->child; +static IrInstGen *ir_analyze_instruction_bit_offset_of(IrAnalyze *ira, IrInstSrcBitOffsetOf *instruction) { + IrInstGen *type_value = instruction->type_value->child; if (type_is_invalid(type_value->value->type)) - return ira->codegen->invalid_instruction; - IrInstruction *field_name_value = instruction->field_name->child; + return ira->codegen->invalid_inst_gen; + IrInstGen *field_name_value = instruction->field_name->child; size_t byte_offset = 0; TypeStructField *field = nullptr; if (!(field = validate_byte_offset(ira, type_value, field_name_value, &byte_offset))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; size_t bit_offset = byte_offset * 8 + field->bit_offset_in_host; - return ir_const_unsigned(ira, &instruction->base, bit_offset); + return ir_const_unsigned(ira, &instruction->base.base, bit_offset); } static void ensure_field_index(ZigType *type, const char *field_name, size_t index) { @@ -22558,7 +23511,7 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, nullptr, var->const_value); } -static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr, ZigValue *out_val, +static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigValue *out_val, ScopeDecls *decls_scope) { Error err; @@ -22589,11 +23542,14 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr while ((curr_entry = decl_it.next()) != nullptr) { // If the declaration is unresolved, force it to be resolved again. - if (curr_entry->value->resolution == TldResolutionUnresolved) { - resolve_top_level_decl(ira->codegen, curr_entry->value, curr_entry->value->source_node, false); - if (curr_entry->value->resolution != TldResolutionOk) { - return ErrorSemanticAnalyzeFail; - } + resolve_top_level_decl(ira->codegen, curr_entry->value, curr_entry->value->source_node, false); + if (curr_entry->value->resolution == TldResolutionInvalid) { + return ErrorSemanticAnalyzeFail; + } + + if (curr_entry->value->resolution == TldResolutionResolving) { + ir_error_dependency_loop(ira, source_instr); + return ErrorSemanticAnalyzeFail; } // Skip comptime blocks and test functions. @@ -22650,6 +23606,8 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr case TldIdVar: { ZigVar *var = ((TldVar *)curr_entry->value)->var; + assert(var != nullptr); + if ((err = type_resolve(ira->codegen, var->const_value->type, ResolveStatusSizeKnown))) return ErrorSemanticAnalyzeFail; @@ -22680,11 +23638,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr ZigFn *fn_entry = ((TldFn *)curr_entry->value)->fn_entry; assert(!fn_entry->is_test); - - if (fn_entry->type_entry == nullptr) { - ir_error_dependency_loop(ira, source_instr); - return ErrorSemanticAnalyzeFail; - } + assert(fn_entry->type_entry != nullptr); AstNodeFnProto *fn_node = &fn_entry->proto_node->data.fn_proto; @@ -22916,7 +23870,7 @@ static void make_enum_field_val(IrAnalyze *ira, ZigValue *enum_field_val, TypeEn enum_field_val->data.x_struct.fields = inner_fields; } -static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr, ZigType *type_entry, +static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigType *type_entry, ZigValue **out) { Error err; @@ -23079,7 +24033,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Enum", nullptr); - ZigValue **fields = alloc_const_vals_ptrs(4); + ZigValue **fields = alloc_const_vals_ptrs(5); result->data.x_struct.fields = fields; // layout: ContainerLayout @@ -23125,6 +24079,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr { return err; } + // is_exhaustive: bool + ensure_field_index(result->type, "is_exhaustive", 4); + fields[4]->special = ConstValSpecialStatic; + fields[4]->type = ira->codegen->builtin_types.entry_bool; + fields[4]->data.x_bool = !type_entry->data.enumeration.non_exhaustive; break; } @@ -23499,22 +24458,20 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr return ErrorNone; } -static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira, - IrInstructionTypeInfo *instruction) -{ +static IrInstGen *ir_analyze_instruction_type_info(IrAnalyze *ira, IrInstSrcTypeInfo *instruction) { Error err; - IrInstruction *type_value = instruction->type_value->child; + IrInstGen *type_value = instruction->type_value->child; ZigType *type_entry = ir_resolve_type(ira, type_value); if (type_is_invalid(type_entry)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *result_type = ir_type_info_get_type(ira, nullptr, nullptr); ZigValue *payload; - if ((err = ir_make_type_info_value(ira, &instruction->base, type_entry, &payload))) - return ira->codegen->invalid_instruction; + if ((err = ir_make_type_info_value(ira, &instruction->base.base, type_entry, &payload))) + return ira->codegen->invalid_inst_gen; - IrInstruction *result = ir_const(ira, &instruction->base, result_type); + IrInstGen *result = ir_const(ira, &instruction->base.base, result_type); ZigValue *out_val = result->value; bigint_init_unsigned(&out_val->data.x_union.tag, type_id_index(type_entry)); out_val->data.x_union.payload = payload; @@ -23538,15 +24495,15 @@ static ZigValue *get_const_field(IrAnalyze *ira, AstNode *source_node, ZigValue return val; } -static Error get_const_field_sentinel(IrAnalyze *ira, IrInstruction *source_instr, ZigValue *struct_value, +static Error get_const_field_sentinel(IrAnalyze *ira, IrInst* source_instr, ZigValue *struct_value, const char *name, size_t field_index, ZigType *elem_type, ZigValue **result) { ZigValue *field_val = get_const_field(ira, source_instr->source_node, struct_value, name, field_index); if (field_val == nullptr) return ErrorSemanticAnalyzeFail; - IrInstruction *field_inst = ir_const_move(ira, source_instr, field_val); - IrInstruction *casted_field_inst = ir_implicit_cast(ira, field_inst, + IrInstGen *field_inst = ir_const_move(ira, source_instr, field_val); + IrInstGen *casted_field_inst = ir_implicit_cast(ira, field_inst, get_optional_type(ira->codegen, elem_type)); if (type_is_invalid(casted_field_inst->value->type)) return ErrorSemanticAnalyzeFail; @@ -23585,12 +24542,12 @@ static ZigType *get_const_field_meta_type(IrAnalyze *ira, AstNode *source_node, { ZigValue *value = get_const_field(ira, source_node, struct_value, name, field_index); if (value == nullptr) - return ira->codegen->invalid_instruction->value->type; + return ira->codegen->invalid_inst_gen->value->type; assert(value->type == ira->codegen->builtin_types.entry_type); return value->data.x_type; } -static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, ZigTypeId tagTypeId, ZigValue *payload) { +static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeId tagTypeId, ZigValue *payload) { Error err; switch (tagTypeId) { case ZigTypeIdInvalid: @@ -23606,21 +24563,21 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi case ZigTypeIdInt: { assert(payload->special == ConstValSpecialStatic); assert(payload->type == ir_type_info_get_type(ira, "Int", nullptr)); - BigInt *bi = get_const_field_lit_int(ira, instruction->source_node, payload, "bits", 1); + BigInt *bi = get_const_field_lit_int(ira, source_instr->source_node, payload, "bits", 1); if (bi == nullptr) - return ira->codegen->invalid_instruction->value->type; + return ira->codegen->invalid_inst_gen->value->type; bool is_signed; - if ((err = get_const_field_bool(ira, instruction->source_node, payload, "is_signed", 0, &is_signed))) - return ira->codegen->invalid_instruction->value->type; + if ((err = get_const_field_bool(ira, source_instr->source_node, payload, "is_signed", 0, &is_signed))) + return ira->codegen->invalid_inst_gen->value->type; return get_int_type(ira->codegen, is_signed, bigint_as_u32(bi)); } case ZigTypeIdFloat: { assert(payload->special == ConstValSpecialStatic); assert(payload->type == ir_type_info_get_type(ira, "Float", nullptr)); - BigInt *bi = get_const_field_lit_int(ira, instruction->source_node, payload, "bits", 0); + BigInt *bi = get_const_field_lit_int(ira, source_instr->source_node, payload, "bits", 0); if (bi == nullptr) - return ira->codegen->invalid_instruction->value->type; + return ira->codegen->invalid_inst_gen->value->type; uint32_t bits = bigint_as_u32(bi); switch (bits) { case 16: return ira->codegen->builtin_types.entry_f16; @@ -23628,48 +24585,47 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi case 64: return ira->codegen->builtin_types.entry_f64; case 128: return ira->codegen->builtin_types.entry_f128; } - ir_add_error(ira, instruction, - buf_sprintf("%d-bit float unsupported", bits)); - return ira->codegen->invalid_instruction->value->type; + ir_add_error(ira, source_instr, buf_sprintf("%d-bit float unsupported", bits)); + return ira->codegen->invalid_inst_gen->value->type; } case ZigTypeIdPointer: { ZigType *type_info_pointer_type = ir_type_info_get_type(ira, "Pointer", nullptr); assert(payload->special == ConstValSpecialStatic); assert(payload->type == type_info_pointer_type); - ZigValue *size_value = get_const_field(ira, instruction->source_node, payload, "size", 0); + ZigValue *size_value = get_const_field(ira, source_instr->source_node, payload, "size", 0); assert(size_value->type == ir_type_info_get_type(ira, "Size", type_info_pointer_type)); BuiltinPtrSize size_enum_index = (BuiltinPtrSize)bigint_as_u32(&size_value->data.x_enum_tag); PtrLen ptr_len = size_enum_index_to_ptr_len(size_enum_index); - ZigType *elem_type = get_const_field_meta_type(ira, instruction->source_node, payload, "child", 4); + ZigType *elem_type = get_const_field_meta_type(ira, source_instr->source_node, payload, "child", 4); if (type_is_invalid(elem_type)) - return ira->codegen->invalid_instruction->value->type; + return ira->codegen->invalid_inst_gen->value->type; ZigValue *sentinel; - if ((err = get_const_field_sentinel(ira, instruction, payload, "sentinel", 6, + if ((err = get_const_field_sentinel(ira, source_instr, payload, "sentinel", 6, elem_type, &sentinel))) { - return ira->codegen->invalid_instruction->value->type; + return ira->codegen->invalid_inst_gen->value->type; } - BigInt *bi = get_const_field_lit_int(ira, instruction->source_node, payload, "alignment", 3); + BigInt *bi = get_const_field_lit_int(ira, source_instr->source_node, payload, "alignment", 3); if (bi == nullptr) - return ira->codegen->invalid_instruction->value->type; + return ira->codegen->invalid_inst_gen->value->type; bool is_const; - if ((err = get_const_field_bool(ira, instruction->source_node, payload, "is_const", 1, &is_const))) - return ira->codegen->invalid_instruction->value->type; + if ((err = get_const_field_bool(ira, source_instr->source_node, payload, "is_const", 1, &is_const))) + return ira->codegen->invalid_inst_gen->value->type; bool is_volatile; - if ((err = get_const_field_bool(ira, instruction->source_node, payload, "is_volatile", 2, + if ((err = get_const_field_bool(ira, source_instr->source_node, payload, "is_volatile", 2, &is_volatile))) { - return ira->codegen->invalid_instruction->value->type; + return ira->codegen->invalid_inst_gen->value->type; } bool is_allowzero; - if ((err = get_const_field_bool(ira, instruction->source_node, payload, "is_allowzero", 5, + if ((err = get_const_field_bool(ira, source_instr->source_node, payload, "is_allowzero", 5, &is_allowzero))) { - return ira->codegen->invalid_instruction->value->type; + return ira->codegen->invalid_inst_gen->value->type; } @@ -23690,18 +24646,18 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi case ZigTypeIdArray: { assert(payload->special == ConstValSpecialStatic); assert(payload->type == ir_type_info_get_type(ira, "Array", nullptr)); - ZigType *elem_type = get_const_field_meta_type(ira, instruction->source_node, payload, "child", 1); + ZigType *elem_type = get_const_field_meta_type(ira, source_instr->source_node, payload, "child", 1); if (type_is_invalid(elem_type)) - return ira->codegen->invalid_instruction->value->type; + return ira->codegen->invalid_inst_gen->value->type; ZigValue *sentinel; - if ((err = get_const_field_sentinel(ira, instruction, payload, "sentinel", 2, + if ((err = get_const_field_sentinel(ira, source_instr, payload, "sentinel", 2, elem_type, &sentinel))) { - return ira->codegen->invalid_instruction->value->type; + return ira->codegen->invalid_inst_gen->value->type; } - BigInt *bi = get_const_field_lit_int(ira, instruction->source_node, payload, "len", 0); + BigInt *bi = get_const_field_lit_int(ira, source_instr->source_node, payload, "len", 0); if (bi == nullptr) - return ira->codegen->invalid_instruction->value->type; + return ira->codegen->invalid_inst_gen->value->type; return get_array_type(ira->codegen, elem_type, bigint_as_u64(bi), sentinel); } case ZigTypeIdComptimeFloat: @@ -23721,78 +24677,77 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi case ZigTypeIdAnyFrame: case ZigTypeIdVector: case ZigTypeIdEnumLiteral: - ir_add_error(ira, instruction, buf_sprintf( + ir_add_error(ira, source_instr, buf_sprintf( "TODO implement @Type for 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907", type_id_name(tagTypeId))); - return ira->codegen->invalid_instruction->value->type; + return ira->codegen->invalid_inst_gen->value->type; case ZigTypeIdUnion: case ZigTypeIdFn: case ZigTypeIdBoundFn: case ZigTypeIdStruct: - ir_add_error(ira, instruction, buf_sprintf( + ir_add_error(ira, source_instr, buf_sprintf( "@Type not availble for 'TypeInfo.%s'", type_id_name(tagTypeId))); - return ira->codegen->invalid_instruction->value->type; + return ira->codegen->invalid_inst_gen->value->type; } zig_unreachable(); } -static IrInstruction *ir_analyze_instruction_type(IrAnalyze *ira, IrInstructionType *instruction) { - IrInstruction *type_info_ir = instruction->type_info->child; - if (type_is_invalid(type_info_ir->value->type)) - return ira->codegen->invalid_instruction; +static IrInstGen *ir_analyze_instruction_type(IrAnalyze *ira, IrInstSrcType *instruction) { + IrInstGen *uncasted_type_info = instruction->type_info->child; + if (type_is_invalid(uncasted_type_info->value->type)) + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_ir = ir_implicit_cast(ira, type_info_ir, ir_type_info_get_type(ira, nullptr, nullptr)); - if (type_is_invalid(casted_ir->value->type)) - return ira->codegen->invalid_instruction; + IrInstGen *type_info = ir_implicit_cast(ira, uncasted_type_info, ir_type_info_get_type(ira, nullptr, nullptr)); + if (type_is_invalid(type_info->value->type)) + return ira->codegen->invalid_inst_gen; - ZigValue *type_info_value = ir_resolve_const(ira, casted_ir, UndefBad); - if (!type_info_value) - return ira->codegen->invalid_instruction; - ZigTypeId typeId = type_id_at_index(bigint_as_usize(&type_info_value->data.x_union.tag)); - ZigType *type = type_info_to_type(ira, type_info_ir, typeId, type_info_value->data.x_union.payload); + ZigValue *type_info_val = ir_resolve_const(ira, type_info, UndefBad); + if (type_info_val == nullptr) + return ira->codegen->invalid_inst_gen; + ZigTypeId type_id_tag = type_id_at_index(bigint_as_usize(&type_info_val->data.x_union.tag)); + ZigType *type = type_info_to_type(ira, &uncasted_type_info->base, type_id_tag, + type_info_val->data.x_union.payload); if (type_is_invalid(type)) - return ira->codegen->invalid_instruction; - return ir_const_type(ira, &instruction->base, type); + return ira->codegen->invalid_inst_gen; + return ir_const_type(ira, &instruction->base.base, type); } -static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira, - IrInstructionTypeId *instruction) -{ - IrInstruction *type_value = instruction->type_value->child; +static IrInstGen *ir_analyze_instruction_type_id(IrAnalyze *ira, IrInstSrcTypeId *instruction) { + IrInstGen *type_value = instruction->type_value->child; ZigType *type_entry = ir_resolve_type(ira, type_value); if (type_is_invalid(type_entry)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *result_type = get_builtin_type(ira->codegen, "TypeId"); - IrInstruction *result = ir_const(ira, &instruction->base, result_type); + IrInstGen *result = ir_const(ira, &instruction->base.base, result_type); bigint_init_unsigned(&result->value->data.x_enum_tag, type_id_index(type_entry)); return result; } -static IrInstruction *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira, - IrInstructionSetEvalBranchQuota *instruction) +static IrInstGen *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira, + IrInstSrcSetEvalBranchQuota *instruction) { uint64_t new_quota; if (!ir_resolve_usize(ira, instruction->new_quota->child, &new_quota)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (new_quota > *ira->new_irb.exec->backward_branch_quota) { *ira->new_irb.exec->backward_branch_quota = new_quota; } - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } -static IrInstruction *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstructionTypeName *instruction) { - IrInstruction *type_value = instruction->type_value->child; +static IrInstGen *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstSrcTypeName *instruction) { + IrInstGen *type_value = instruction->type_value->child; ZigType *type_entry = ir_resolve_type(ira, type_value); if (type_is_invalid(type_entry)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (!type_entry->cached_const_name_val) { type_entry->cached_const_name_val = create_const_str_lit(ira->codegen, type_bare_name(type_entry)); } - IrInstruction *result = ir_const(ira, &instruction->base, nullptr); + IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); copy_const_val(result->value, type_entry->cached_const_name_val); return result; } @@ -23804,13 +24759,13 @@ static void ir_cimport_cache_paths(Buf *cache_dir, Buf *tmp_c_file_digest, Buf * buf_ptr(cache_dir), buf_ptr(tmp_c_file_digest)); buf_appendf(out_zig_path, "%s" OS_SEP "cimport.zig", buf_ptr(out_zig_dir)); } -static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstructionCImport *instruction) { +static IrInstGen *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstSrcCImport *instruction) { Error err; - AstNode *node = instruction->base.source_node; + AstNode *node = instruction->base.base.source_node; assert(node->type == NodeTypeFnCallExpr); AstNode *block_node = node->data.fn_call_expr.params.at(0); - ScopeCImport *cimport_scope = create_cimport_scope(ira->codegen, node, instruction->base.scope); + ScopeCImport *cimport_scope = create_cimport_scope(ira->codegen, node, instruction->base.base.scope); // Execute the C import block like an inline function ZigType *void_type = ira->codegen->builtin_types.entry_void; @@ -23821,13 +24776,13 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, &cimport_scope->buf, block_node, nullptr, nullptr, nullptr, UndefBad))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (type_is_invalid(cimport_result->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; destroy(result_ptr, "ZigValue"); - ZigPackage *cur_scope_pkg = scope_package(instruction->base.scope); + ZigPackage *cur_scope_pkg = scope_package(instruction->base.base.scope); Buf *namespace_name = buf_sprintf("%s.cimport:%" ZIG_PRI_usize ":%" ZIG_PRI_usize, buf_ptr(&cur_scope_pkg->pkg_path), node->line + 1, node->column + 1); @@ -23839,7 +24794,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct CacheHash *cache_hash; if ((err = create_c_object_cache(ira->codegen, &cache_hash, false))) { ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to create cache: %s", err_str(err))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } cache_buf(cache_hash, &cimport_scope->buf); @@ -23851,7 +24806,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct if ((err = cache_hit(cache_hash, &tmp_c_file_digest))) { if (err != ErrorInvalidFormat) { ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to check cache: %s", err_str(err))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } ira->codegen->caches_to_release.append(cache_hash); @@ -23870,12 +24825,12 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct if ((err = os_make_path(tmp_c_file_dir))) { ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to make dir: %s", err_str(err))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if ((err = os_write_file(&tmp_c_file_path, &cimport_scope->buf))) { ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to write .h file: %s", err_str(err))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (ira->codegen->verbose_cimport) { fprintf(stderr, "@cImport source: %s\n", buf_ptr(&tmp_c_file_path)); @@ -23910,7 +24865,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct { if (err != ErrorCCompileErrors) { ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ErrorMsg *parent_err_msg = ir_add_error_node(ira, node, buf_sprintf("C import failed")); @@ -23931,7 +24886,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct } } - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (ira->codegen->verbose_cimport) { fprintf(stderr, "@cImport .d file: %s\n", buf_ptr(tmp_dep_file)); @@ -23939,29 +24894,29 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct if ((err = cache_add_dep_file(cache_hash, tmp_dep_file, false))) { ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to parse .d file: %s", err_str(err))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if ((err = cache_final(cache_hash, &tmp_c_file_digest))) { ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to finalize cache: %s", err_str(err))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ir_cimport_cache_paths(ira->codegen->cache_dir, &tmp_c_file_digest, out_zig_dir, out_zig_path); if ((err = os_make_path(out_zig_dir))) { ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to make output dir: %s", err_str(err))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } FILE *out_file = fopen(buf_ptr(out_zig_path), "wb"); if (out_file == nullptr) { ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to open output file: %s", strerror(errno))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } stage2_render_ast(ast, out_file); if (fclose(out_file) != 0) { ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to write to output file: %s", strerror(errno))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (ira->codegen->verbose_cimport) { @@ -23980,90 +24935,90 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct if ((err = file_fetch(ira->codegen, out_zig_path, import_code))) { ir_add_error_node(ira, node, buf_sprintf("unable to open '%s': %s", buf_ptr(out_zig_path), err_str(err))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *child_import = add_source_file(ira->codegen, cimport_pkg, out_zig_path, import_code, SourceKindCImport); - return ir_const_type(ira, &instruction->base, child_import); + return ir_const_type(ira, &instruction->base.base, child_import); } -static IrInstruction *ir_analyze_instruction_c_include(IrAnalyze *ira, IrInstructionCInclude *instruction) { - IrInstruction *name_value = instruction->name->child; +static IrInstGen *ir_analyze_instruction_c_include(IrAnalyze *ira, IrInstSrcCInclude *instruction) { + IrInstGen *name_value = instruction->name->child; if (type_is_invalid(name_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; Buf *include_name = ir_resolve_str(ira, name_value); if (!include_name) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - Buf *c_import_buf = exec_c_import_buf(ira->new_irb.exec); + Buf *c_import_buf = ira->new_irb.exec->c_import_buf; // We check for this error in pass1 assert(c_import_buf); buf_appendf(c_import_buf, "#include <%s>\n", buf_ptr(include_name)); - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } -static IrInstruction *ir_analyze_instruction_c_define(IrAnalyze *ira, IrInstructionCDefine *instruction) { - IrInstruction *name = instruction->name->child; +static IrInstGen *ir_analyze_instruction_c_define(IrAnalyze *ira, IrInstSrcCDefine *instruction) { + IrInstGen *name = instruction->name->child; if (type_is_invalid(name->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; Buf *define_name = ir_resolve_str(ira, name); if (!define_name) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *value = instruction->value->child; + IrInstGen *value = instruction->value->child; if (type_is_invalid(value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; Buf *define_value = nullptr; // The second parameter is either a string or void (equivalent to "") if (value->value->type->id != ZigTypeIdVoid) { define_value = ir_resolve_str(ira, value); if (!define_value) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - Buf *c_import_buf = exec_c_import_buf(ira->new_irb.exec); + Buf *c_import_buf = ira->new_irb.exec->c_import_buf; // We check for this error in pass1 assert(c_import_buf); buf_appendf(c_import_buf, "#define %s %s\n", buf_ptr(define_name), define_value ? buf_ptr(define_value) : ""); - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } -static IrInstruction *ir_analyze_instruction_c_undef(IrAnalyze *ira, IrInstructionCUndef *instruction) { - IrInstruction *name = instruction->name->child; +static IrInstGen *ir_analyze_instruction_c_undef(IrAnalyze *ira, IrInstSrcCUndef *instruction) { + IrInstGen *name = instruction->name->child; if (type_is_invalid(name->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; Buf *undef_name = ir_resolve_str(ira, name); if (!undef_name) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - Buf *c_import_buf = exec_c_import_buf(ira->new_irb.exec); + Buf *c_import_buf = ira->new_irb.exec->c_import_buf; // We check for this error in pass1 assert(c_import_buf); buf_appendf(c_import_buf, "#undef %s\n", buf_ptr(undef_name)); - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } -static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstructionEmbedFile *instruction) { - IrInstruction *name = instruction->name->child; +static IrInstGen *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstSrcEmbedFile *instruction) { + IrInstGen *name = instruction->name->child; if (type_is_invalid(name->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; Buf *rel_file_path = ir_resolve_str(ira, name); if (!rel_file_path) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - ZigType *import = get_scope_import(instruction->base.scope); + ZigType *import = get_scope_import(instruction->base.base.scope); // figure out absolute path to resource Buf source_dir_path = BUF_INIT; os_path_dirname(import->data.structure.root_struct->path, &source_dir_path); @@ -24080,93 +25035,95 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru Error err; if ((err = file_fetch(ira->codegen, file_path, file_contents))) { if (err == ErrorFileNotFound) { - ir_add_error(ira, instruction->name, buf_sprintf("unable to find '%s'", buf_ptr(file_path))); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->name->base, + buf_sprintf("unable to find '%s'", buf_ptr(file_path))); + return ira->codegen->invalid_inst_gen; } else { - ir_add_error(ira, instruction->name, buf_sprintf("unable to open '%s': %s", buf_ptr(file_path), err_str(err))); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->name->base, + buf_sprintf("unable to open '%s': %s", buf_ptr(file_path), err_str(err))); + return ira->codegen->invalid_inst_gen; } } ZigType *result_type = get_array_type(ira->codegen, ira->codegen->builtin_types.entry_u8, buf_len(file_contents), nullptr); - IrInstruction *result = ir_const(ira, &instruction->base, result_type); + IrInstGen *result = ir_const(ira, &instruction->base.base, result_type); init_const_str_lit(ira->codegen, result->value, file_contents); return result; } -static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchgSrc *instruction) { +static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxchg *instruction) { ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child); if (type_is_invalid(operand_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (operand_type->id == ZigTypeIdFloat) { - ir_add_error(ira, instruction->type_value->child, + ir_add_error(ira, &instruction->type_value->child->base, buf_sprintf("expected integer, enum or pointer type, found '%s'", buf_ptr(&operand_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *ptr = instruction->ptr->child; + IrInstGen *ptr = instruction->ptr->child; if (type_is_invalid(ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; // TODO let this be volatile ZigType *ptr_type = get_pointer_to_type(ira->codegen, operand_type, false); - IrInstruction *casted_ptr = ir_implicit_cast(ira, ptr, ptr_type); + IrInstGen *casted_ptr = ir_implicit_cast(ira, ptr, ptr_type); if (type_is_invalid(casted_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *cmp_value = instruction->cmp_value->child; + IrInstGen *cmp_value = instruction->cmp_value->child; if (type_is_invalid(cmp_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *new_value = instruction->new_value->child; + IrInstGen *new_value = instruction->new_value->child; if (type_is_invalid(new_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *success_order_value = instruction->success_order_value->child; + IrInstGen *success_order_value = instruction->success_order_value->child; if (type_is_invalid(success_order_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; AtomicOrder success_order; if (!ir_resolve_atomic_order(ira, success_order_value, &success_order)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *failure_order_value = instruction->failure_order_value->child; + IrInstGen *failure_order_value = instruction->failure_order_value->child; if (type_is_invalid(failure_order_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; AtomicOrder failure_order; if (!ir_resolve_atomic_order(ira, failure_order_value, &failure_order)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_cmp_value = ir_implicit_cast(ira, cmp_value, operand_type); + IrInstGen *casted_cmp_value = ir_implicit_cast(ira, cmp_value, operand_type); if (type_is_invalid(casted_cmp_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_new_value = ir_implicit_cast(ira, new_value, operand_type); + IrInstGen *casted_new_value = ir_implicit_cast(ira, new_value, operand_type); if (type_is_invalid(casted_new_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (success_order < AtomicOrderMonotonic) { - ir_add_error(ira, success_order_value, + ir_add_error(ira, &success_order_value->base, buf_sprintf("success atomic ordering must be Monotonic or stricter")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (failure_order < AtomicOrderMonotonic) { - ir_add_error(ira, failure_order_value, + ir_add_error(ira, &failure_order_value->base, buf_sprintf("failure atomic ordering must be Monotonic or stricter")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (failure_order > success_order) { - ir_add_error(ira, failure_order_value, + ir_add_error(ira, &failure_order_value->base, buf_sprintf("failure atomic ordering must be no stricter than success")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (failure_order == AtomicOrderRelease || failure_order == AtomicOrderAcqRel) { - ir_add_error(ira, failure_order_value, + ir_add_error(ira, &failure_order_value->base, buf_sprintf("failure atomic ordering must not be Release or AcqRel")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar && @@ -24175,66 +25132,63 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi } ZigType *result_type = get_optional_type(ira->codegen, operand_type); - IrInstruction *result_loc; + IrInstGen *result_loc; if (handle_is_ptr(result_type)) { - result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, + result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc, result_type, nullptr, true, true); - if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) { + if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) { return result_loc; } } else { result_loc = nullptr; } - return ir_build_cmpxchg_gen(ira, &instruction->base, result_type, + return ir_build_cmpxchg_gen(ira, &instruction->base.base, result_type, casted_ptr, casted_cmp_value, casted_new_value, success_order, failure_order, instruction->is_weak, result_loc); } -static IrInstruction *ir_analyze_instruction_fence(IrAnalyze *ira, IrInstructionFence *instruction) { - IrInstruction *order_value = instruction->order_value->child; - if (type_is_invalid(order_value->value->type)) - return ira->codegen->invalid_instruction; +static IrInstGen *ir_analyze_instruction_fence(IrAnalyze *ira, IrInstSrcFence *instruction) { + IrInstGen *order_inst = instruction->order->child; + if (type_is_invalid(order_inst->value->type)) + return ira->codegen->invalid_inst_gen; AtomicOrder order; - if (!ir_resolve_atomic_order(ira, order_value, &order)) - return ira->codegen->invalid_instruction; + if (!ir_resolve_atomic_order(ira, order_inst, &order)) + return ira->codegen->invalid_inst_gen; if (order < AtomicOrderAcquire) { - ir_add_error(ira, order_value, + ir_add_error(ira, &order_inst->base, buf_sprintf("atomic ordering must be Acquire or stricter")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *result = ir_build_fence(&ira->new_irb, - instruction->base.scope, instruction->base.source_node, order_value, order); - result->value->type = ira->codegen->builtin_types.entry_void; - return result; + return ir_build_fence_gen(ira, &instruction->base.base, order); } -static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstructionTruncate *instruction) { - IrInstruction *dest_type_value = instruction->dest_type->child; +static IrInstGen *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstSrcTruncate *instruction) { + IrInstGen *dest_type_value = instruction->dest_type->child; ZigType *dest_type = ir_resolve_type(ira, dest_type_value); if (type_is_invalid(dest_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (dest_type->id != ZigTypeIdInt && dest_type->id != ZigTypeIdComptimeInt) { - ir_add_error(ira, dest_type_value, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name))); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &dest_type_value->base, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name))); + return ira->codegen->invalid_inst_gen; } - IrInstruction *target = instruction->target->child; + IrInstGen *target = instruction->target->child; ZigType *src_type = target->value->type; if (type_is_invalid(src_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (src_type->id != ZigTypeIdInt && src_type->id != ZigTypeIdComptimeInt) { - ir_add_error(ira, target, buf_sprintf("expected integer type, found '%s'", buf_ptr(&src_type->name))); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &target->base, buf_sprintf("expected integer type, found '%s'", buf_ptr(&src_type->name))); + return ira->codegen->invalid_inst_gen; } if (dest_type->id == ZigTypeIdComptimeInt) { @@ -24244,54 +25198,51 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct if (instr_is_comptime(target)) { ZigValue *val = ir_resolve_const(ira, target, UndefBad); if (val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *result = ir_const(ira, &instruction->base, dest_type); + IrInstGen *result = ir_const(ira, &instruction->base.base, dest_type); bigint_truncate(&result->value->data.x_bigint, &val->data.x_bigint, dest_type->data.integral.bit_count, dest_type->data.integral.is_signed); return result; } if (src_type->data.integral.bit_count == 0 || dest_type->data.integral.bit_count == 0) { - IrInstruction *result = ir_const(ira, &instruction->base, dest_type); + IrInstGen *result = ir_const(ira, &instruction->base.base, dest_type); bigint_init_unsigned(&result->value->data.x_bigint, 0); return result; } if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) { const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned"; - ir_add_error(ira, target, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name))); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &target->base, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name))); + return ira->codegen->invalid_inst_gen; } else if (src_type->data.integral.bit_count < dest_type->data.integral.bit_count) { - ir_add_error(ira, target, buf_sprintf("type '%s' has fewer bits than destination type '%s'", + ir_add_error(ira, &target->base, buf_sprintf("type '%s' has fewer bits than destination type '%s'", buf_ptr(&src_type->name), buf_ptr(&dest_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *new_instruction = ir_build_truncate(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, dest_type_value, target); - new_instruction->value->type = dest_type; - return new_instruction; + return ir_build_truncate_gen(ira, &instruction->base.base, dest_type, target); } -static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstructionIntCast *instruction) { +static IrInstGen *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstSrcIntCast *instruction) { ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child); if (type_is_invalid(dest_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (dest_type->id != ZigTypeIdInt && dest_type->id != ZigTypeIdComptimeInt) { - ir_add_error(ira, instruction->dest_type, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name))); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->dest_type->base, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name))); + return ira->codegen->invalid_inst_gen; } - IrInstruction *target = instruction->target->child; + IrInstGen *target = instruction->target->child; if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (target->value->type->id != ZigTypeIdInt && target->value->type->id != ZigTypeIdComptimeInt) { - ir_add_error(ira, instruction->target, buf_sprintf("expected integer type, found '%s'", + ir_add_error(ira, &instruction->target->base, buf_sprintf("expected integer type, found '%s'", buf_ptr(&target->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (instr_is_comptime(target)) { @@ -24299,28 +25250,28 @@ static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstruct } if (dest_type->id == ZigTypeIdComptimeInt) { - ir_add_error(ira, instruction->target, buf_sprintf("attempt to cast runtime value to '%s'", + ir_add_error(ira, &instruction->target->base, buf_sprintf("attempt to cast runtime value to '%s'", buf_ptr(&dest_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - return ir_analyze_widen_or_shorten(ira, &instruction->base, target, dest_type); + return ir_analyze_widen_or_shorten(ira, &instruction->base.base, target, dest_type); } -static IrInstruction *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstructionFloatCast *instruction) { +static IrInstGen *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstSrcFloatCast *instruction) { ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child); if (type_is_invalid(dest_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (dest_type->id != ZigTypeIdFloat) { - ir_add_error(ira, instruction->dest_type, + ir_add_error(ira, &instruction->dest_type->base, buf_sprintf("expected float type, found '%s'", buf_ptr(&dest_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *target = instruction->target->child; + IrInstGen *target = instruction->target->child; if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (target->value->type->id == ZigTypeIdComptimeInt || target->value->type->id == ZigTypeIdComptimeFloat) @@ -24332,55 +25283,55 @@ static IrInstruction *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstru } else { op = CastOpNumLitToConcrete; } - return ir_resolve_cast(ira, &instruction->base, target, dest_type, op); + return ir_resolve_cast(ira, &instruction->base.base, target, dest_type, op); } else { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } if (target->value->type->id != ZigTypeIdFloat) { - ir_add_error(ira, instruction->target, buf_sprintf("expected float type, found '%s'", + ir_add_error(ira, &instruction->target->base, buf_sprintf("expected float type, found '%s'", buf_ptr(&target->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - return ir_analyze_widen_or_shorten(ira, &instruction->base, target, dest_type); + return ir_analyze_widen_or_shorten(ira, &instruction->base.base, target, dest_type); } -static IrInstruction *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInstructionErrSetCast *instruction) { +static IrInstGen *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInstSrcErrSetCast *instruction) { ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child); if (type_is_invalid(dest_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (dest_type->id != ZigTypeIdErrorSet) { - ir_add_error(ira, instruction->dest_type, + ir_add_error(ira, &instruction->dest_type->base, buf_sprintf("expected error set type, found '%s'", buf_ptr(&dest_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *target = instruction->target->child; + IrInstGen *target = instruction->target->child; if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (target->value->type->id != ZigTypeIdErrorSet) { - ir_add_error(ira, instruction->target, + ir_add_error(ira, &instruction->target->base, buf_sprintf("expected error set type, found '%s'", buf_ptr(&target->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - return ir_analyze_err_set_cast(ira, &instruction->base, target, dest_type); + return ir_analyze_err_set_cast(ira, &instruction->base.base, target, dest_type); } -static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) { +static IrInstGen *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstSrcFromBytes *instruction) { Error err; ZigType *dest_child_type = ir_resolve_type(ira, instruction->dest_child_type->child); if (type_is_invalid(dest_child_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *target = instruction->target->child; + IrInstGen *target = instruction->target->child; if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; bool src_ptr_const; bool src_ptr_volatile; @@ -24390,27 +25341,27 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru src_ptr_volatile = target->value->type->data.pointer.is_volatile; if ((err = resolve_ptr_align(ira, target->value->type, &src_ptr_align))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else if (is_slice(target->value->type)) { ZigType *src_ptr_type = target->value->type->data.structure.fields[slice_ptr_index]->type_entry; src_ptr_const = src_ptr_type->data.pointer.is_const; src_ptr_volatile = src_ptr_type->data.pointer.is_volatile; if ((err = resolve_ptr_align(ira, src_ptr_type, &src_ptr_align))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else { src_ptr_const = true; src_ptr_volatile = false; if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusAlignmentKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; src_ptr_align = get_abi_alignment(ira->codegen, target->value->type); } if (src_ptr_align != 0) { if ((err = type_resolve(ira->codegen, dest_child_type, ResolveStatusAlignmentKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_child_type, @@ -24423,9 +25374,9 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru src_ptr_align, 0, 0, false); ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr); - IrInstruction *casted_value = ir_implicit_cast(ira, target, u8_slice); + IrInstGen *casted_value = ir_implicit_cast(ira, target, u8_slice); if (type_is_invalid(casted_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; bool have_known_len = false; uint64_t known_len; @@ -24433,7 +25384,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru if (instr_is_comptime(casted_value)) { ZigValue *val = ir_resolve_const(ira, casted_value, UndefBad); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *len_val = val->data.x_struct.fields[slice_len_index]; if (value_is_comptime(len_val)) { @@ -24442,9 +25393,9 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru } } - IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, + IrInstGen *result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc, dest_slice_type, nullptr, true, true); - if (result_loc != nullptr && (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc))) { + if (result_loc != nullptr && (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable)) { return result_loc; } @@ -24461,41 +25412,41 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru if (have_known_len) { if ((err = type_resolve(ira->codegen, dest_child_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; uint64_t child_type_size = type_size(ira->codegen, dest_child_type); uint64_t remainder = known_len % child_type_size; if (remainder != 0) { - ErrorMsg *msg = ir_add_error(ira, &instruction->base, + ErrorMsg *msg = ir_add_error(ira, &instruction->base.base, buf_sprintf("unable to convert [%" ZIG_PRI_u64 "]u8 to %s: size mismatch", known_len, buf_ptr(&dest_slice_type->name))); - add_error_note(ira->codegen, msg, instruction->dest_child_type->source_node, + add_error_note(ira->codegen, msg, instruction->dest_child_type->base.source_node, buf_sprintf("%s has size %" ZIG_PRI_u64 "; remaining bytes: %" ZIG_PRI_u64, buf_ptr(&dest_child_type->name), child_type_size, remainder)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } - return ir_build_resize_slice(ira, &instruction->base, casted_value, dest_slice_type, result_loc); + return ir_build_resize_slice(ira, &instruction->base.base, casted_value, dest_slice_type, result_loc); } -static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) { +static IrInstGen *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstSrcToBytes *instruction) { Error err; - IrInstruction *target = instruction->target->child; + IrInstGen *target = instruction->target->child; if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (!is_slice(target->value->type)) { - ir_add_error(ira, instruction->target, + ir_add_error(ira, &instruction->target->base, buf_sprintf("expected slice, found '%s'", buf_ptr(&target->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *src_ptr_type = target->value->type->data.structure.fields[slice_ptr_index]->type_entry; uint32_t alignment; if ((err = resolve_ptr_align(ira, src_ptr_type, &alignment))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8, src_ptr_type->data.pointer.is_const, src_ptr_type->data.pointer.is_volatile, PtrLenUnknown, @@ -24505,9 +25456,9 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct if (instr_is_comptime(target)) { ZigValue *target_val = ir_resolve_const(ira, target, UndefBad); if (target_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *result = ir_const(ira, &instruction->base, dest_slice_type); + IrInstGen *result = ir_const(ira, &instruction->base.base, dest_slice_type); result->value->data.x_struct.fields = alloc_const_vals_ptrs(2); ZigValue *ptr_val = result->value->data.x_struct.fields[slice_ptr_index]; @@ -24527,13 +25478,13 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct return result; } - IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, + IrInstGen *result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc, dest_slice_type, nullptr, true, true); - if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) { + if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) { return result_loc; } - return ir_build_resize_slice(ira, &instruction->base, target, dest_slice_type, result_loc); + return ir_build_resize_slice(ira, &instruction->base.base, target, dest_slice_type, result_loc); } static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) { @@ -24550,26 +25501,26 @@ static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_ali return ErrorNone; } -static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) { +static IrInstGen *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstSrcIntToFloat *instruction) { ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child); if (type_is_invalid(dest_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *target = instruction->target->child; + IrInstGen *target = instruction->target->child; if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (target->value->type->id != ZigTypeIdInt && target->value->type->id != ZigTypeIdComptimeInt) { - ir_add_error(ira, instruction->target, buf_sprintf("expected int type, found '%s'", + ir_add_error(ira, &instruction->target->base, buf_sprintf("expected int type, found '%s'", buf_ptr(&target->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpIntToFloat); + return ir_resolve_cast(ira, &instruction->base.base, target, dest_type, CastOpIntToFloat); } -static IrInstruction *ir_analyze_float_to_int(IrAnalyze *ira, IrInstruction *source_instr, - ZigType *dest_type, IrInstruction *operand, AstNode *operand_source_node) +static IrInstGen *ir_analyze_float_to_int(IrAnalyze *ira, IrInst* source_instr, + ZigType *dest_type, IrInstGen *operand, AstNode *operand_source_node) { if (operand->value->type->id == ZigTypeIdComptimeInt) { return ir_implicit_cast(ira, operand, dest_type); @@ -24578,106 +25529,107 @@ static IrInstruction *ir_analyze_float_to_int(IrAnalyze *ira, IrInstruction *sou if (operand->value->type->id != ZigTypeIdFloat && operand->value->type->id != ZigTypeIdComptimeFloat) { ir_add_error_node(ira, operand_source_node, buf_sprintf("expected float type, found '%s'", buf_ptr(&operand->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } return ir_resolve_cast(ira, source_instr, operand, dest_type, CastOpFloatToInt); } -static IrInstruction *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrInstructionFloatToInt *instruction) { +static IrInstGen *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrInstSrcFloatToInt *instruction) { ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child); if (type_is_invalid(dest_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *operand = instruction->target->child; + IrInstGen *operand = instruction->target->child; if (type_is_invalid(operand->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_analyze_float_to_int(ira, &instruction->base, dest_type, operand, instruction->target->source_node); + return ir_analyze_float_to_int(ira, &instruction->base.base, dest_type, operand, + instruction->target->base.source_node); } -static IrInstruction *ir_analyze_instruction_err_to_int(IrAnalyze *ira, IrInstructionErrToInt *instruction) { - IrInstruction *target = instruction->target->child; +static IrInstGen *ir_analyze_instruction_err_to_int(IrAnalyze *ira, IrInstSrcErrToInt *instruction) { + IrInstGen *target = instruction->target->child; if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_target; + IrInstGen *casted_target; if (target->value->type->id == ZigTypeIdErrorSet) { casted_target = target; } else { casted_target = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_global_error_set); if (type_is_invalid(casted_target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - return ir_analyze_err_to_int(ira, &instruction->base, casted_target, ira->codegen->err_tag_type); + return ir_analyze_err_to_int(ira, &instruction->base.base, casted_target, ira->codegen->err_tag_type); } -static IrInstruction *ir_analyze_instruction_int_to_err(IrAnalyze *ira, IrInstructionIntToErr *instruction) { - IrInstruction *target = instruction->target->child; +static IrInstGen *ir_analyze_instruction_int_to_err(IrAnalyze *ira, IrInstSrcIntToErr *instruction) { + IrInstGen *target = instruction->target->child; if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_target = ir_implicit_cast(ira, target, ira->codegen->err_tag_type); + IrInstGen *casted_target = ir_implicit_cast(ira, target, ira->codegen->err_tag_type); if (type_is_invalid(casted_target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_analyze_int_to_err(ira, &instruction->base, casted_target, ira->codegen->builtin_types.entry_global_error_set); + return ir_analyze_int_to_err(ira, &instruction->base.base, casted_target, ira->codegen->builtin_types.entry_global_error_set); } -static IrInstruction *ir_analyze_instruction_bool_to_int(IrAnalyze *ira, IrInstructionBoolToInt *instruction) { - IrInstruction *target = instruction->target->child; +static IrInstGen *ir_analyze_instruction_bool_to_int(IrAnalyze *ira, IrInstSrcBoolToInt *instruction) { + IrInstGen *target = instruction->target->child; if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (target->value->type->id != ZigTypeIdBool) { - ir_add_error(ira, instruction->target, buf_sprintf("expected bool, found '%s'", + ir_add_error(ira, &instruction->target->base, buf_sprintf("expected bool, found '%s'", buf_ptr(&target->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (instr_is_comptime(target)) { bool is_true; if (!ir_resolve_bool(ira, target, &is_true)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_const_unsigned(ira, &instruction->base, is_true ? 1 : 0); + return ir_const_unsigned(ira, &instruction->base.base, is_true ? 1 : 0); } ZigType *u1_type = get_int_type(ira->codegen, false, 1); - return ir_resolve_cast(ira, &instruction->base, target, u1_type, CastOpBoolToInt); + return ir_resolve_cast(ira, &instruction->base.base, target, u1_type, CastOpBoolToInt); } -static IrInstruction *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstructionIntType *instruction) { - IrInstruction *is_signed_value = instruction->is_signed->child; +static IrInstGen *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstSrcIntType *instruction) { + IrInstGen *is_signed_value = instruction->is_signed->child; bool is_signed; if (!ir_resolve_bool(ira, is_signed_value, &is_signed)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *bit_count_value = instruction->bit_count->child; + IrInstGen *bit_count_value = instruction->bit_count->child; uint64_t bit_count; if (!ir_resolve_unsigned(ira, bit_count_value, ira->codegen->builtin_types.entry_u16, &bit_count)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_const_type(ira, &instruction->base, get_int_type(ira->codegen, is_signed, (uint32_t)bit_count)); + return ir_const_type(ira, &instruction->base.base, get_int_type(ira->codegen, is_signed, (uint32_t)bit_count)); } -static IrInstruction *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstructionVectorType *instruction) { +static IrInstGen *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstSrcVectorType *instruction) { uint64_t len; if (!ir_resolve_unsigned(ira, instruction->len->child, ira->codegen->builtin_types.entry_u32, &len)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *elem_type = ir_resolve_vector_elem_type(ira, instruction->elem_type->child); if (type_is_invalid(elem_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *vector_type = get_vector_type(ira->codegen, len, elem_type); - return ir_const_type(ira, &instruction->base, vector_type); + return ir_const_type(ira, &instruction->base.base, vector_type); } -static IrInstruction *ir_analyze_shuffle_vector(IrAnalyze *ira, IrInstruction *source_instr, - ZigType *scalar_type, IrInstruction *a, IrInstruction *b, IrInstruction *mask) +static IrInstGen *ir_analyze_shuffle_vector(IrAnalyze *ira, IrInst* source_instr, + ZigType *scalar_type, IrInstGen *a, IrInstGen *b, IrInstGen *mask) { ir_assert(source_instr && scalar_type && a && b && mask, source_instr); ir_assert(is_valid_vector_elem_type(scalar_type), source_instr); @@ -24688,15 +25640,15 @@ static IrInstruction *ir_analyze_shuffle_vector(IrAnalyze *ira, IrInstruction *s } else if (mask->value->type->id == ZigTypeIdArray) { len_mask = mask->value->type->data.array.len; } else { - ir_add_error(ira, mask, + ir_add_error(ira, &mask->base, buf_sprintf("expected vector or array, found '%s'", buf_ptr(&mask->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } mask = ir_implicit_cast(ira, mask, get_vector_type(ira->codegen, len_mask, ira->codegen->builtin_types.entry_i32)); if (type_is_invalid(mask->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; uint32_t len_a; if (a->value->type->id == ZigTypeIdVector) { @@ -24706,11 +25658,11 @@ static IrInstruction *ir_analyze_shuffle_vector(IrAnalyze *ira, IrInstruction *s } else if (a->value->type->id == ZigTypeIdUndefined) { len_a = UINT32_MAX; } else { - ir_add_error(ira, a, + ir_add_error(ira, &a->base, buf_sprintf("expected vector or array with element type '%s', found '%s'", buf_ptr(&scalar_type->name), buf_ptr(&a->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } uint32_t len_b; @@ -24721,38 +25673,38 @@ static IrInstruction *ir_analyze_shuffle_vector(IrAnalyze *ira, IrInstruction *s } else if (b->value->type->id == ZigTypeIdUndefined) { len_b = UINT32_MAX; } else { - ir_add_error(ira, b, + ir_add_error(ira, &b->base, buf_sprintf("expected vector or array with element type '%s', found '%s'", buf_ptr(&scalar_type->name), buf_ptr(&b->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (len_a == UINT32_MAX && len_b == UINT32_MAX) { - return ir_const_undef(ira, a, get_vector_type(ira->codegen, len_mask, scalar_type)); + return ir_const_undef(ira, &a->base, get_vector_type(ira->codegen, len_mask, scalar_type)); } if (len_a == UINT32_MAX) { len_a = len_b; - a = ir_const_undef(ira, a, get_vector_type(ira->codegen, len_a, scalar_type)); + a = ir_const_undef(ira, &a->base, get_vector_type(ira->codegen, len_a, scalar_type)); } else { a = ir_implicit_cast(ira, a, get_vector_type(ira->codegen, len_a, scalar_type)); if (type_is_invalid(a->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (len_b == UINT32_MAX) { len_b = len_a; - b = ir_const_undef(ira, b, get_vector_type(ira->codegen, len_b, scalar_type)); + b = ir_const_undef(ira, &b->base, get_vector_type(ira->codegen, len_b, scalar_type)); } else { b = ir_implicit_cast(ira, b, get_vector_type(ira->codegen, len_b, scalar_type)); if (type_is_invalid(b->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigValue *mask_val = ir_resolve_const(ira, mask, UndefOk); if (mask_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; expand_undef_array(ira->codegen, mask_val); @@ -24762,7 +25714,7 @@ static IrInstruction *ir_analyze_shuffle_vector(IrAnalyze *ira, IrInstruction *s continue; int32_t v_i32 = bigint_as_signed(&mask_elem_val->data.x_bigint); uint32_t v; - IrInstruction *chosen_operand; + IrInstGen *chosen_operand; if (v_i32 >= 0) { v = (uint32_t)v_i32; chosen_operand = a; @@ -24771,16 +25723,16 @@ static IrInstruction *ir_analyze_shuffle_vector(IrAnalyze *ira, IrInstruction *s chosen_operand = b; } if (v >= chosen_operand->value->type->data.vector.len) { - ErrorMsg *msg = ir_add_error(ira, mask, + ErrorMsg *msg = ir_add_error(ira, &mask->base, buf_sprintf("mask index '%u' has out-of-bounds selection", i)); - add_error_note(ira->codegen, msg, chosen_operand->source_node, + add_error_note(ira->codegen, msg, chosen_operand->base.source_node, buf_sprintf("selected index '%u' out of bounds of %s", v, buf_ptr(&chosen_operand->value->type->name))); if (chosen_operand == a && v < len_a + len_b) { - add_error_note(ira->codegen, msg, b->source_node, + add_error_note(ira->codegen, msg, b->base.source_node, buf_create_from_str("selections from the second vector are specified with negative numbers")); } - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } @@ -24788,16 +25740,16 @@ static IrInstruction *ir_analyze_shuffle_vector(IrAnalyze *ira, IrInstruction *s if (instr_is_comptime(a) && instr_is_comptime(b)) { ZigValue *a_val = ir_resolve_const(ira, a, UndefOk); if (a_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *b_val = ir_resolve_const(ira, b, UndefOk); if (b_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; expand_undef_array(ira->codegen, a_val); expand_undef_array(ira->codegen, b_val); - IrInstruction *result = ir_const(ira, source_instr, result_type); + IrInstGen *result = ir_const(ira, source_instr, result_type); result->value->data.x_array.data.s_none.elements = create_const_vals(len_mask); for (uint32_t i = 0; i < mask_val->type->data.vector.len; i += 1) { ZigValue *mask_elem_val = &mask_val->data.x_array.data.s_none.elements[i]; @@ -24829,7 +25781,7 @@ static IrInstruction *ir_analyze_shuffle_vector(IrAnalyze *ira, IrInstruction *s uint32_t len_min = min(len_a, len_b); uint32_t len_max = max(len_a, len_b); - IrInstruction *expand_mask = ir_const(ira, mask, + IrInstGen *expand_mask = ir_const(ira, &mask->base, get_vector_type(ira->codegen, len_max, ira->codegen->builtin_types.entry_i32)); expand_mask->value->data.x_array.data.s_none.elements = create_const_vals(len_max); uint32_t i = 0; @@ -24838,7 +25790,7 @@ static IrInstruction *ir_analyze_shuffle_vector(IrAnalyze *ira, IrInstruction *s for (; i < len_max; i += 1) bigint_init_signed(&expand_mask->value->data.x_array.data.s_none.elements[i].data.x_bigint, -1); - IrInstruction *undef = ir_const_undef(ira, source_instr, + IrInstGen *undef = ir_const_undef(ira, source_instr, get_vector_type(ira->codegen, len_min, scalar_type)); if (len_b < len_a) { @@ -24848,62 +25800,59 @@ static IrInstruction *ir_analyze_shuffle_vector(IrAnalyze *ira, IrInstruction *s } } - IrInstruction *result = ir_build_shuffle_vector(&ira->new_irb, - source_instr->scope, source_instr->source_node, - nullptr, a, b, mask); - result->value->type = result_type; - return result; + return ir_build_shuffle_vector_gen(ira, source_instr->scope, source_instr->source_node, + result_type, a, b, mask); } -static IrInstruction *ir_analyze_instruction_shuffle_vector(IrAnalyze *ira, IrInstructionShuffleVector *instruction) { - ZigType *scalar_type = ir_resolve_vector_elem_type(ira, instruction->scalar_type); +static IrInstGen *ir_analyze_instruction_shuffle_vector(IrAnalyze *ira, IrInstSrcShuffleVector *instruction) { + ZigType *scalar_type = ir_resolve_vector_elem_type(ira, instruction->scalar_type->child); if (type_is_invalid(scalar_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *a = instruction->a->child; + IrInstGen *a = instruction->a->child; if (type_is_invalid(a->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *b = instruction->b->child; + IrInstGen *b = instruction->b->child; if (type_is_invalid(b->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *mask = instruction->mask->child; + IrInstGen *mask = instruction->mask->child; if (type_is_invalid(mask->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_analyze_shuffle_vector(ira, &instruction->base, scalar_type, a, b, mask); + return ir_analyze_shuffle_vector(ira, &instruction->base.base, scalar_type, a, b, mask); } -static IrInstruction *ir_analyze_instruction_splat(IrAnalyze *ira, IrInstructionSplatSrc *instruction) { +static IrInstGen *ir_analyze_instruction_splat(IrAnalyze *ira, IrInstSrcSplat *instruction) { Error err; - IrInstruction *len = instruction->len->child; + IrInstGen *len = instruction->len->child; if (type_is_invalid(len->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *scalar = instruction->scalar->child; + IrInstGen *scalar = instruction->scalar->child; if (type_is_invalid(scalar->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; uint64_t len_u64; if (!ir_resolve_unsigned(ira, len, ira->codegen->builtin_types.entry_u32, &len_u64)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; uint32_t len_int = len_u64; - if ((err = ir_validate_vector_elem_type(ira, scalar, scalar->value->type))) - return ira->codegen->invalid_instruction; + if ((err = ir_validate_vector_elem_type(ira, scalar->base.source_node, scalar->value->type))) + return ira->codegen->invalid_inst_gen; ZigType *return_type = get_vector_type(ira->codegen, len_int, scalar->value->type); if (instr_is_comptime(scalar)) { ZigValue *scalar_val = ir_resolve_const(ira, scalar, UndefOk); if (scalar_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (scalar_val->special == ConstValSpecialUndef) - return ir_const_undef(ira, &instruction->base, return_type); + return ir_const_undef(ira, &instruction->base.base, return_type); - IrInstruction *result = ir_const(ira, &instruction->base, return_type); + IrInstGen *result = ir_const(ira, &instruction->base.base, return_type); result->value->data.x_array.data.s_none.elements = create_const_vals(len_int); for (uint32_t i = 0; i < len_int; i += 1) { copy_const_val(&result->value->data.x_array.data.s_none.elements[i], scalar_val); @@ -24911,48 +25860,45 @@ static IrInstruction *ir_analyze_instruction_splat(IrAnalyze *ira, IrInstruction return result; } - return ir_build_splat_gen(ira, &instruction->base, return_type, scalar); + return ir_build_splat_gen(ira, &instruction->base.base, return_type, scalar); } -static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) { - IrInstruction *value = instruction->value->child; +static IrInstGen *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstSrcBoolNot *instruction) { + IrInstGen *value = instruction->value->child; if (type_is_invalid(value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *bool_type = ira->codegen->builtin_types.entry_bool; - IrInstruction *casted_value = ir_implicit_cast(ira, value, bool_type); + IrInstGen *casted_value = ir_implicit_cast(ira, value, bool_type); if (type_is_invalid(casted_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (instr_is_comptime(casted_value)) { ZigValue *value = ir_resolve_const(ira, casted_value, UndefBad); if (value == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_const_bool(ira, &instruction->base, !value->data.x_bool); + return ir_const_bool(ira, &instruction->base.base, !value->data.x_bool); } - IrInstruction *result = ir_build_bool_not(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, casted_value); - result->value->type = bool_type; - return result; + return ir_build_bool_not_gen(ira, &instruction->base.base, casted_value); } -static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemset *instruction) { +static IrInstGen *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstSrcMemset *instruction) { Error err; - IrInstruction *dest_ptr = instruction->dest_ptr->child; + IrInstGen *dest_ptr = instruction->dest_ptr->child; if (type_is_invalid(dest_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *byte_value = instruction->byte->child; + IrInstGen *byte_value = instruction->byte->child; if (type_is_invalid(byte_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *count_value = instruction->count->child; + IrInstGen *count_value = instruction->count->child; if (type_is_invalid(count_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *dest_uncasted_type = dest_ptr->value->type; bool dest_is_volatile = (dest_uncasted_type->id == ZigTypeIdPointer) && @@ -24963,24 +25909,24 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio uint32_t dest_align; if (dest_uncasted_type->id == ZigTypeIdPointer) { if ((err = resolve_ptr_align(ira, dest_uncasted_type, &dest_align))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else { dest_align = get_abi_alignment(ira->codegen, u8); } ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile, PtrLenUnknown, dest_align, 0, 0, false); - IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr); + IrInstGen *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr); if (type_is_invalid(casted_dest_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_byte = ir_implicit_cast(ira, byte_value, u8); + IrInstGen *casted_byte = ir_implicit_cast(ira, byte_value, u8); if (type_is_invalid(casted_byte->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_count = ir_implicit_cast(ira, count_value, usize); + IrInstGen *casted_count = ir_implicit_cast(ira, count_value, usize); if (type_is_invalid(casted_count->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; // TODO test this at comptime with u8 and non-u8 types if (instr_is_comptime(casted_dest_ptr) && @@ -24989,15 +25935,15 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio { ZigValue *dest_ptr_val = ir_resolve_const(ira, casted_dest_ptr, UndefBad); if (dest_ptr_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *byte_val = ir_resolve_const(ira, casted_byte, UndefOk); if (byte_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *count_val = ir_resolve_const(ira, casted_count, UndefBad); if (count_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (casted_dest_ptr->value->data.x_ptr.special != ConstPtrSpecialHardCodedAddr && casted_dest_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar) @@ -25042,38 +25988,35 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio size_t count = bigint_as_usize(&count_val->data.x_bigint); size_t end = start + count; if (end > bound_end) { - ir_add_error(ira, count_value, buf_sprintf("out of bounds pointer access")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &count_value->base, buf_sprintf("out of bounds pointer access")); + return ira->codegen->invalid_inst_gen; } for (size_t i = start; i < end; i += 1) { copy_const_val(&dest_elements[i], byte_val); } - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } } - IrInstruction *result = ir_build_memset(&ira->new_irb, instruction->base.scope, instruction->base.source_node, - casted_dest_ptr, casted_byte, casted_count); - result->value->type = ira->codegen->builtin_types.entry_void; - return result; + return ir_build_memset_gen(ira, &instruction->base.base, casted_dest_ptr, casted_byte, casted_count); } -static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructionMemcpy *instruction) { +static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy *instruction) { Error err; - IrInstruction *dest_ptr = instruction->dest_ptr->child; + IrInstGen *dest_ptr = instruction->dest_ptr->child; if (type_is_invalid(dest_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *src_ptr = instruction->src_ptr->child; + IrInstGen *src_ptr = instruction->src_ptr->child; if (type_is_invalid(src_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *count_value = instruction->count->child; + IrInstGen *count_value = instruction->count->child; if (type_is_invalid(count_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *u8 = ira->codegen->builtin_types.entry_u8; ZigType *dest_uncasted_type = dest_ptr->value->type; @@ -25086,7 +26029,7 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio uint32_t dest_align; if (dest_uncasted_type->id == ZigTypeIdPointer) { if ((err = resolve_ptr_align(ira, dest_uncasted_type, &dest_align))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else { dest_align = get_abi_alignment(ira->codegen, u8); } @@ -25094,7 +26037,7 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio uint32_t src_align; if (src_uncasted_type->id == ZigTypeIdPointer) { if ((err = resolve_ptr_align(ira, src_uncasted_type, &src_align))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else { src_align = get_abi_alignment(ira->codegen, u8); } @@ -25105,17 +26048,17 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio ZigType *u8_ptr_const = get_pointer_to_type_extra(ira->codegen, u8, true, src_is_volatile, PtrLenUnknown, src_align, 0, 0, false); - IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr_mut); + IrInstGen *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr_mut); if (type_is_invalid(casted_dest_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_src_ptr = ir_implicit_cast(ira, src_ptr, u8_ptr_const); + IrInstGen *casted_src_ptr = ir_implicit_cast(ira, src_ptr, u8_ptr_const); if (type_is_invalid(casted_src_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_count = ir_implicit_cast(ira, count_value, usize); + IrInstGen *casted_count = ir_implicit_cast(ira, count_value, usize); if (type_is_invalid(casted_count->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; // TODO test this at comptime with u8 and non-u8 types // TODO test with dest ptr being a global runtime variable @@ -25125,15 +26068,15 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio { ZigValue *dest_ptr_val = ir_resolve_const(ira, casted_dest_ptr, UndefBad); if (dest_ptr_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *src_ptr_val = ir_resolve_const(ira, casted_src_ptr, UndefBad); if (src_ptr_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *count_val = ir_resolve_const(ira, casted_count, UndefBad); if (count_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (dest_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { size_t count = bigint_as_usize(&count_val->data.x_bigint); @@ -25176,8 +26119,8 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio } if (dest_start + count > dest_end) { - ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds pointer access")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("out of bounds pointer access")); + return ira->codegen->invalid_inst_gen; } ZigValue *src_elements; @@ -25219,8 +26162,8 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio } if (src_start + count > src_end) { - ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds pointer access")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("out of bounds pointer access")); + return ira->codegen->invalid_inst_gen; } // TODO check for noalias violations - this should be generalized to work for any function @@ -25229,42 +26172,39 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio copy_const_val(&dest_elements[dest_start + i], &src_elements[src_start + i]); } - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } } - IrInstruction *result = ir_build_memcpy(&ira->new_irb, instruction->base.scope, instruction->base.source_node, - casted_dest_ptr, casted_src_ptr, casted_count); - result->value->type = ira->codegen->builtin_types.entry_void; - return result; + return ir_build_memcpy_gen(ira, &instruction->base.base, casted_dest_ptr, casted_src_ptr, casted_count); } -static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSliceSrc *instruction) { - IrInstruction *ptr_ptr = instruction->ptr->child; +static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *instruction) { + IrInstGen *ptr_ptr = instruction->ptr->child; if (type_is_invalid(ptr_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *ptr_ptr_type = ptr_ptr->value->type; assert(ptr_ptr_type->id == ZigTypeIdPointer); ZigType *array_type = ptr_ptr_type->data.pointer.child_type; - IrInstruction *start = instruction->start->child; + IrInstGen *start = instruction->start->child; if (type_is_invalid(start->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *usize = ira->codegen->builtin_types.entry_usize; - IrInstruction *casted_start = ir_implicit_cast(ira, start, usize); + IrInstGen *casted_start = ir_implicit_cast(ira, start, usize); if (type_is_invalid(casted_start->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *end; + IrInstGen *end; if (instruction->end) { end = instruction->end->child; if (type_is_invalid(end->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; end = ir_implicit_cast(ira, end, usize); if (type_is_invalid(end->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else { end = nullptr; } @@ -25292,8 +26232,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction PtrLenUnknown, array_type->data.pointer.explicit_alignment, 0, 0, false); } else { - ir_add_error(ira, &instruction->base, buf_sprintf("slice of single-item pointer")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("slice of single-item pointer")); + return ira->codegen->invalid_inst_gen; } } else { elem_type = array_type->data.pointer.child_type; @@ -25303,8 +26243,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction ZigType *maybe_sentineled_slice_ptr_type = array_type; non_sentinel_slice_ptr_type = adjust_ptr_sentinel(ira->codegen, maybe_sentineled_slice_ptr_type, nullptr); if (!end) { - ir_add_error(ira, &instruction->base, buf_sprintf("slice of pointer must include end value")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("slice of pointer must include end value")); + return ira->codegen->invalid_inst_gen; } } } else if (is_slice(array_type)) { @@ -25312,23 +26252,23 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction non_sentinel_slice_ptr_type = adjust_ptr_sentinel(ira->codegen, maybe_sentineled_slice_ptr_type, nullptr); elem_type = non_sentinel_slice_ptr_type->data.pointer.child_type; } else { - ir_add_error(ira, &instruction->base, + ir_add_error(ira, &instruction->base.base, buf_sprintf("slice of non-array type '%s'", buf_ptr(&array_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *return_type; ZigValue *sentinel_val = nullptr; if (instruction->sentinel) { - IrInstruction *uncasted_sentinel = instruction->sentinel->child; + IrInstGen *uncasted_sentinel = instruction->sentinel->child; if (type_is_invalid(uncasted_sentinel->value->type)) - return ira->codegen->invalid_instruction; - IrInstruction *sentinel = ir_implicit_cast(ira, uncasted_sentinel, elem_type); + return ira->codegen->invalid_inst_gen; + IrInstGen *sentinel = ir_implicit_cast(ira, uncasted_sentinel, elem_type); if (type_is_invalid(sentinel->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; sentinel_val = ir_resolve_const(ira, sentinel, UndefBad); if (sentinel_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *slice_ptr_type = adjust_ptr_sentinel(ira->codegen, non_sentinel_slice_ptr_type, sentinel_val); return_type = get_slice_type(ira->codegen, slice_ptr_type); } else { @@ -25350,9 +26290,9 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction if (array_type->id == ZigTypeIdPointer) { ZigType *child_array_type = array_type->data.pointer.child_type; assert(child_array_type->id == ZigTypeIdArray); - parent_ptr = const_ptr_pointee(ira, ira->codegen, ptr_ptr->value, instruction->base.source_node); + parent_ptr = const_ptr_pointee(ira, ira->codegen, ptr_ptr->value, instruction->base.base.source_node); if (parent_ptr == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (parent_ptr->special == ConstValSpecialUndef) { @@ -25361,26 +26301,26 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction rel_end = SIZE_MAX; ptr_is_undef = true; } else { - array_val = const_ptr_pointee(ira, ira->codegen, parent_ptr, instruction->base.source_node); + array_val = const_ptr_pointee(ira, ira->codegen, parent_ptr, instruction->base.base.source_node); if (array_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; rel_end = child_array_type->data.array.len; abs_offset = 0; } } else { - array_val = const_ptr_pointee(ira, ira->codegen, ptr_ptr->value, instruction->base.source_node); + array_val = const_ptr_pointee(ira, ira->codegen, ptr_ptr->value, instruction->base.base.source_node); if (array_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; rel_end = array_type->data.array.len; parent_ptr = nullptr; abs_offset = 0; } } else if (array_type->id == ZigTypeIdPointer) { assert(array_type->data.pointer.ptr_len == PtrLenUnknown); - parent_ptr = const_ptr_pointee(ira, ira->codegen, ptr_ptr->value, instruction->base.source_node); + parent_ptr = const_ptr_pointee(ira, ira->codegen, ptr_ptr->value, instruction->base.base.source_node); if (parent_ptr == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (parent_ptr->special == ConstValSpecialUndef) { array_val = nullptr; @@ -25426,19 +26366,19 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction zig_panic("TODO slice of null ptr"); } } else if (is_slice(array_type)) { - ZigValue *slice_ptr = const_ptr_pointee(ira, ira->codegen, ptr_ptr->value, instruction->base.source_node); + ZigValue *slice_ptr = const_ptr_pointee(ira, ira->codegen, ptr_ptr->value, instruction->base.base.source_node); if (slice_ptr == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (slice_ptr->special == ConstValSpecialUndef) { - ir_add_error(ira, &instruction->base, buf_sprintf("slice of undefined")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("slice of undefined")); + return ira->codegen->invalid_inst_gen; } parent_ptr = slice_ptr->data.x_struct.fields[slice_ptr_index]; if (parent_ptr->special == ConstValSpecialUndef) { - ir_add_error(ira, &instruction->base, buf_sprintf("slice of undefined")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("slice of undefined")); + return ira->codegen->invalid_inst_gen; } ZigValue *len_val = slice_ptr->data.x_struct.fields[slice_len_index]; @@ -25481,37 +26421,37 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction ZigValue *start_val = ir_resolve_const(ira, casted_start, UndefBad); if (!start_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; uint64_t start_scalar = bigint_as_u64(&start_val->data.x_bigint); if (!ptr_is_undef && start_scalar > rel_end) { - ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("out of bounds slice")); + return ira->codegen->invalid_inst_gen; } uint64_t end_scalar = rel_end; if (end) { ZigValue *end_val = ir_resolve_const(ira, end, UndefBad); if (!end_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; end_scalar = bigint_as_u64(&end_val->data.x_bigint); } if (!ptr_is_undef) { if (end_scalar > rel_end) { - ir_add_error(ira, &instruction->base, buf_sprintf("out of bounds slice")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("out of bounds slice")); + return ira->codegen->invalid_inst_gen; } if (start_scalar > end_scalar) { - ir_add_error(ira, &instruction->base, buf_sprintf("slice start is greater than end")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("slice start is greater than end")); + return ira->codegen->invalid_inst_gen; } } if (ptr_is_undef && start_scalar != end_scalar) { - ir_add_error(ira, &instruction->base, buf_sprintf("non-zero length slice of undefined pointer")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("non-zero length slice of undefined pointer")); + return ira->codegen->invalid_inst_gen; } - IrInstruction *result = ir_const(ira, &instruction->base, return_type); + IrInstGen *result = ir_const(ira, &instruction->base.base, return_type); ZigValue *out_val = result->value; out_val->data.x_struct.fields = alloc_const_vals_ptrs(2); @@ -25568,28 +26508,28 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction return result; } - IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, + IrInstGen *result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc, return_type, nullptr, true, true); - if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) { + if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) { return result_loc; } - return ir_build_slice_gen(ira, &instruction->base, return_type, + return ir_build_slice_gen(ira, &instruction->base.base, return_type, ptr_ptr, casted_start, end, instruction->safety_check_on, result_loc); } -static IrInstruction *ir_analyze_instruction_member_count(IrAnalyze *ira, IrInstructionMemberCount *instruction) { +static IrInstGen *ir_analyze_instruction_member_count(IrAnalyze *ira, IrInstSrcMemberCount *instruction) { Error err; - IrInstruction *container = instruction->container->child; + IrInstGen *container = instruction->container->child; if (type_is_invalid(container->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *container_type = ir_resolve_type(ira, container); if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; uint64_t result; if (type_is_invalid(container_type)) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else if (container_type->id == ZigTypeIdEnum) { result = container_type->data.enumeration.src_field_count; } else if (container_type->id == ZigTypeIdStruct) { @@ -25597,135 +26537,135 @@ static IrInstruction *ir_analyze_instruction_member_count(IrAnalyze *ira, IrInst } else if (container_type->id == ZigTypeIdUnion) { result = container_type->data.unionation.src_field_count; } else if (container_type->id == ZigTypeIdErrorSet) { - if (!resolve_inferred_error_set(ira->codegen, container_type, instruction->base.source_node)) { - return ira->codegen->invalid_instruction; + if (!resolve_inferred_error_set(ira->codegen, container_type, instruction->base.base.source_node)) { + return ira->codegen->invalid_inst_gen; } if (type_is_global_error_set(container_type)) { - ir_add_error(ira, &instruction->base, buf_sprintf("global error set member count not available at comptime")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("global error set member count not available at comptime")); + return ira->codegen->invalid_inst_gen; } result = container_type->data.error_set.err_count; } else { - ir_add_error(ira, &instruction->base, buf_sprintf("no value count available for type '%s'", buf_ptr(&container_type->name))); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("no value count available for type '%s'", buf_ptr(&container_type->name))); + return ira->codegen->invalid_inst_gen; } - return ir_const_unsigned(ira, &instruction->base, result); + return ir_const_unsigned(ira, &instruction->base.base, result); } -static IrInstruction *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInstructionMemberType *instruction) { +static IrInstGen *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInstSrcMemberType *instruction) { Error err; - IrInstruction *container_type_value = instruction->container_type->child; + IrInstGen *container_type_value = instruction->container_type->child; ZigType *container_type = ir_resolve_type(ira, container_type_value); if (type_is_invalid(container_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; uint64_t member_index; - IrInstruction *index_value = instruction->member_index->child; + IrInstGen *index_value = instruction->member_index->child; if (!ir_resolve_usize(ira, index_value, &member_index)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (container_type->id == ZigTypeIdStruct) { if (member_index >= container_type->data.structure.src_field_count) { - ir_add_error(ira, index_value, + ir_add_error(ira, &index_value->base, buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", member_index, buf_ptr(&container_type->name), container_type->data.structure.src_field_count)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } TypeStructField *field = container_type->data.structure.fields[member_index]; - return ir_const_type(ira, &instruction->base, field->type_entry); + return ir_const_type(ira, &instruction->base.base, field->type_entry); } else if (container_type->id == ZigTypeIdUnion) { if (member_index >= container_type->data.unionation.src_field_count) { - ir_add_error(ira, index_value, + ir_add_error(ira, &index_value->base, buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", member_index, buf_ptr(&container_type->name), container_type->data.unionation.src_field_count)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } TypeUnionField *field = &container_type->data.unionation.fields[member_index]; - return ir_const_type(ira, &instruction->base, field->type_entry); + return ir_const_type(ira, &instruction->base.base, field->type_entry); } else { - ir_add_error(ira, container_type_value, + ir_add_error(ira, &container_type_value->base, buf_sprintf("type '%s' does not support @memberType", buf_ptr(&container_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } -static IrInstruction *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInstructionMemberName *instruction) { +static IrInstGen *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInstSrcMemberName *instruction) { Error err; - IrInstruction *container_type_value = instruction->container_type->child; + IrInstGen *container_type_value = instruction->container_type->child; ZigType *container_type = ir_resolve_type(ira, container_type_value); if (type_is_invalid(container_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; uint64_t member_index; - IrInstruction *index_value = instruction->member_index->child; + IrInstGen *index_value = instruction->member_index->child; if (!ir_resolve_usize(ira, index_value, &member_index)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (container_type->id == ZigTypeIdStruct) { if (member_index >= container_type->data.structure.src_field_count) { - ir_add_error(ira, index_value, + ir_add_error(ira, &index_value->base, buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", member_index, buf_ptr(&container_type->name), container_type->data.structure.src_field_count)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } TypeStructField *field = container_type->data.structure.fields[member_index]; - IrInstruction *result = ir_const(ira, &instruction->base, nullptr); + IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); init_const_str_lit(ira->codegen, result->value, field->name); return result; } else if (container_type->id == ZigTypeIdEnum) { if (member_index >= container_type->data.enumeration.src_field_count) { - ir_add_error(ira, index_value, + ir_add_error(ira, &index_value->base, buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", member_index, buf_ptr(&container_type->name), container_type->data.enumeration.src_field_count)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } TypeEnumField *field = &container_type->data.enumeration.fields[member_index]; - IrInstruction *result = ir_const(ira, &instruction->base, nullptr); + IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); init_const_str_lit(ira->codegen, result->value, field->name); return result; } else if (container_type->id == ZigTypeIdUnion) { if (member_index >= container_type->data.unionation.src_field_count) { - ir_add_error(ira, index_value, + ir_add_error(ira, &index_value->base, buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members", member_index, buf_ptr(&container_type->name), container_type->data.unionation.src_field_count)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } TypeUnionField *field = &container_type->data.unionation.fields[member_index]; - IrInstruction *result = ir_const(ira, &instruction->base, nullptr); + IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); init_const_str_lit(ira->codegen, result->value, field->name); return result; } else { - ir_add_error(ira, container_type_value, + ir_add_error(ira, &container_type_value->base, buf_sprintf("type '%s' does not support @memberName", buf_ptr(&container_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } -static IrInstruction *ir_analyze_instruction_has_field(IrAnalyze *ira, IrInstructionHasField *instruction) { +static IrInstGen *ir_analyze_instruction_has_field(IrAnalyze *ira, IrInstSrcHasField *instruction) { Error err; ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child); if (type_is_invalid(container_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if ((err = type_resolve(ira->codegen, container_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; Buf *field_name = ir_resolve_str(ira, instruction->field_name->child); if (field_name == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; bool result; if (container_type->id == ZigTypeIdStruct) { @@ -25735,91 +26675,77 @@ static IrInstruction *ir_analyze_instruction_has_field(IrAnalyze *ira, IrInstruc } else if (container_type->id == ZigTypeIdUnion) { result = find_union_type_field(container_type, field_name) != nullptr; } else { - ir_add_error(ira, instruction->container_type, + ir_add_error(ira, &instruction->container_type->base, buf_sprintf("type '%s' does not support @hasField", buf_ptr(&container_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - return ir_const_bool(ira, &instruction->base, result); + return ir_const_bool(ira, &instruction->base.base, result); } -static IrInstruction *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstructionBreakpoint *instruction) { - IrInstruction *result = ir_build_breakpoint(&ira->new_irb, - instruction->base.scope, instruction->base.source_node); - result->value->type = ira->codegen->builtin_types.entry_void; - return result; +static IrInstGen *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstSrcBreakpoint *instruction) { + return ir_build_breakpoint_gen(ira, &instruction->base.base); } -static IrInstruction *ir_analyze_instruction_return_address(IrAnalyze *ira, IrInstructionReturnAddress *instruction) { - IrInstruction *result = ir_build_return_address(&ira->new_irb, - instruction->base.scope, instruction->base.source_node); - result->value->type = ira->codegen->builtin_types.entry_usize; - return result; +static IrInstGen *ir_analyze_instruction_return_address(IrAnalyze *ira, IrInstSrcReturnAddress *instruction) { + return ir_build_return_address_gen(ira, &instruction->base.base); } -static IrInstruction *ir_analyze_instruction_frame_address(IrAnalyze *ira, IrInstructionFrameAddress *instruction) { - IrInstruction *result = ir_build_frame_address(&ira->new_irb, - instruction->base.scope, instruction->base.source_node); - result->value->type = ira->codegen->builtin_types.entry_usize; - return result; +static IrInstGen *ir_analyze_instruction_frame_address(IrAnalyze *ira, IrInstSrcFrameAddress *instruction) { + return ir_build_frame_address_gen(ira, &instruction->base.base); } -static IrInstruction *ir_analyze_instruction_frame_handle(IrAnalyze *ira, IrInstructionFrameHandle *instruction) { - ZigFn *fn = exec_fn_entry(ira->new_irb.exec); - ir_assert(fn != nullptr, &instruction->base); +static IrInstGen *ir_analyze_instruction_frame_handle(IrAnalyze *ira, IrInstSrcFrameHandle *instruction) { + ZigFn *fn = ira->new_irb.exec->fn_entry; + ir_assert(fn != nullptr, &instruction->base.base); if (fn->inferred_async_node == nullptr) { - fn->inferred_async_node = instruction->base.source_node; + fn->inferred_async_node = instruction->base.base.source_node; } ZigType *frame_type = get_fn_frame_type(ira->codegen, fn); ZigType *ptr_frame_type = get_pointer_to_type(ira->codegen, frame_type, false); - IrInstruction *result = ir_build_handle(&ira->new_irb, instruction->base.scope, instruction->base.source_node); - result->value->type = ptr_frame_type; - return result; + return ir_build_handle_gen(ira, &instruction->base.base, ptr_frame_type); } -static IrInstruction *ir_analyze_instruction_frame_type(IrAnalyze *ira, IrInstructionFrameType *instruction) { +static IrInstGen *ir_analyze_instruction_frame_type(IrAnalyze *ira, IrInstSrcFrameType *instruction) { ZigFn *fn = ir_resolve_fn(ira, instruction->fn->child); if (fn == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (fn->type_entry->data.fn.is_generic) { - ir_add_error(ira, &instruction->base, + ir_add_error(ira, &instruction->base.base, buf_sprintf("@Frame() of generic function")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *ty = get_fn_frame_type(ira->codegen, fn); - return ir_const_type(ira, &instruction->base, ty); + return ir_const_type(ira, &instruction->base.base, ty); } -static IrInstruction *ir_analyze_instruction_frame_size(IrAnalyze *ira, IrInstructionFrameSizeSrc *instruction) { - IrInstruction *fn = instruction->fn->child; +static IrInstGen *ir_analyze_instruction_frame_size(IrAnalyze *ira, IrInstSrcFrameSize *instruction) { + IrInstGen *fn = instruction->fn->child; if (type_is_invalid(fn->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (fn->value->type->id != ZigTypeIdFn) { - ir_add_error(ira, fn, + ir_add_error(ira, &fn->base, buf_sprintf("expected function, found '%s'", buf_ptr(&fn->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ira->codegen->need_frame_size_prefix_data = true; - IrInstruction *result = ir_build_frame_size_gen(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, fn); - result->value->type = ira->codegen->builtin_types.entry_usize; - return result; + return ir_build_frame_size_gen(ira, &instruction->base.base, fn); } -static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) { +static IrInstGen *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstSrcAlignOf *instruction) { // Here we create a lazy value in order to avoid resolving the alignment of the type // immediately. This avoids false positive dependency loops such as: // const Node = struct { // field: []align(@alignOf(Node)) Node, // }; - IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_num_lit_int); + IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_num_lit_int); result->value->special = ConstValSpecialLazy; LazyValueAlignOf *lazy_align_of = allocate(1, "LazyValueAlignOf"); @@ -25829,41 +26755,41 @@ static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruct lazy_align_of->target_type = instruction->type_value->child; if (ir_resolve_type_lazy(ira, lazy_align_of->target_type) == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return result; } -static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstructionOverflowOp *instruction) { +static IrInstGen *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstSrcOverflowOp *instruction) { Error err; - IrInstruction *type_value = instruction->type_value->child; + IrInstGen *type_value = instruction->type_value->child; if (type_is_invalid(type_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *dest_type = ir_resolve_type(ira, type_value); if (type_is_invalid(dest_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (dest_type->id != ZigTypeIdInt) { - ir_add_error(ira, type_value, + ir_add_error(ira, &type_value->base, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *op1 = instruction->op1->child; + IrInstGen *op1 = instruction->op1->child; if (type_is_invalid(op1->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, dest_type); + IrInstGen *casted_op1 = ir_implicit_cast(ira, op1, dest_type); if (type_is_invalid(casted_op1->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *op2 = instruction->op2->child; + IrInstGen *op2 = instruction->op2->child; if (type_is_invalid(op2->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_op2; + IrInstGen *casted_op2; if (instruction->op == IrOverflowOpShl) { ZigType *shift_amt_type = get_smallest_unsigned_int_type(ira->codegen, dest_type->data.integral.bit_count - 1); @@ -25872,17 +26798,17 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr casted_op2 = ir_implicit_cast(ira, op2, dest_type); } if (type_is_invalid(casted_op2->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *result_ptr = instruction->result_ptr->child; + IrInstGen *result_ptr = instruction->result_ptr->child; if (type_is_invalid(result_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *expected_ptr_type; if (result_ptr->value->type->id == ZigTypeIdPointer) { uint32_t alignment; if ((err = resolve_ptr_align(ira, result_ptr->value->type, &alignment))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; expected_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_type, false, result_ptr->value->type->data.pointer.is_volatile, PtrLenSingle, @@ -25891,9 +26817,9 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr expected_ptr_type = get_pointer_to_type(ira->codegen, dest_type, false); } - IrInstruction *casted_result_ptr = ir_implicit_cast(ira, result_ptr, expected_ptr_type); + IrInstGen *casted_result_ptr = ir_implicit_cast(ira, result_ptr, expected_ptr_type); if (type_is_invalid(casted_result_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2) && @@ -25901,22 +26827,22 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr { ZigValue *op1_val = ir_resolve_const(ira, casted_op1, UndefBad); if (op1_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *op2_val = ir_resolve_const(ira, casted_op2, UndefBad); if (op2_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *result_val = ir_resolve_const(ira, casted_result_ptr, UndefBad); if (result_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; BigInt *op1_bigint = &op1_val->data.x_bigint; BigInt *op2_bigint = &op2_val->data.x_bigint; ZigValue *pointee_val = const_ptr_pointee(ira, ira->codegen, result_val, - casted_result_ptr->source_node); + casted_result_ptr->base.source_node); if (pointee_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; BigInt *dest_bigint = &pointee_val->data.x_bigint; switch (instruction->op) { case IrOverflowOpAdd: @@ -25943,17 +26869,14 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr dest_type->data.integral.is_signed); } pointee_val->special = ConstValSpecialStatic; - return ir_const_bool(ira, &instruction->base, result_bool); + return ir_const_bool(ira, &instruction->base.base, result_bool); } - IrInstruction *result = ir_build_overflow_op(&ira->new_irb, - instruction->base.scope, instruction->base.source_node, - instruction->op, type_value, casted_op1, casted_op2, casted_result_ptr, dest_type); - result->value->type = ira->codegen->builtin_types.entry_bool; - return result; + return ir_build_overflow_op_gen(ira, &instruction->base.base, instruction->op, + casted_op1, casted_op2, casted_result_ptr, dest_type); } -static void ir_eval_mul_add(IrAnalyze *ira, IrInstructionMulAdd *source_instr, ZigType *float_type, +static void ir_eval_mul_add(IrAnalyze *ira, IrInstSrcMulAdd *source_instr, ZigType *float_type, ZigValue *op1, ZigValue *op2, ZigValue *op3, ZigValue *out_val) { if (float_type->id == ZigTypeIdComptimeFloat) { f128M_mulAdd(&out_val->data.x_bigfloat.value, &op1->data.x_bigfloat.value, &op2->data.x_bigfloat.value, @@ -25980,61 +26903,61 @@ static void ir_eval_mul_add(IrAnalyze *ira, IrInstructionMulAdd *source_instr, Z } } -static IrInstruction *ir_analyze_instruction_mul_add(IrAnalyze *ira, IrInstructionMulAdd *instruction) { - IrInstruction *type_value = instruction->type_value->child; +static IrInstGen *ir_analyze_instruction_mul_add(IrAnalyze *ira, IrInstSrcMulAdd *instruction) { + IrInstGen *type_value = instruction->type_value->child; if (type_is_invalid(type_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *expr_type = ir_resolve_type(ira, type_value); if (type_is_invalid(expr_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; // Only allow float types, and vectors of floats. ZigType *float_type = (expr_type->id == ZigTypeIdVector) ? expr_type->data.vector.elem_type : expr_type; if (float_type->id != ZigTypeIdFloat) { - ir_add_error(ira, type_value, + ir_add_error(ira, &type_value->base, buf_sprintf("expected float or vector of float type, found '%s'", buf_ptr(&float_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *op1 = instruction->op1->child; + IrInstGen *op1 = instruction->op1->child; if (type_is_invalid(op1->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, expr_type); + IrInstGen *casted_op1 = ir_implicit_cast(ira, op1, expr_type); if (type_is_invalid(casted_op1->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *op2 = instruction->op2->child; + IrInstGen *op2 = instruction->op2->child; if (type_is_invalid(op2->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, expr_type); + IrInstGen *casted_op2 = ir_implicit_cast(ira, op2, expr_type); if (type_is_invalid(casted_op2->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *op3 = instruction->op3->child; + IrInstGen *op3 = instruction->op3->child; if (type_is_invalid(op3->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_op3 = ir_implicit_cast(ira, op3, expr_type); + IrInstGen *casted_op3 = ir_implicit_cast(ira, op3, expr_type); if (type_is_invalid(casted_op3->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2) && instr_is_comptime(casted_op3)) { ZigValue *op1_const = ir_resolve_const(ira, casted_op1, UndefBad); if (!op1_const) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *op2_const = ir_resolve_const(ira, casted_op2, UndefBad); if (!op2_const) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *op3_const = ir_resolve_const(ira, casted_op3, UndefBad); if (!op3_const) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *result = ir_const(ira, &instruction->base, expr_type); + IrInstGen *result = ir_const(ira, &instruction->base.base, expr_type); ZigValue *out_val = result->value; if (expr_type->id == ZigTypeIdVector) { @@ -26065,63 +26988,59 @@ static IrInstruction *ir_analyze_instruction_mul_add(IrAnalyze *ira, IrInstructi return result; } - IrInstruction *result = ir_build_mul_add(&ira->new_irb, - instruction->base.scope, instruction->base.source_node, - type_value, casted_op1, casted_op2, casted_op3); - result->value->type = expr_type; - return result; + return ir_build_mul_add_gen(ira, &instruction->base.base, casted_op1, casted_op2, casted_op3, expr_type); } -static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstructionTestErrSrc *instruction) { - IrInstruction *base_ptr = instruction->base_ptr->child; +static IrInstGen *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstSrcTestErr *instruction) { + IrInstGen *base_ptr = instruction->base_ptr->child; if (type_is_invalid(base_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *value; + IrInstGen *value; if (instruction->base_ptr_is_payload) { value = base_ptr; } else { - value = ir_get_deref(ira, &instruction->base, base_ptr, nullptr); + value = ir_get_deref(ira, &instruction->base.base, base_ptr, nullptr); } ZigType *type_entry = value->value->type; if (type_is_invalid(type_entry)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (type_entry->id == ZigTypeIdErrorUnion) { if (instr_is_comptime(value)) { ZigValue *err_union_val = ir_resolve_const(ira, value, UndefBad); if (!err_union_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (err_union_val->special != ConstValSpecialRuntime) { ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set; - return ir_const_bool(ira, &instruction->base, (err != nullptr)); + return ir_const_bool(ira, &instruction->base.base, (err != nullptr)); } } if (instruction->resolve_err_set) { ZigType *err_set_type = type_entry->data.error_union.err_set_type; - if (!resolve_inferred_error_set(ira->codegen, err_set_type, instruction->base.source_node)) { - return ira->codegen->invalid_instruction; + if (!resolve_inferred_error_set(ira->codegen, err_set_type, instruction->base.base.source_node)) { + return ira->codegen->invalid_inst_gen; } if (!type_is_global_error_set(err_set_type) && err_set_type->data.error_set.err_count == 0) { assert(!err_set_type->data.error_set.incomplete); - return ir_const_bool(ira, &instruction->base, false); + return ir_const_bool(ira, &instruction->base.base, false); } } - return ir_build_test_err_gen(ira, &instruction->base, value); + return ir_build_test_err_gen(ira, &instruction->base.base, value); } else if (type_entry->id == ZigTypeIdErrorSet) { - return ir_const_bool(ira, &instruction->base, true); + return ir_const_bool(ira, &instruction->base.base, true); } else { - return ir_const_bool(ira, &instruction->base, false); + return ir_const_bool(ira, &instruction->base.base, false); } } -static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *base_ptr, bool initializing) +static IrInstGen *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *base_ptr, bool initializing) { ZigType *ptr_type = base_ptr->value->type; @@ -26130,12 +27049,12 @@ static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction * ZigType *type_entry = ptr_type->data.pointer.child_type; if (type_is_invalid(type_entry)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (type_entry->id != ZigTypeIdErrorUnion) { - ir_add_error(ira, base_ptr, + ir_add_error(ira, &base_ptr->base, buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *err_set_type = type_entry->data.error_union.err_set_type; @@ -26146,13 +27065,13 @@ static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction * if (instr_is_comptime(base_ptr)) { ZigValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad); if (!ptr_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar && ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { ZigValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); if (err_union_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (initializing && err_union_val->special == ConstValSpecialUndef) { ZigValue *vals = create_const_vals(2); @@ -26175,11 +27094,10 @@ static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction * } ir_assert(err_union_val->special != ConstValSpecialRuntime, source_instr); - IrInstruction *result; + IrInstGen *result; if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) { - result = ir_build_unwrap_err_code(&ira->new_irb, source_instr->scope, - source_instr->source_node, base_ptr); - result->value->type = result_type; + result = ir_build_unwrap_err_code_gen(ira, source_instr->scope, + source_instr->source_node, base_ptr, result_type); result->value->special = ConstValSpecialStatic; } else { result = ir_const(ira, source_instr, result_type); @@ -26192,23 +27110,18 @@ static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction * } } - IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb, - source_instr->scope, source_instr->source_node, base_ptr); - result->value->type = result_type; - return result; + return ir_build_unwrap_err_code_gen(ira, source_instr->scope, source_instr->source_node, base_ptr, result_type); } -static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, - IrInstructionUnwrapErrCode *instruction) -{ - IrInstruction *base_ptr = instruction->err_union_ptr->child; +static IrInstGen *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrInstSrcUnwrapErrCode *instruction) { + IrInstGen *base_ptr = instruction->err_union_ptr->child; if (type_is_invalid(base_ptr->value->type)) - return ira->codegen->invalid_instruction; - return ir_analyze_unwrap_err_code(ira, &instruction->base, base_ptr, false); + return ira->codegen->invalid_inst_gen; + return ir_analyze_unwrap_err_code(ira, &instruction->base.base, base_ptr, false); } -static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *base_ptr, bool safety_check_on, bool initializing) +static IrInstGen *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *base_ptr, bool safety_check_on, bool initializing) { ZigType *ptr_type = base_ptr->value->type; @@ -26217,17 +27130,17 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct ZigType *type_entry = ptr_type->data.pointer.child_type; if (type_is_invalid(type_entry)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (type_entry->id != ZigTypeIdErrorUnion) { - ir_add_error(ira, base_ptr, + ir_add_error(ira, &base_ptr->base, buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *payload_type = type_entry->data.error_union.payload_type; if (type_is_invalid(payload_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type, ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, @@ -26236,11 +27149,11 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct if (instr_is_comptime(base_ptr)) { ZigValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad); if (!ptr_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) { ZigValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); if (err_union_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (initializing && err_union_val->special == ConstValSpecialUndef) { ZigValue *vals = create_const_vals(2); ZigValue *err_set_val = &vals[0]; @@ -26263,14 +27176,13 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct if (err != nullptr) { ir_add_error(ira, source_instr, buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *result; + IrInstGen *result; if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) { - result = ir_build_unwrap_err_payload(&ira->new_irb, source_instr->scope, - source_instr->source_node, base_ptr, safety_check_on, initializing); - result->value->type = result_type; + result = ir_build_unwrap_err_payload_gen(ira, source_instr->scope, + source_instr->source_node, base_ptr, safety_check_on, initializing, result_type); result->value->special = ConstValSpecialStatic; } else { result = ir_const(ira, source_instr, result_type); @@ -26283,28 +27195,26 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct } } - IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb, source_instr->scope, - source_instr->source_node, base_ptr, safety_check_on, initializing); - result->value->type = result_type; - return result; + return ir_build_unwrap_err_payload_gen(ira, source_instr->scope, source_instr->source_node, + base_ptr, safety_check_on, initializing, result_type); } -static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, - IrInstructionUnwrapErrPayload *instruction) +static IrInstGen *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, + IrInstSrcUnwrapErrPayload *instruction) { assert(instruction->value->child); - IrInstruction *value = instruction->value->child; + IrInstGen *value = instruction->value->child; if (type_is_invalid(value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_analyze_unwrap_error_payload(ira, &instruction->base, value, instruction->safety_check_on, false); + return ir_analyze_unwrap_error_payload(ira, &instruction->base.base, value, instruction->safety_check_on, false); } -static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) { - AstNode *proto_node = instruction->base.source_node; +static IrInstGen *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstSrcFnProto *instruction) { + AstNode *proto_node = instruction->base.base.source_node; assert(proto_node->type == NodeTypeFnProto); - IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type); + IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_type); result->value->special = ConstValSpecialLazy; LazyValueFnType *lazy_fn_type = allocate(1, "LazyValueFnType"); @@ -26313,29 +27223,29 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct lazy_fn_type->base.id = LazyValueIdFnType; if (proto_node->data.fn_proto.auto_err_set) { - ir_add_error(ira, &instruction->base, + ir_add_error(ira, &instruction->base.base, buf_sprintf("inferring error set of return type valid only for function definitions")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } lazy_fn_type->cc = cc_from_fn_proto(&proto_node->data.fn_proto); if (instruction->callconv_value != nullptr) { ZigType *cc_enum_type = get_builtin_type(ira->codegen, "CallingConvention"); - IrInstruction *casted_value = ir_implicit_cast(ira, instruction->callconv_value, cc_enum_type); + IrInstGen *casted_value = ir_implicit_cast(ira, instruction->callconv_value->child, cc_enum_type); if (type_is_invalid(casted_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *const_value = ir_resolve_const(ira, casted_value, UndefBad); if (const_value == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; lazy_fn_type->cc = (CallingConvention)bigint_as_u32(&const_value->data.x_enum_tag); } size_t param_count = proto_node->data.fn_proto.params.length; lazy_fn_type->proto_node = proto_node; - lazy_fn_type->param_types = allocate(param_count); + lazy_fn_type->param_types = allocate(param_count); for (size_t param_index = 0; param_index < param_count; param_index += 1) { AstNode *param_node = proto_node->data.fn_proto.params.at(param_index); @@ -26360,63 +27270,63 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct return result; } - IrInstruction *param_type_value = instruction->param_types[param_index]->child; + IrInstGen *param_type_value = instruction->param_types[param_index]->child; if (type_is_invalid(param_type_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (ir_resolve_const(ira, param_type_value, LazyOk) == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; lazy_fn_type->param_types[param_index] = param_type_value; } if (instruction->align_value != nullptr) { lazy_fn_type->align_inst = instruction->align_value->child; if (ir_resolve_const(ira, lazy_fn_type->align_inst, LazyOk) == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } lazy_fn_type->return_type = instruction->return_type->child; if (ir_resolve_const(ira, lazy_fn_type->return_type, LazyOk) == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return result; } -static IrInstruction *ir_analyze_instruction_test_comptime(IrAnalyze *ira, IrInstructionTestComptime *instruction) { - IrInstruction *value = instruction->value->child; +static IrInstGen *ir_analyze_instruction_test_comptime(IrAnalyze *ira, IrInstSrcTestComptime *instruction) { + IrInstGen *value = instruction->value->child; if (type_is_invalid(value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_const_bool(ira, &instruction->base, instr_is_comptime(value)); + return ir_const_bool(ira, &instruction->base.base, instr_is_comptime(value)); } -static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, - IrInstructionCheckSwitchProngs *instruction) +static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, + IrInstSrcCheckSwitchProngs *instruction) { - IrInstruction *target_value = instruction->target_value->child; + IrInstGen *target_value = instruction->target_value->child; ZigType *switch_type = target_value->value->type; if (type_is_invalid(switch_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (switch_type->id == ZigTypeIdEnum) { HashMap field_prev_uses = {}; field_prev_uses.init(switch_type->data.enumeration.src_field_count); for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) { - IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i]; + IrInstSrcCheckSwitchProngsRange *range = &instruction->ranges[range_i]; - IrInstruction *start_value_uncasted = range->start->child; + IrInstGen *start_value_uncasted = range->start->child; if (type_is_invalid(start_value_uncasted->value->type)) - return ira->codegen->invalid_instruction; - IrInstruction *start_value = ir_implicit_cast(ira, start_value_uncasted, switch_type); + return ira->codegen->invalid_inst_gen; + IrInstGen *start_value = ir_implicit_cast(ira, start_value_uncasted, switch_type); if (type_is_invalid(start_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *end_value_uncasted = range->end->child; + IrInstGen *end_value_uncasted = range->end->child; if (type_is_invalid(end_value_uncasted->value->type)) - return ira->codegen->invalid_instruction; - IrInstruction *end_value = ir_implicit_cast(ira, end_value_uncasted, switch_type); + return ira->codegen->invalid_inst_gen; + IrInstGen *end_value = ir_implicit_cast(ira, end_value_uncasted, switch_type); if (type_is_invalid(end_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; assert(start_value->value->type->id == ZigTypeIdEnum); BigInt start_index; @@ -26427,7 +27337,7 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, bigint_init_bigint(&end_index, &end_value->value->data.x_enum_tag); if (bigint_cmp(&start_index, &end_index) == CmpGT) { - ir_add_error(ira, start_value, + ir_add_error(ira, &start_value->base, buf_sprintf("range start value is greater than the end value")); } @@ -26438,12 +27348,12 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, if (cmp == CmpGT) { break; } - auto entry = field_prev_uses.put_unique(field_index, start_value->source_node); + auto entry = field_prev_uses.put_unique(field_index, start_value->base.source_node); if (entry) { AstNode *prev_node = entry->value; TypeEnumField *enum_field = find_enum_field_by_tag(switch_type, &field_index); assert(enum_field != nullptr); - ErrorMsg *msg = ir_add_error(ira, start_value, + ErrorMsg *msg = ir_add_error(ira, &start_value->base, buf_sprintf("duplicate switch value: '%s.%s'", buf_ptr(&switch_type->name), buf_ptr(enum_field->name))); add_error_note(ira->codegen, msg, prev_node, buf_sprintf("other value is here")); @@ -26451,79 +27361,96 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, bigint_incr(&field_index); } } - if (!instruction->have_else_prong) { - if (switch_type->data.enumeration.layout == ContainerLayoutExtern) { - ir_add_error(ira, &instruction->base, - buf_sprintf("switch on an extern enum must have an else prong")); + if (instruction->have_underscore_prong) { + if (!switch_type->data.enumeration.non_exhaustive){ + ir_add_error(ira, &instruction->base.base, + buf_sprintf("switch on non-exhaustive enum has `_` prong")); + } + for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) { + TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i]; + if (buf_eql_str(enum_field->name, "_")) + continue; + + auto entry = field_prev_uses.maybe_get(enum_field->value); + if (!entry) { + ir_add_error(ira, &instruction->base.base, + buf_sprintf("enumeration value '%s.%s' not handled in switch", buf_ptr(&switch_type->name), + buf_ptr(enum_field->name))); + } + } + } else if (!instruction->have_else_prong) { + if (switch_type->data.enumeration.non_exhaustive) { + ir_add_error(ira, &instruction->base.base, + buf_sprintf("switch on non-exhaustive enum must include `else` or `_` prong")); } for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) { TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i]; auto entry = field_prev_uses.maybe_get(enum_field->value); if (!entry) { - ir_add_error(ira, &instruction->base, + ir_add_error(ira, &instruction->base.base, buf_sprintf("enumeration value '%s.%s' not handled in switch", buf_ptr(&switch_type->name), buf_ptr(enum_field->name))); } } } } else if (switch_type->id == ZigTypeIdErrorSet) { - if (!resolve_inferred_error_set(ira->codegen, switch_type, target_value->source_node)) { - return ira->codegen->invalid_instruction; + if (!resolve_inferred_error_set(ira->codegen, switch_type, target_value->base.source_node)) { + return ira->codegen->invalid_inst_gen; } size_t field_prev_uses_count = ira->codegen->errors_by_index.length; AstNode **field_prev_uses = allocate(field_prev_uses_count, "AstNode *"); for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) { - IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i]; + IrInstSrcCheckSwitchProngsRange *range = &instruction->ranges[range_i]; - IrInstruction *start_value_uncasted = range->start->child; + IrInstGen *start_value_uncasted = range->start->child; if (type_is_invalid(start_value_uncasted->value->type)) - return ira->codegen->invalid_instruction; - IrInstruction *start_value = ir_implicit_cast(ira, start_value_uncasted, switch_type); + return ira->codegen->invalid_inst_gen; + IrInstGen *start_value = ir_implicit_cast(ira, start_value_uncasted, switch_type); if (type_is_invalid(start_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *end_value_uncasted = range->end->child; + IrInstGen *end_value_uncasted = range->end->child; if (type_is_invalid(end_value_uncasted->value->type)) - return ira->codegen->invalid_instruction; - IrInstruction *end_value = ir_implicit_cast(ira, end_value_uncasted, switch_type); + return ira->codegen->invalid_inst_gen; + IrInstGen *end_value = ir_implicit_cast(ira, end_value_uncasted, switch_type); if (type_is_invalid(end_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - ir_assert(start_value->value->type->id == ZigTypeIdErrorSet, &instruction->base); + ir_assert(start_value->value->type->id == ZigTypeIdErrorSet, &instruction->base.base); uint32_t start_index = start_value->value->data.x_err_set->value; - ir_assert(end_value->value->type->id == ZigTypeIdErrorSet, &instruction->base); + ir_assert(end_value->value->type->id == ZigTypeIdErrorSet, &instruction->base.base); uint32_t end_index = end_value->value->data.x_err_set->value; if (start_index != end_index) { - ir_add_error(ira, end_value, buf_sprintf("ranges not allowed when switching on errors")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &end_value->base, buf_sprintf("ranges not allowed when switching on errors")); + return ira->codegen->invalid_inst_gen; } AstNode *prev_node = field_prev_uses[start_index]; if (prev_node != nullptr) { Buf *err_name = &ira->codegen->errors_by_index.at(start_index)->name; - ErrorMsg *msg = ir_add_error(ira, start_value, + ErrorMsg *msg = ir_add_error(ira, &start_value->base, buf_sprintf("duplicate switch value: '%s.%s'", buf_ptr(&switch_type->name), buf_ptr(err_name))); add_error_note(ira->codegen, msg, prev_node, buf_sprintf("other value is here")); } - field_prev_uses[start_index] = start_value->source_node; + field_prev_uses[start_index] = start_value->base.source_node; } if (!instruction->have_else_prong) { if (type_is_global_error_set(switch_type)) { - ir_add_error(ira, &instruction->base, + ir_add_error(ira, &instruction->base.base, buf_sprintf("else prong required when switching on type 'anyerror'")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else { for (uint32_t i = 0; i < switch_type->data.error_set.err_count; i += 1) { ErrorTableEntry *err_entry = switch_type->data.error_set.errors[i]; AstNode *prev_node = field_prev_uses[err_entry->value]; if (prev_node == nullptr) { - ir_add_error(ira, &instruction->base, + ir_add_error(ira, &instruction->base.base, buf_sprintf("error.%s not handled in switch", buf_ptr(&err_entry->name))); } } @@ -26534,44 +27461,44 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, } else if (switch_type->id == ZigTypeIdInt) { RangeSet rs = {0}; for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) { - IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i]; + IrInstSrcCheckSwitchProngsRange *range = &instruction->ranges[range_i]; - IrInstruction *start_value = range->start->child; + IrInstGen *start_value = range->start->child; if (type_is_invalid(start_value->value->type)) - return ira->codegen->invalid_instruction; - IrInstruction *casted_start_value = ir_implicit_cast(ira, start_value, switch_type); + return ira->codegen->invalid_inst_gen; + IrInstGen *casted_start_value = ir_implicit_cast(ira, start_value, switch_type); if (type_is_invalid(casted_start_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *end_value = range->end->child; + IrInstGen *end_value = range->end->child; if (type_is_invalid(end_value->value->type)) - return ira->codegen->invalid_instruction; - IrInstruction *casted_end_value = ir_implicit_cast(ira, end_value, switch_type); + return ira->codegen->invalid_inst_gen; + IrInstGen *casted_end_value = ir_implicit_cast(ira, end_value, switch_type); if (type_is_invalid(casted_end_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *start_val = ir_resolve_const(ira, casted_start_value, UndefBad); if (!start_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *end_val = ir_resolve_const(ira, casted_end_value, UndefBad); if (!end_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; assert(start_val->type->id == ZigTypeIdInt || start_val->type->id == ZigTypeIdComptimeInt); assert(end_val->type->id == ZigTypeIdInt || end_val->type->id == ZigTypeIdComptimeInt); if (bigint_cmp(&start_val->data.x_bigint, &end_val->data.x_bigint) == CmpGT) { - ir_add_error(ira, start_value, + ir_add_error(ira, &start_value->base, buf_sprintf("range start value is greater than the end value")); } AstNode *prev_node = rangeset_add_range(&rs, &start_val->data.x_bigint, &end_val->data.x_bigint, - start_value->source_node); + start_value->base.source_node); if (prev_node != nullptr) { - ErrorMsg *msg = ir_add_error(ira, start_value, buf_sprintf("duplicate switch value")); + ErrorMsg *msg = ir_add_error(ira, &start_value->base, buf_sprintf("duplicate switch value")); add_error_note(ira->codegen, msg, prev_node, buf_sprintf("previous value is here")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } if (!instruction->have_else_prong) { @@ -26580,25 +27507,25 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, BigInt max_val; eval_min_max_value_int(ira->codegen, switch_type, &max_val, true); if (!rangeset_spans(&rs, &min_val, &max_val)) { - ir_add_error(ira, &instruction->base, buf_sprintf("switch must handle all possibilities")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("switch must handle all possibilities")); + return ira->codegen->invalid_inst_gen; } } } else if (switch_type->id == ZigTypeIdBool) { int seenTrue = 0; int seenFalse = 0; for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) { - IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i]; + IrInstSrcCheckSwitchProngsRange *range = &instruction->ranges[range_i]; - IrInstruction *value = range->start->child; + IrInstGen *value = range->start->child; - IrInstruction *casted_value = ir_implicit_cast(ira, value, switch_type); + IrInstGen *casted_value = ir_implicit_cast(ira, value, switch_type); if (type_is_invalid(casted_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigValue *const_expr_val = ir_resolve_const(ira, casted_value, UndefBad); if (!const_expr_val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; assert(const_expr_val->type->id == ZigTypeIdBool); @@ -26609,60 +27536,59 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, } if ((seenTrue > 1) || (seenFalse > 1)) { - ir_add_error(ira, value, buf_sprintf("duplicate switch value")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &value->base, buf_sprintf("duplicate switch value")); + return ira->codegen->invalid_inst_gen; } } if (((seenTrue < 1) || (seenFalse < 1)) && !instruction->have_else_prong) { - ir_add_error(ira, &instruction->base, buf_sprintf("switch must handle all possibilities")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("switch must handle all possibilities")); + return ira->codegen->invalid_inst_gen; } } else if (!instruction->have_else_prong) { - ir_add_error(ira, &instruction->base, + ir_add_error(ira, &instruction->base.base, buf_sprintf("else prong required when switching on type '%s'", buf_ptr(&switch_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } -static IrInstruction *ir_analyze_instruction_check_statement_is_void(IrAnalyze *ira, - IrInstructionCheckStatementIsVoid *instruction) +static IrInstGen *ir_analyze_instruction_check_statement_is_void(IrAnalyze *ira, + IrInstSrcCheckStatementIsVoid *instruction) { - IrInstruction *statement_value = instruction->statement_value->child; + IrInstGen *statement_value = instruction->statement_value->child; ZigType *statement_type = statement_value->value->type; if (type_is_invalid(statement_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (statement_type->id != ZigTypeIdVoid && statement_type->id != ZigTypeIdUnreachable) { - ir_add_error(ira, &instruction->base, buf_sprintf("expression value is ignored")); + ir_add_error(ira, &instruction->base.base, buf_sprintf("expression value is ignored")); } - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } -static IrInstruction *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructionPanic *instruction) { - IrInstruction *msg = instruction->msg->child; +static IrInstGen *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstSrcPanic *instruction) { + IrInstGen *msg = instruction->msg->child; if (type_is_invalid(msg->value->type)) return ir_unreach_error(ira); - if (ir_should_inline(ira->new_irb.exec, instruction->base.scope)) { - ir_add_error(ira, &instruction->base, buf_sprintf("encountered @panic at compile-time")); + if (ir_should_inline(ira->old_irb.exec, instruction->base.base.scope)) { + ir_add_error(ira, &instruction->base.base, buf_sprintf("encountered @panic at compile-time")); return ir_unreach_error(ira); } ZigType *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8, true, false, PtrLenUnknown, 0, 0, 0, false); ZigType *str_type = get_slice_type(ira->codegen, u8_ptr_type); - IrInstruction *casted_msg = ir_implicit_cast(ira, msg, str_type); + IrInstGen *casted_msg = ir_implicit_cast(ira, msg, str_type); if (type_is_invalid(casted_msg->value->type)) return ir_unreach_error(ira); - IrInstruction *new_instruction = ir_build_panic(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, casted_msg); + IrInstGen *new_instruction = ir_build_panic_gen(ira, &instruction->base.base, casted_msg); return ir_finish_anal(ira, new_instruction); } -static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint32_t align_bytes, bool safety_check_on) { +static IrInstGen *ir_align_cast(IrAnalyze *ira, IrInstGen *target, uint32_t align_bytes, bool safety_check_on) { Error err; ZigType *target_type = target->value->type; @@ -26674,7 +27600,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 if (target_type->id == ZigTypeIdPointer) { result_type = adjust_ptr_align(ira->codegen, target_type, align_bytes); if ((err = resolve_ptr_align(ira, target_type, &old_align_bytes))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else if (target_type->id == ZigTypeIdFn) { FnTypeId fn_type_id = target_type->data.fn.fn_type_id; old_align_bytes = fn_type_id.alignment; @@ -26685,7 +27611,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 { ZigType *ptr_type = target_type->data.maybe.child_type; if ((err = resolve_ptr_align(ira, ptr_type, &old_align_bytes))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *better_ptr_type = adjust_ptr_align(ira->codegen, ptr_type, align_bytes); result_type = get_optional_type(ira->codegen, better_ptr_type); @@ -26700,47 +27626,44 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 } else if (is_slice(target_type)) { ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index]->type_entry; if ((err = resolve_ptr_align(ira, slice_ptr_type, &old_align_bytes))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *result_ptr_type = adjust_ptr_align(ira->codegen, slice_ptr_type, align_bytes); result_type = get_slice_type(ira->codegen, result_ptr_type); } else { - ir_add_error(ira, target, + ir_add_error(ira, &target->base, buf_sprintf("expected pointer or slice, found '%s'", buf_ptr(&target_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (instr_is_comptime(target)) { ZigValue *val = ir_resolve_const(ira, target, UndefBad); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr && val->data.x_ptr.data.hard_coded_addr.addr % align_bytes != 0) { - ir_add_error(ira, target, + ir_add_error(ira, &target->base, buf_sprintf("pointer address 0x%" ZIG_PRI_x64 " is not aligned to %" PRIu32 " bytes", val->data.x_ptr.data.hard_coded_addr.addr, align_bytes)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *result = ir_const(ira, target, result_type); + IrInstGen *result = ir_const(ira, &target->base, result_type); copy_const_val(result->value, val); result->value->type = result_type; return result; } - IrInstruction *result; if (safety_check_on && align_bytes > old_align_bytes && align_bytes != 1) { - result = ir_build_align_cast(&ira->new_irb, target->scope, target->source_node, nullptr, target); + return ir_build_align_cast_gen(ira, target->base.scope, target->base.source_node, target, result_type); } else { - result = ir_build_cast(&ira->new_irb, target->scope, target->source_node, result_type, target, CastOpNoop); + return ir_build_cast(ira, &target->base, result_type, target, CastOpNoop); } - result->value->type = result_type; - return result; } -static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr, - ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on) +static IrInstGen *ir_analyze_ptr_cast(IrAnalyze *ira, IrInst* source_instr, IrInstGen *ptr, + ZigType *dest_type, IrInst *dest_type_src, bool safety_check_on) { Error err; @@ -26756,44 +27679,44 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ ZigType *src_ptr_type = get_src_ptr_type(src_type); if (src_ptr_type == nullptr) { - ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name))); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &ptr->base, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name))); + return ira->codegen->invalid_inst_gen; } ZigType *dest_ptr_type = get_src_ptr_type(dest_type); if (dest_ptr_type == nullptr) { ir_add_error(ira, dest_type_src, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (get_ptr_const(src_type) && !get_ptr_const(dest_type)) { ir_add_error(ira, source_instr, buf_sprintf("cast discards const qualifier")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } uint32_t src_align_bytes; if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; uint32_t dest_align_bytes; if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if ((err = type_resolve(ira->codegen, src_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (type_has_bits(dest_type) && !type_has_bits(src_type)) { ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("'%s' and '%s' do not have the same in-memory representation", buf_ptr(&src_type->name), buf_ptr(&dest_type->name))); - add_error_note(ira->codegen, msg, ptr->source_node, + add_error_note(ira->codegen, msg, ptr->base.source_node, buf_sprintf("'%s' has no in-memory bits", buf_ptr(&src_type->name))); add_error_note(ira->codegen, msg, dest_type_src->source_node, buf_sprintf("'%s' has in-memory bits", buf_ptr(&dest_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (instr_is_comptime(ptr)) { @@ -26801,7 +27724,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ UndefAllowed is_undef_allowed = dest_allows_addr_zero ? UndefOk : UndefBad; ZigValue *val = ir_resolve_const(ira, ptr, is_undef_allowed); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (value_is_comptime(val) && val->special != ConstValSpecialUndef) { bool is_addr_zero = val->data.x_ptr.special == ConstPtrSpecialNull || @@ -26810,16 +27733,16 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ if (is_addr_zero && !dest_allows_addr_zero) { ir_add_error(ira, source_instr, buf_sprintf("null pointer casted to type '%s'", buf_ptr(&dest_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } - IrInstruction *result; + IrInstGen *result; if (ptr->value->data.x_ptr.mut == ConstPtrMutInfer) { result = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on); if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else { result = ir_const(ira, source_instr, dest_type); } @@ -26837,40 +27760,40 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ if (dest_align_bytes > src_align_bytes) { ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment")); - add_error_note(ira->codegen, msg, ptr->source_node, + add_error_note(ira->codegen, msg, ptr->base.source_node, buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&src_type->name), src_align_bytes)); add_error_note(ira->codegen, msg, dest_type_src->source_node, buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&dest_type->name), dest_align_bytes)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on); + IrInstGen *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on); // Keep the bigger alignment, it can only help- // unless the target is zero bits. - IrInstruction *result; + IrInstGen *result; if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) { result = ir_align_cast(ira, casted_ptr, src_align_bytes, false); if (type_is_invalid(result->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else { result = casted_ptr; } return result; } -static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCastSrc *instruction) { - IrInstruction *dest_type_value = instruction->dest_type->child; +static IrInstGen *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstSrcPtrCast *instruction) { + IrInstGen *dest_type_value = instruction->dest_type->child; ZigType *dest_type = ir_resolve_type(ira, dest_type_value); if (type_is_invalid(dest_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *ptr = instruction->ptr->child; + IrInstGen *ptr = instruction->ptr->child; ZigType *src_type = ptr->value->type; if (type_is_invalid(src_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value, + return ir_analyze_ptr_cast(ira, &instruction->base.base, ptr, dest_type, &dest_type_value->base, instruction->safety_check_on); } @@ -27201,7 +28124,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou zig_unreachable(); } -static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, +static IrInstGen *ir_analyze_bit_cast(IrAnalyze *ira, IrInst* source_instr, IrInstGen *value, ZigType *dest_type) { Error err; @@ -27217,14 +28140,14 @@ static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_ buf_sprintf("cannot cast a value of type '%s'", buf_ptr(&dest_type->name))); add_error_note(ira->codegen, msg, source_instr->source_node, buf_sprintf("use @intToEnum for type coercion")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; uint64_t dest_size_bytes = type_size(ira->codegen, dest_type); uint64_t src_size_bytes = type_size(ira->codegen, src_type); @@ -27233,7 +28156,7 @@ static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_ buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64, buf_ptr(&dest_type->name), dest_size_bytes, buf_ptr(&src_type->name), src_size_bytes)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type); @@ -27243,26 +28166,26 @@ static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_ buf_sprintf("destination type '%s' has %" ZIG_PRI_u64 " bits but source type '%s' has %" ZIG_PRI_u64 " bits", buf_ptr(&dest_type->name), dest_size_bits, buf_ptr(&src_type->name), src_size_bits)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (instr_is_comptime(value)) { ZigValue *val = ir_resolve_const(ira, value, UndefBad); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *result = ir_const(ira, source_instr, dest_type); + IrInstGen *result = ir_const(ira, source_instr, dest_type); uint8_t *buf = allocate_nonzero(src_size_bytes); buf_write_value_bytes(ira->codegen, buf, val); if ((err = buf_read_value_bytes(ira, ira->codegen, source_instr->source_node, buf, result->value))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return result; } return ir_build_bit_cast_gen(ira, source_instr, value, dest_type); } -static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target, +static IrInstGen *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInst* source_instr, IrInstGen *target, ZigType *ptr_type) { Error err; @@ -27270,136 +28193,128 @@ static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *sourc ir_assert(get_src_ptr_type(ptr_type) != nullptr, source_instr); ir_assert(type_has_bits(ptr_type), source_instr); - IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize); + IrInstGen *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize); if (type_is_invalid(casted_int->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (instr_is_comptime(casted_int)) { ZigValue *val = ir_resolve_const(ira, casted_int, UndefBad); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; uint64_t addr = bigint_as_u64(&val->data.x_bigint); if (!ptr_allows_addr_zero(ptr_type) && addr == 0) { ir_add_error(ira, source_instr, buf_sprintf("pointer type '%s' does not allow address zero", buf_ptr(&ptr_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } uint32_t align_bytes; if ((err = resolve_ptr_align(ira, ptr_type, &align_bytes))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (addr != 0 && addr % align_bytes != 0) { ir_add_error(ira, source_instr, buf_sprintf("pointer type '%s' requires aligned address", buf_ptr(&ptr_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *result = ir_const(ira, source_instr, ptr_type); + IrInstGen *result = ir_const(ira, source_instr, ptr_type); result->value->data.x_ptr.special = ConstPtrSpecialHardCodedAddr; result->value->data.x_ptr.mut = ConstPtrMutRuntimeVar; result->value->data.x_ptr.data.hard_coded_addr.addr = addr; return result; } - IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, source_instr->scope, - source_instr->source_node, nullptr, casted_int); - result->value->type = ptr_type; - return result; + return ir_build_int_to_ptr_gen(ira, source_instr->scope, source_instr->source_node, casted_int, ptr_type); } -static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) { +static IrInstGen *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstSrcIntToPtr *instruction) { Error err; - IrInstruction *dest_type_value = instruction->dest_type->child; + IrInstGen *dest_type_value = instruction->dest_type->child; ZigType *dest_type = ir_resolve_type(ira, dest_type_value); if (type_is_invalid(dest_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; // We explicitly check for the size, so we can use get_src_ptr_type if (get_src_ptr_type(dest_type) == nullptr) { - ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name))); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &dest_type_value->base, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name))); + return ira->codegen->invalid_inst_gen; } bool has_bits; if ((err = type_has_bits2(ira->codegen, dest_type, &has_bits))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (!has_bits) { - ir_add_error(ira, dest_type_value, + ir_add_error(ira, &dest_type_value->base, buf_sprintf("type '%s' has 0 bits and cannot store information", buf_ptr(&dest_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *target = instruction->target->child; + IrInstGen *target = instruction->target->child; if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_analyze_int_to_ptr(ira, &instruction->base, target, dest_type); + return ir_analyze_int_to_ptr(ira, &instruction->base.base, target, dest_type); } -static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira, - IrInstructionDeclRef *instruction) -{ - IrInstruction *ref_instruction = ir_analyze_decl_ref(ira, &instruction->base, instruction->tld); +static IrInstGen *ir_analyze_instruction_decl_ref(IrAnalyze *ira, IrInstSrcDeclRef *instruction) { + IrInstGen *ref_instruction = ir_analyze_decl_ref(ira, &instruction->base.base, instruction->tld); if (type_is_invalid(ref_instruction->value->type)) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (instruction->lval == LValPtr) { return ref_instruction; } else { - return ir_get_deref(ira, &instruction->base, ref_instruction, nullptr); + return ir_get_deref(ira, &instruction->base.base, ref_instruction, nullptr); } } -static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstructionPtrToInt *instruction) { +static IrInstGen *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstSrcPtrToInt *instruction) { Error err; - IrInstruction *target = instruction->target->child; + IrInstGen *target = instruction->target->child; if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *usize = ira->codegen->builtin_types.entry_usize; // We check size explicitly so we can use get_src_ptr_type here. if (get_src_ptr_type(target->value->type) == nullptr) { - ir_add_error(ira, target, + ir_add_error(ira, &target->base, buf_sprintf("expected pointer, found '%s'", buf_ptr(&target->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } bool has_bits; if ((err = type_has_bits2(ira->codegen, target->value->type, &has_bits))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (!has_bits) { - ir_add_error(ira, target, + ir_add_error(ira, &target->base, buf_sprintf("pointer to size 0 type has no address")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (instr_is_comptime(target)) { ZigValue *val = ir_resolve_const(ira, target, UndefBad); if (!val) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (val->type->id == ZigTypeIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { - IrInstruction *result = ir_const(ira, &instruction->base, usize); + IrInstGen *result = ir_const(ira, &instruction->base.base, usize); bigint_init_unsigned(&result->value->data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr); result->value->type = usize; return result; } } - IrInstruction *result = ir_build_ptr_to_int(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, target); - result->value->type = usize; - return result; + return ir_build_ptr_to_int_gen(ira, &instruction->base.base, target); } -static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstructionPtrType *instruction) { - IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type); +static IrInstGen *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstSrcPtrType *instruction) { + IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_type); result->value->special = ConstValSpecialLazy; LazyValuePtrType *lazy_ptr_type = allocate(1, "LazyValuePtrType"); @@ -27410,17 +28325,17 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct if (instruction->sentinel != nullptr) { lazy_ptr_type->sentinel = instruction->sentinel->child; if (ir_resolve_const(ira, lazy_ptr_type->sentinel, LazyOk) == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } lazy_ptr_type->elem_type = instruction->child_type->child; if (ir_resolve_type_lazy(ira, lazy_ptr_type->elem_type) == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (instruction->align_value != nullptr) { lazy_ptr_type->align_inst = instruction->align_value->child; if (ir_resolve_const(ira, lazy_ptr_type->align_inst, LazyOk) == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } lazy_ptr_type->ptr_len = instruction->ptr_len; @@ -27433,10 +28348,10 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct return result; } -static IrInstruction *ir_analyze_instruction_align_cast(IrAnalyze *ira, IrInstructionAlignCast *instruction) { - IrInstruction *target = instruction->target->child; +static IrInstGen *ir_analyze_instruction_align_cast(IrAnalyze *ira, IrInstSrcAlignCast *instruction) { + IrInstGen *target = instruction->target->child; if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *elem_type = nullptr; if (is_slice(target->value->type)) { @@ -27447,192 +28362,192 @@ static IrInstruction *ir_analyze_instruction_align_cast(IrAnalyze *ira, IrInstru } uint32_t align_bytes; - IrInstruction *align_bytes_inst = instruction->align_bytes->child; + IrInstGen *align_bytes_inst = instruction->align_bytes->child; if (!ir_resolve_align(ira, align_bytes_inst, elem_type, &align_bytes)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *result = ir_align_cast(ira, target, align_bytes, true); + IrInstGen *result = ir_align_cast(ira, target, align_bytes, true); if (type_is_invalid(result->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return result; } -static IrInstruction *ir_analyze_instruction_opaque_type(IrAnalyze *ira, IrInstructionOpaqueType *instruction) { +static IrInstGen *ir_analyze_instruction_opaque_type(IrAnalyze *ira, IrInstSrcOpaqueType *instruction) { Buf *bare_name = buf_alloc(); - Buf *full_name = get_anon_type_name(ira->codegen, ira->new_irb.exec, "opaque", - instruction->base.scope, instruction->base.source_node, bare_name); - ZigType *result_type = get_opaque_type(ira->codegen, instruction->base.scope, instruction->base.source_node, - buf_ptr(full_name), bare_name); - return ir_const_type(ira, &instruction->base, result_type); + Buf *full_name = get_anon_type_name(ira->codegen, ira->old_irb.exec, "opaque", + instruction->base.base.scope, instruction->base.base.source_node, bare_name); + ZigType *result_type = get_opaque_type(ira->codegen, instruction->base.base.scope, + instruction->base.base.source_node, buf_ptr(full_name), bare_name); + return ir_const_type(ira, &instruction->base.base, result_type); } -static IrInstruction *ir_analyze_instruction_set_align_stack(IrAnalyze *ira, IrInstructionSetAlignStack *instruction) { +static IrInstGen *ir_analyze_instruction_set_align_stack(IrAnalyze *ira, IrInstSrcSetAlignStack *instruction) { uint32_t align_bytes; - IrInstruction *align_bytes_inst = instruction->align_bytes->child; + IrInstGen *align_bytes_inst = instruction->align_bytes->child; if (!ir_resolve_align(ira, align_bytes_inst, nullptr, &align_bytes)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (align_bytes > 256) { - ir_add_error(ira, &instruction->base, buf_sprintf("attempt to @setAlignStack(%" PRIu32 "); maximum is 256", align_bytes)); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("attempt to @setAlignStack(%" PRIu32 "); maximum is 256", align_bytes)); + return ira->codegen->invalid_inst_gen; } - ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); + ZigFn *fn_entry = ira->new_irb.exec->fn_entry; if (fn_entry == nullptr) { - ir_add_error(ira, &instruction->base, buf_sprintf("@setAlignStack outside function")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("@setAlignStack outside function")); + return ira->codegen->invalid_inst_gen; } if (fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionNaked) { - ir_add_error(ira, &instruction->base, buf_sprintf("@setAlignStack in naked function")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("@setAlignStack in naked function")); + return ira->codegen->invalid_inst_gen; } if (fn_entry->fn_inline == FnInlineAlways) { - ir_add_error(ira, &instruction->base, buf_sprintf("@setAlignStack in inline function")); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &instruction->base.base, buf_sprintf("@setAlignStack in inline function")); + return ira->codegen->invalid_inst_gen; } if (fn_entry->set_alignstack_node != nullptr) { - ErrorMsg *msg = ir_add_error_node(ira, instruction->base.source_node, + ErrorMsg *msg = ir_add_error(ira, &instruction->base.base, buf_sprintf("alignstack set twice")); add_error_note(ira->codegen, msg, fn_entry->set_alignstack_node, buf_sprintf("first set here")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - fn_entry->set_alignstack_node = instruction->base.source_node; + fn_entry->set_alignstack_node = instruction->base.base.source_node; fn_entry->alignstack_value = align_bytes; - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } -static IrInstruction *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstructionArgType *instruction) { - IrInstruction *fn_type_inst = instruction->fn_type->child; +static IrInstGen *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstSrcArgType *instruction) { + IrInstGen *fn_type_inst = instruction->fn_type->child; ZigType *fn_type = ir_resolve_type(ira, fn_type_inst); if (type_is_invalid(fn_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *arg_index_inst = instruction->arg_index->child; + IrInstGen *arg_index_inst = instruction->arg_index->child; uint64_t arg_index; if (!ir_resolve_usize(ira, arg_index_inst, &arg_index)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (fn_type->id == ZigTypeIdBoundFn) { fn_type = fn_type->data.bound_fn.fn_type; arg_index += 1; } if (fn_type->id != ZigTypeIdFn) { - ir_add_error(ira, fn_type_inst, buf_sprintf("expected function, found '%s'", buf_ptr(&fn_type->name))); - return ira->codegen->invalid_instruction; + ir_add_error(ira, &fn_type_inst->base, buf_sprintf("expected function, found '%s'", buf_ptr(&fn_type->name))); + return ira->codegen->invalid_inst_gen; } FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; if (arg_index >= fn_type_id->param_count) { if (instruction->allow_var) { // TODO remove this with var args - return ir_const_type(ira, &instruction->base, ira->codegen->builtin_types.entry_var); + return ir_const_type(ira, &instruction->base.base, ira->codegen->builtin_types.entry_var); } - ir_add_error(ira, arg_index_inst, + ir_add_error(ira, &arg_index_inst->base, buf_sprintf("arg index %" ZIG_PRI_u64 " out of bounds; '%s' has %" ZIG_PRI_usize " arguments", arg_index, buf_ptr(&fn_type->name), fn_type_id->param_count)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigType *result_type = fn_type_id->param_info[arg_index].type; if (result_type == nullptr) { // Args are only unresolved if our function is generic. - ir_assert(fn_type->data.fn.is_generic, &instruction->base); + ir_assert(fn_type->data.fn.is_generic, &instruction->base.base); if (instruction->allow_var) { - return ir_const_type(ira, &instruction->base, ira->codegen->builtin_types.entry_var); + return ir_const_type(ira, &instruction->base.base, ira->codegen->builtin_types.entry_var); } else { - ir_add_error(ira, arg_index_inst, + ir_add_error(ira, &arg_index_inst->base, buf_sprintf("@ArgType could not resolve the type of arg %" ZIG_PRI_u64 " because '%s' is generic", arg_index, buf_ptr(&fn_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } - return ir_const_type(ira, &instruction->base, result_type); + return ir_const_type(ira, &instruction->base.base, result_type); } -static IrInstruction *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstructionTagType *instruction) { +static IrInstGen *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstSrcTagType *instruction) { Error err; - IrInstruction *target_inst = instruction->target->child; + IrInstGen *target_inst = instruction->target->child; ZigType *enum_type = ir_resolve_type(ira, target_inst); if (type_is_invalid(enum_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (enum_type->id == ZigTypeIdEnum) { if ((err = type_resolve(ira->codegen, enum_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_const_type(ira, &instruction->base, enum_type->data.enumeration.tag_int_type); + return ir_const_type(ira, &instruction->base.base, enum_type->data.enumeration.tag_int_type); } else if (enum_type->id == ZigTypeIdUnion) { - ZigType *tag_type = ir_resolve_union_tag_type(ira, instruction->target, enum_type); + ZigType *tag_type = ir_resolve_union_tag_type(ira, instruction->target->base.source_node, enum_type); if (type_is_invalid(tag_type)) - return ira->codegen->invalid_instruction; - return ir_const_type(ira, &instruction->base, tag_type); + return ira->codegen->invalid_inst_gen; + return ir_const_type(ira, &instruction->base.base, tag_type); } else { - ir_add_error(ira, target_inst, buf_sprintf("expected enum or union, found '%s'", + ir_add_error(ira, &target_inst->base, buf_sprintf("expected enum or union, found '%s'", buf_ptr(&enum_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } -static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op) { +static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op) { ZigType *operand_type = ir_resolve_type(ira, op); if (type_is_invalid(operand_type)) return ira->codegen->builtin_types.entry_invalid; if (operand_type->id == ZigTypeIdInt) { if (operand_type->data.integral.bit_count < 8) { - ir_add_error(ira, op, + ir_add_error(ira, &op->base, buf_sprintf("expected integer type 8 bits or larger, found %" PRIu32 "-bit integer type", operand_type->data.integral.bit_count)); return ira->codegen->builtin_types.entry_invalid; } uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch); if (operand_type->data.integral.bit_count > max_atomic_bits) { - ir_add_error(ira, op, + ir_add_error(ira, &op->base, buf_sprintf("expected %" PRIu32 "-bit integer type or smaller, found %" PRIu32 "-bit integer type", max_atomic_bits, operand_type->data.integral.bit_count)); return ira->codegen->builtin_types.entry_invalid; } if (!is_power_of_2(operand_type->data.integral.bit_count)) { - ir_add_error(ira, op, + ir_add_error(ira, &op->base, buf_sprintf("%" PRIu32 "-bit integer type is not a power of 2", operand_type->data.integral.bit_count)); return ira->codegen->builtin_types.entry_invalid; } } else if (operand_type->id == ZigTypeIdEnum) { ZigType *int_type = operand_type->data.enumeration.tag_int_type; if (int_type->data.integral.bit_count < 8) { - ir_add_error(ira, op, + ir_add_error(ira, &op->base, buf_sprintf("expected enum tag type 8 bits or larger, found %" PRIu32 "-bit tag type", int_type->data.integral.bit_count)); return ira->codegen->builtin_types.entry_invalid; } uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch); if (int_type->data.integral.bit_count > max_atomic_bits) { - ir_add_error(ira, op, + ir_add_error(ira, &op->base, buf_sprintf("expected %" PRIu32 "-bit enum tag type or smaller, found %" PRIu32 "-bit tag type", max_atomic_bits, int_type->data.integral.bit_count)); return ira->codegen->builtin_types.entry_invalid; } if (!is_power_of_2(int_type->data.integral.bit_count)) { - ir_add_error(ira, op, + ir_add_error(ira, &op->base, buf_sprintf("%" PRIu32 "-bit enum tag type is not a power of 2", int_type->data.integral.bit_count)); return ira->codegen->builtin_types.entry_invalid; } } else if (operand_type->id == ZigTypeIdFloat) { uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch); if (operand_type->data.floating.bit_count > max_atomic_bits) { - ir_add_error(ira, op, + ir_add_error(ira, &op->base, buf_sprintf("expected %" PRIu32 "-bit float or smaller, found %" PRIu32 "-bit float", max_atomic_bits, (uint32_t) operand_type->data.floating.bit_count)); return ira->codegen->builtin_types.entry_invalid; } } else if (get_codegen_ptr_type(operand_type) == nullptr) { - ir_add_error(ira, op, + ir_add_error(ira, &op->base, buf_sprintf("expected integer, float, enum or pointer type, found '%s'", buf_ptr(&operand_type->name))); return ira->codegen->builtin_types.entry_invalid; } @@ -27640,172 +28555,146 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op return operand_type; } -static IrInstruction *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstructionAtomicRmw *instruction) { +static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAtomicRmw *instruction) { ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child); if (type_is_invalid(operand_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *ptr_inst = instruction->ptr->child; + IrInstGen *ptr_inst = instruction->ptr->child; if (type_is_invalid(ptr_inst->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; // TODO let this be volatile ZigType *ptr_type = get_pointer_to_type(ira->codegen, operand_type, false); - IrInstruction *casted_ptr = ir_implicit_cast(ira, ptr_inst, ptr_type); + IrInstGen *casted_ptr = ir_implicit_cast(ira, ptr_inst, ptr_type); if (type_is_invalid(casted_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; AtomicRmwOp op; - if (instruction->op == nullptr) { - op = instruction->resolved_op; - } else { - if (!ir_resolve_atomic_rmw_op(ira, instruction->op->child, &op)) { - return ira->codegen->invalid_instruction; - } + if (!ir_resolve_atomic_rmw_op(ira, instruction->op->child, &op)) { + return ira->codegen->invalid_inst_gen; } if (operand_type->id == ZigTypeIdEnum && op != AtomicRmwOp_xchg) { - ir_add_error(ira, instruction->op, + ir_add_error(ira, &instruction->op->base, buf_sprintf("@atomicRmw on enum only works with .Xchg")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else if (operand_type->id == ZigTypeIdFloat && op > AtomicRmwOp_sub) { - ir_add_error(ira, instruction->op, + ir_add_error(ira, &instruction->op->base, buf_sprintf("@atomicRmw with float only works with .Xchg, .Add and .Sub")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - IrInstruction *operand = instruction->operand->child; + IrInstGen *operand = instruction->operand->child; if (type_is_invalid(operand->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_operand = ir_implicit_cast(ira, operand, operand_type); + IrInstGen *casted_operand = ir_implicit_cast(ira, operand, operand_type); if (type_is_invalid(casted_operand->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; AtomicOrder ordering; - if (instruction->ordering == nullptr) { - ordering = instruction->resolved_ordering; - } else { - if (!ir_resolve_atomic_order(ira, instruction->ordering->child, &ordering)) - return ira->codegen->invalid_instruction; - if (ordering == AtomicOrderUnordered) { - ir_add_error(ira, instruction->ordering, - buf_sprintf("@atomicRmw atomic ordering must not be Unordered")); - return ira->codegen->invalid_instruction; - } + if (!ir_resolve_atomic_order(ira, instruction->ordering->child, &ordering)) + return ira->codegen->invalid_inst_gen; + if (ordering == AtomicOrderUnordered) { + ir_add_error(ira, &instruction->ordering->base, + buf_sprintf("@atomicRmw atomic ordering must not be Unordered")); + return ira->codegen->invalid_inst_gen; } if (instr_is_comptime(casted_operand) && instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar) { - zig_panic("TODO compile-time execution of atomicRmw"); + ir_add_error(ira, &instruction->base.base, + buf_sprintf("compiler bug: TODO compile-time execution of @atomicRmw")); + return ira->codegen->invalid_inst_gen; } - IrInstruction *result = ir_build_atomic_rmw(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, nullptr, casted_ptr, nullptr, casted_operand, nullptr, - op, ordering); - result->value->type = operand_type; - return result; + return ir_build_atomic_rmw_gen(ira, &instruction->base.base, casted_ptr, casted_operand, op, + ordering, operand_type); } -static IrInstruction *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstructionAtomicLoad *instruction) { +static IrInstGen *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstSrcAtomicLoad *instruction) { ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child); if (type_is_invalid(operand_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *ptr_inst = instruction->ptr->child; + IrInstGen *ptr_inst = instruction->ptr->child; if (type_is_invalid(ptr_inst->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *ptr_type = get_pointer_to_type(ira->codegen, operand_type, true); - IrInstruction *casted_ptr = ir_implicit_cast(ira, ptr_inst, ptr_type); + IrInstGen *casted_ptr = ir_implicit_cast(ira, ptr_inst, ptr_type); if (type_is_invalid(casted_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; AtomicOrder ordering; - if (instruction->ordering == nullptr) { - ordering = instruction->resolved_ordering; - } else { - if (!ir_resolve_atomic_order(ira, instruction->ordering->child, &ordering)) - return ira->codegen->invalid_instruction; - } + if (!ir_resolve_atomic_order(ira, instruction->ordering->child, &ordering)) + return ira->codegen->invalid_inst_gen; if (ordering == AtomicOrderRelease || ordering == AtomicOrderAcqRel) { - ir_assert(instruction->ordering != nullptr, &instruction->base); - ir_add_error(ira, instruction->ordering, + ir_assert(instruction->ordering != nullptr, &instruction->base.base); + ir_add_error(ira, &instruction->ordering->base, buf_sprintf("@atomicLoad atomic ordering must not be Release or AcqRel")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (instr_is_comptime(casted_ptr)) { - IrInstruction *result = ir_get_deref(ira, &instruction->base, casted_ptr, nullptr); - ir_assert(result->value->type != nullptr, &instruction->base); + IrInstGen *result = ir_get_deref(ira, &instruction->base.base, casted_ptr, nullptr); + ir_assert(result->value->type != nullptr, &instruction->base.base); return result; } - IrInstruction *result = ir_build_atomic_load(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, nullptr, casted_ptr, nullptr, ordering); - result->value->type = operand_type; - return result; + return ir_build_atomic_load_gen(ira, &instruction->base.base, casted_ptr, ordering, operand_type); } -static IrInstruction *ir_analyze_instruction_atomic_store(IrAnalyze *ira, IrInstructionAtomicStore *instruction) { +static IrInstGen *ir_analyze_instruction_atomic_store(IrAnalyze *ira, IrInstSrcAtomicStore *instruction) { ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child); if (type_is_invalid(operand_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *ptr_inst = instruction->ptr->child; + IrInstGen *ptr_inst = instruction->ptr->child; if (type_is_invalid(ptr_inst->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *ptr_type = get_pointer_to_type(ira->codegen, operand_type, false); - IrInstruction *casted_ptr = ir_implicit_cast(ira, ptr_inst, ptr_type); + IrInstGen *casted_ptr = ir_implicit_cast(ira, ptr_inst, ptr_type); if (type_is_invalid(casted_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *value = instruction->value->child; + IrInstGen *value = instruction->value->child; if (type_is_invalid(value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_value = ir_implicit_cast(ira, value, operand_type); + IrInstGen *casted_value = ir_implicit_cast(ira, value, operand_type); if (type_is_invalid(casted_value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; AtomicOrder ordering; - if (instruction->ordering == nullptr) { - ordering = instruction->resolved_ordering; - } else { - if (!ir_resolve_atomic_order(ira, instruction->ordering->child, &ordering)) - return ira->codegen->invalid_instruction; - } + if (!ir_resolve_atomic_order(ira, instruction->ordering->child, &ordering)) + return ira->codegen->invalid_inst_gen; if (ordering == AtomicOrderAcquire || ordering == AtomicOrderAcqRel) { - ir_assert(instruction->ordering != nullptr, &instruction->base); - ir_add_error(ira, instruction->ordering, + ir_assert(instruction->ordering != nullptr, &instruction->base.base); + ir_add_error(ira, &instruction->ordering->base, buf_sprintf("@atomicStore atomic ordering must not be Acquire or AcqRel")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (instr_is_comptime(casted_value) && instr_is_comptime(casted_ptr)) { - IrInstruction *result = ir_analyze_store_ptr(ira, &instruction->base, casted_ptr, value, false); + IrInstGen *result = ir_analyze_store_ptr(ira, &instruction->base.base, casted_ptr, value, false); result->value->type = ira->codegen->builtin_types.entry_void; return result; } - IrInstruction *result = ir_build_atomic_store(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, nullptr, casted_ptr, casted_value, nullptr, ordering); - result->value->type = ira->codegen->builtin_types.entry_void; - return result; + return ir_build_atomic_store_gen(ira, &instruction->base.base, casted_ptr, casted_value, ordering); } -static IrInstruction *ir_analyze_instruction_save_err_ret_addr(IrAnalyze *ira, IrInstructionSaveErrRetAddr *instruction) { - IrInstruction *result = ir_build_save_err_ret_addr(&ira->new_irb, instruction->base.scope, - instruction->base.source_node); - result->value->type = ira->codegen->builtin_types.entry_void; - return result; +static IrInstGen *ir_analyze_instruction_save_err_ret_addr(IrAnalyze *ira, IrInstSrcSaveErrRetAddr *instruction) { + return ir_build_save_err_ret_addr_gen(ira, &instruction->base.base); } -static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, BuiltinFnId fop, ZigType *float_type, +static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, IrInst* source_instr, BuiltinFnId fop, ZigType *float_type, ZigValue *op, ZigValue *out_val) { assert(ira && source_instr && float_type && out_val && op); @@ -28018,30 +28907,30 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, IrInstruction *source_instr, B return nullptr; } -static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstructionFloatOp *instruction) { - IrInstruction *operand = instruction->operand->child; +static IrInstGen *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstSrcFloatOp *instruction) { + IrInstGen *operand = instruction->operand->child; ZigType *operand_type = operand->value->type; if (type_is_invalid(operand_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; // This instruction accepts floats and vectors of floats. ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type; if (scalar_type->id != ZigTypeIdFloat && scalar_type->id != ZigTypeIdComptimeFloat) { - ir_add_error(ira, operand, + ir_add_error(ira, &operand->base, buf_sprintf("expected float type, found '%s'", buf_ptr(&scalar_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (instr_is_comptime(operand)) { ZigValue *operand_val = ir_resolve_const(ira, operand, UndefOk); if (operand_val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (operand_val->special == ConstValSpecialUndef) - return ir_const_undef(ira, &instruction->base, operand_type); + return ir_const_undef(ira, &instruction->base.base, operand_type); - IrInstruction *result = ir_const(ira, &instruction->base, operand_type); + IrInstGen *result = ir_const(ira, &instruction->base.base, operand_type); ZigValue *out_val = result->value; if (operand_type->id == ZigTypeIdVector) { @@ -28052,47 +28941,44 @@ static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstruct for (size_t i = 0; i < len; i += 1) { ZigValue *elem_operand = &operand_val->data.x_array.data.s_none.elements[i]; ZigValue *float_out_val = &out_val->data.x_array.data.s_none.elements[i]; - ir_assert(elem_operand->type == scalar_type, &instruction->base); - ir_assert(float_out_val->type == scalar_type, &instruction->base); - ErrorMsg *msg = ir_eval_float_op(ira, &instruction->base, instruction->fn_id, scalar_type, + ir_assert(elem_operand->type == scalar_type, &instruction->base.base); + ir_assert(float_out_val->type == scalar_type, &instruction->base.base); + ErrorMsg *msg = ir_eval_float_op(ira, &instruction->base.base, instruction->fn_id, scalar_type, elem_operand, float_out_val); if (msg != nullptr) { - add_error_note(ira->codegen, msg, instruction->base.source_node, + add_error_note(ira->codegen, msg, instruction->base.base.source_node, buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } float_out_val->type = scalar_type; } out_val->type = operand_type; out_val->special = ConstValSpecialStatic; } else { - if (ir_eval_float_op(ira, &instruction->base, instruction->fn_id, scalar_type, + if (ir_eval_float_op(ira, &instruction->base.base, instruction->fn_id, scalar_type, operand_val, out_val) != nullptr) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } return result; } - ir_assert(scalar_type->id == ZigTypeIdFloat, &instruction->base); + ir_assert(scalar_type->id == ZigTypeIdFloat, &instruction->base.base); - IrInstruction *result = ir_build_float_op(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, operand, instruction->fn_id); - result->value->type = operand_type; - return result; + return ir_build_float_op_gen(ira, &instruction->base.base, operand, instruction->fn_id, operand_type); } -static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) { +static IrInstGen *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstSrcBswap *instruction) { Error err; ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); if (type_is_invalid(int_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *uncasted_op = instruction->op->child; + IrInstGen *uncasted_op = instruction->op->child; if (type_is_invalid(uncasted_op->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; uint32_t vector_len; // UINT32_MAX means not a vector if (uncasted_op->value->type->id == ZigTypeIdArray && @@ -28108,28 +28994,28 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction bool is_vector = (vector_len != UINT32_MAX); ZigType *op_type = is_vector ? get_vector_type(ira->codegen, vector_len, int_type) : int_type; - IrInstruction *op = ir_implicit_cast(ira, uncasted_op, op_type); + IrInstGen *op = ir_implicit_cast(ira, uncasted_op, op_type); if (type_is_invalid(op->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (int_type->data.integral.bit_count == 8 || int_type->data.integral.bit_count == 0) return op; if (int_type->data.integral.bit_count % 8 != 0) { - ir_add_error(ira, instruction->op, + ir_add_error(ira, &instruction->op->base, buf_sprintf("@byteSwap integer type '%s' has %" PRIu32 " bits which is not evenly divisible by 8", buf_ptr(&int_type->name), int_type->data.integral.bit_count)); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if (instr_is_comptime(op)) { ZigValue *val = ir_resolve_const(ira, op, UndefOk); if (val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (val->special == ConstValSpecialUndef) - return ir_const_undef(ira, &instruction->base, op_type); + return ir_const_undef(ira, &instruction->base.base, op_type); - IrInstruction *result = ir_const(ira, &instruction->base, op_type); + IrInstGen *result = ir_const(ira, &instruction->base.base, op_type); size_t buf_size = int_type->data.integral.bit_count / 8; uint8_t *buf = allocate_nonzero(buf_size); if (is_vector) { @@ -28137,10 +29023,10 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction result->value->data.x_array.data.s_none.elements = create_const_vals(op_type->data.vector.len); for (unsigned i = 0; i < op_type->data.vector.len; i += 1) { ZigValue *op_elem_val = &val->data.x_array.data.s_none.elements[i]; - if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, instruction->base.source_node, + if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, instruction->base.base.source_node, op_elem_val, UndefOk))) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ZigValue *result_elem_val = &result->value->data.x_array.data.s_none.elements[i]; result_elem_val->type = int_type; @@ -28162,23 +29048,20 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction return result; } - IrInstruction *result = ir_build_bswap(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, nullptr, op); - result->value->type = op_type; - return result; + return ir_build_bswap_gen(ira, &instruction->base.base, op_type, op); } -static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstructionBitReverse *instruction) { +static IrInstGen *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstSrcBitReverse *instruction) { ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); if (type_is_invalid(int_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *op = ir_implicit_cast(ira, instruction->op->child, int_type); + IrInstGen *op = ir_implicit_cast(ira, instruction->op->child, int_type); if (type_is_invalid(op->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (int_type->data.integral.bit_count == 0) { - IrInstruction *result = ir_const(ira, &instruction->base, int_type); + IrInstGen *result = ir_const(ira, &instruction->base.base, int_type); bigint_init_unsigned(&result->value->data.x_bigint, 0); return result; } @@ -28186,11 +29069,11 @@ static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstr if (instr_is_comptime(op)) { ZigValue *val = ir_resolve_const(ira, op, UndefOk); if (val == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (val->special == ConstValSpecialUndef) - return ir_const_undef(ira, &instruction->base, int_type); + return ir_const_undef(ira, &instruction->base.base, int_type); - IrInstruction *result = ir_const(ira, &instruction->base, int_type); + IrInstGen *result = ir_const(ira, &instruction->base.base, int_type); size_t num_bits = int_type->data.integral.bit_count; size_t buf_size = (num_bits + 7) / 8; uint8_t *comptime_buf = allocate_nonzero(buf_size); @@ -28217,128 +29100,125 @@ static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstr return result; } - IrInstruction *result = ir_build_bit_reverse(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, nullptr, op); - result->value->type = int_type; - return result; + return ir_build_bit_reverse_gen(ira, &instruction->base.base, int_type, op); } -static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) { - IrInstruction *target = instruction->target->child; +static IrInstGen *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstSrcEnumToInt *instruction) { + IrInstGen *target = instruction->target->child; if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_analyze_enum_to_int(ira, &instruction->base, target); + return ir_analyze_enum_to_int(ira, &instruction->base.base, target); } -static IrInstruction *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInstructionIntToEnum *instruction) { +static IrInstGen *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInstSrcIntToEnum *instruction) { Error err; - IrInstruction *dest_type_value = instruction->dest_type->child; + IrInstGen *dest_type_value = instruction->dest_type->child; ZigType *dest_type = ir_resolve_type(ira, dest_type_value); if (type_is_invalid(dest_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (dest_type->id != ZigTypeIdEnum) { - ir_add_error(ira, instruction->dest_type, + ir_add_error(ira, &instruction->dest_type->base, buf_sprintf("expected enum, found type '%s'", buf_ptr(&dest_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *tag_type = dest_type->data.enumeration.tag_int_type; - IrInstruction *target = instruction->target->child; + IrInstGen *target = instruction->target->child; if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *casted_target = ir_implicit_cast(ira, target, tag_type); + IrInstGen *casted_target = ir_implicit_cast(ira, target, tag_type); if (type_is_invalid(casted_target->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_analyze_int_to_enum(ira, &instruction->base, casted_target, dest_type); + return ir_analyze_int_to_enum(ira, &instruction->base.base, casted_target, dest_type); } -static IrInstruction *ir_analyze_instruction_check_runtime_scope(IrAnalyze *ira, IrInstructionCheckRuntimeScope *instruction) { - IrInstruction *block_comptime_inst = instruction->scope_is_comptime->child; +static IrInstGen *ir_analyze_instruction_check_runtime_scope(IrAnalyze *ira, IrInstSrcCheckRuntimeScope *instruction) { + IrInstGen *block_comptime_inst = instruction->scope_is_comptime->child; bool scope_is_comptime; if (!ir_resolve_bool(ira, block_comptime_inst, &scope_is_comptime)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *is_comptime_inst = instruction->is_comptime->child; + IrInstGen *is_comptime_inst = instruction->is_comptime->child; bool is_comptime; if (!ir_resolve_bool(ira, is_comptime_inst, &is_comptime)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (!scope_is_comptime && is_comptime) { - ErrorMsg *msg = ir_add_error(ira, &instruction->base, + ErrorMsg *msg = ir_add_error(ira, &instruction->base.base, buf_sprintf("comptime control flow inside runtime block")); - add_error_note(ira->codegen, msg, block_comptime_inst->source_node, + add_error_note(ira->codegen, msg, block_comptime_inst->base.source_node, buf_sprintf("runtime block created here")); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } -static IrInstruction *ir_analyze_instruction_has_decl(IrAnalyze *ira, IrInstructionHasDecl *instruction) { +static IrInstGen *ir_analyze_instruction_has_decl(IrAnalyze *ira, IrInstSrcHasDecl *instruction) { ZigType *container_type = ir_resolve_type(ira, instruction->container->child); if (type_is_invalid(container_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; Buf *name = ir_resolve_str(ira, instruction->name->child); if (name == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (!is_container(container_type)) { - ir_add_error(ira, instruction->container, + ir_add_error(ira, &instruction->container->base, buf_sprintf("expected struct, enum, or union; found '%s'", buf_ptr(&container_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } ScopeDecls *container_scope = get_container_scope(container_type); Tld *tld = find_container_decl(ira->codegen, container_scope, name); if (tld == nullptr) - return ir_const_bool(ira, &instruction->base, false); + return ir_const_bool(ira, &instruction->base.base, false); - if (tld->visib_mod == VisibModPrivate && tld->import != get_scope_import(instruction->base.scope)) { - return ir_const_bool(ira, &instruction->base, false); + if (tld->visib_mod == VisibModPrivate && tld->import != get_scope_import(instruction->base.base.scope)) { + return ir_const_bool(ira, &instruction->base.base, false); } - return ir_const_bool(ira, &instruction->base, true); + return ir_const_bool(ira, &instruction->base.base, true); } -static IrInstruction *ir_analyze_instruction_undeclared_ident(IrAnalyze *ira, IrInstructionUndeclaredIdent *instruction) { +static IrInstGen *ir_analyze_instruction_undeclared_ident(IrAnalyze *ira, IrInstSrcUndeclaredIdent *instruction) { // put a variable of same name with invalid type in global scope // so that future references to this same name will find a variable with an invalid type - populate_invalid_variable_in_scope(ira->codegen, instruction->base.scope, instruction->base.source_node, - instruction->name); - ir_add_error(ira, &instruction->base, + populate_invalid_variable_in_scope(ira->codegen, instruction->base.base.scope, + instruction->base.base.source_node, instruction->name); + ir_add_error(ira, &instruction->base.base, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(instruction->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } -static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstructionEndExpr *instruction) { - IrInstruction *value = instruction->value->child; +static IrInstGen *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstSrcEndExpr *instruction) { + IrInstGen *value = instruction->value->child; if (type_is_invalid(value->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; bool was_written = instruction->result_loc->written; - IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, + IrInstGen *result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc, value->value->type, value, false, true); if (result_loc != nullptr) { if (type_is_invalid(result_loc->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (result_loc->value->type->id == ZigTypeIdUnreachable) return result_loc; if (!was_written || instruction->result_loc->id == ResultLocIdPeer) { - IrInstruction *store_ptr = ir_analyze_store_ptr(ira, &instruction->base, result_loc, value, + IrInstGen *store_ptr = ir_analyze_store_ptr(ira, &instruction->base.base, result_loc, value, instruction->result_loc->allow_write_through_const); if (type_is_invalid(store_ptr->value->type)) { - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } } @@ -28353,101 +29233,100 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct } } - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); } -static IrInstruction *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, IrInstructionImplicitCast *instruction) { - IrInstruction *operand = instruction->operand->child; +static IrInstGen *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, IrInstSrcImplicitCast *instruction) { + IrInstGen *operand = instruction->operand->child; if (type_is_invalid(operand->value->type)) return operand; ZigType *dest_type = ir_resolve_type(ira, instruction->result_loc_cast->base.source_instruction->child); if (type_is_invalid(dest_type)) - return ira->codegen->invalid_instruction; - return ir_implicit_cast2(ira, &instruction->base, operand, dest_type); + return ira->codegen->invalid_inst_gen; + return ir_implicit_cast2(ira, &instruction->base.base, operand, dest_type); } -static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInstructionBitCastSrc *instruction) { - IrInstruction *operand = instruction->operand->child; +static IrInstGen *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInstSrcBitCast *instruction) { + IrInstGen *operand = instruction->operand->child; if (type_is_invalid(operand->value->type)) return operand; - IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, + IrInstGen *result_loc = ir_resolve_result(ira, &instruction->base.base, &instruction->result_loc_bit_cast->base, operand->value->type, operand, false, true); - if (result_loc != nullptr && (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc))) + if (result_loc != nullptr && + (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable)) + { return result_loc; + } ZigType *dest_type = ir_resolve_type(ira, instruction->result_loc_bit_cast->base.source_instruction->child); if (type_is_invalid(dest_type)) - return ira->codegen->invalid_instruction; - return ir_analyze_bit_cast(ira, &instruction->base, operand, dest_type); + return ira->codegen->invalid_inst_gen; + return ir_analyze_bit_cast(ira, &instruction->base.base, operand, dest_type); } -static IrInstruction *ir_analyze_instruction_union_init_named_field(IrAnalyze *ira, - IrInstructionUnionInitNamedField *instruction) +static IrInstGen *ir_analyze_instruction_union_init_named_field(IrAnalyze *ira, + IrInstSrcUnionInitNamedField *instruction) { ZigType *union_type = ir_resolve_type(ira, instruction->union_type->child); if (type_is_invalid(union_type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (union_type->id != ZigTypeIdUnion) { - ir_add_error(ira, instruction->union_type, + ir_add_error(ira, &instruction->union_type->base, buf_sprintf("non-union type '%s' passed to @unionInit", buf_ptr(&union_type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } Buf *field_name = ir_resolve_str(ira, instruction->field_name->child); if (field_name == nullptr) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *field_result_loc = instruction->field_result_loc->child; + IrInstGen *field_result_loc = instruction->field_result_loc->child; if (type_is_invalid(field_result_loc->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *result_loc = instruction->result_loc->child; + IrInstGen *result_loc = instruction->result_loc->child; if (type_is_invalid(result_loc->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_analyze_union_init(ira, &instruction->base, instruction->base.source_node, + return ir_analyze_union_init(ira, &instruction->base.base, instruction->base.base.source_node, union_type, field_name, field_result_loc, result_loc); } -static IrInstruction *ir_analyze_instruction_suspend_begin(IrAnalyze *ira, IrInstructionSuspendBegin *instruction) { - IrInstructionSuspendBegin *result = ir_build_suspend_begin(&ira->new_irb, instruction->base.scope, - instruction->base.source_node); - return &result->base; +static IrInstGen *ir_analyze_instruction_suspend_begin(IrAnalyze *ira, IrInstSrcSuspendBegin *instruction) { + return ir_build_suspend_begin_gen(ira, &instruction->base.base); } -static IrInstruction *ir_analyze_instruction_suspend_finish(IrAnalyze *ira, - IrInstructionSuspendFinish *instruction) -{ - IrInstruction *begin_base = instruction->begin->base.child; +static IrInstGen *ir_analyze_instruction_suspend_finish(IrAnalyze *ira, IrInstSrcSuspendFinish *instruction) { + IrInstGen *begin_base = instruction->begin->base.child; if (type_is_invalid(begin_base->value->type)) - return ira->codegen->invalid_instruction; - ir_assert(begin_base->id == IrInstructionIdSuspendBegin, &instruction->base); - IrInstructionSuspendBegin *begin = reinterpret_cast(begin_base); + return ira->codegen->invalid_inst_gen; + ir_assert(begin_base->id == IrInstGenIdSuspendBegin, &instruction->base.base); + IrInstGenSuspendBegin *begin = reinterpret_cast(begin_base); - ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); - ir_assert(fn_entry != nullptr, &instruction->base); + ZigFn *fn_entry = ira->new_irb.exec->fn_entry; + ir_assert(fn_entry != nullptr, &instruction->base.base); if (fn_entry->inferred_async_node == nullptr) { - fn_entry->inferred_async_node = instruction->base.source_node; + fn_entry->inferred_async_node = instruction->base.base.source_node; } - return ir_build_suspend_finish(&ira->new_irb, instruction->base.scope, instruction->base.source_node, begin); + return ir_build_suspend_finish_gen(ira, &instruction->base.base, begin); } -static IrInstruction *analyze_frame_ptr_to_anyframe_T(IrAnalyze *ira, IrInstruction *source_instr, - IrInstruction *frame_ptr, ZigFn **target_fn) +static IrInstGen *analyze_frame_ptr_to_anyframe_T(IrAnalyze *ira, IrInst* source_instr, + IrInstGen *frame_ptr, ZigFn **target_fn) { if (type_is_invalid(frame_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; *target_fn = nullptr; ZigType *result_type; - IrInstruction *frame; + IrInstGen *frame; if (frame_ptr->value->type->id == ZigTypeIdPointer && frame_ptr->value->type->data.pointer.ptr_len == PtrLenSingle && frame_ptr->value->type->data.pointer.child_type->id == ZigTypeIdFnFrame) @@ -28470,38 +29349,38 @@ static IrInstruction *analyze_frame_ptr_to_anyframe_T(IrAnalyze *ira, IrInstruct { ir_add_error(ira, source_instr, buf_sprintf("expected anyframe->T, found '%s'", buf_ptr(&frame->value->type->name))); - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; } else { result_type = frame->value->type->data.any_frame.result_type; } } ZigType *any_frame_type = get_any_frame_type(ira->codegen, result_type); - IrInstruction *casted_frame = ir_implicit_cast(ira, frame, any_frame_type); + IrInstGen *casted_frame = ir_implicit_cast(ira, frame, any_frame_type); if (type_is_invalid(casted_frame->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; return casted_frame; } -static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstructionAwaitSrc *instruction) { - IrInstruction *operand = instruction->frame->child; +static IrInstGen *ir_analyze_instruction_await(IrAnalyze *ira, IrInstSrcAwait *instruction) { + IrInstGen *operand = instruction->frame->child; if (type_is_invalid(operand->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigFn *target_fn; - IrInstruction *frame = analyze_frame_ptr_to_anyframe_T(ira, &instruction->base, operand, &target_fn); + IrInstGen *frame = analyze_frame_ptr_to_anyframe_T(ira, &instruction->base.base, operand, &target_fn); if (type_is_invalid(frame->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; ZigType *result_type = frame->value->type->data.any_frame.result_type; - ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); - ir_assert(fn_entry != nullptr, &instruction->base); + ZigFn *fn_entry = ira->new_irb.exec->fn_entry; + ir_assert(fn_entry != nullptr, &instruction->base.base); // If it's not @Frame(func) then it's definitely a suspend point if (target_fn == nullptr) { if (fn_entry->inferred_async_node == nullptr) { - fn_entry->inferred_async_node = instruction->base.source_node; + fn_entry->inferred_async_node = instruction->base.base.source_node; } } @@ -28509,401 +29388,367 @@ static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstruction fn_entry->calls_or_awaits_errorable_fn = true; } - IrInstruction *result_loc; + IrInstGen *result_loc; if (type_has_bits(result_type)) { - result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, + result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc, result_type, nullptr, true, true); - if (result_loc != nullptr && (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc))) + if (result_loc != nullptr && + (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable)) + { return result_loc; + } } else { result_loc = nullptr; } - IrInstructionAwaitGen *result = ir_build_await_gen(ira, &instruction->base, frame, result_type, result_loc); + IrInstGenAwait *result = ir_build_await_gen(ira, &instruction->base.base, frame, result_type, result_loc); result->target_fn = target_fn; fn_entry->await_list.append(result); return ir_finish_anal(ira, &result->base); } -static IrInstruction *ir_analyze_instruction_resume(IrAnalyze *ira, IrInstructionResume *instruction) { - IrInstruction *frame_ptr = instruction->frame->child; +static IrInstGen *ir_analyze_instruction_resume(IrAnalyze *ira, IrInstSrcResume *instruction) { + IrInstGen *frame_ptr = instruction->frame->child; if (type_is_invalid(frame_ptr->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - IrInstruction *frame; + IrInstGen *frame; if (frame_ptr->value->type->id == ZigTypeIdPointer && frame_ptr->value->type->data.pointer.ptr_len == PtrLenSingle && frame_ptr->value->type->data.pointer.child_type->id == ZigTypeIdFnFrame) { frame = frame_ptr; } else { - frame = ir_get_deref(ira, &instruction->base, frame_ptr, nullptr); + frame = ir_get_deref(ira, &instruction->base.base, frame_ptr, nullptr); } ZigType *any_frame_type = get_any_frame_type(ira->codegen, nullptr); - IrInstruction *casted_frame = ir_implicit_cast(ira, frame, any_frame_type); + IrInstGen *casted_frame = ir_implicit_cast(ira, frame, any_frame_type); if (type_is_invalid(casted_frame->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - return ir_build_resume(&ira->new_irb, instruction->base.scope, instruction->base.source_node, casted_frame); + return ir_build_resume_gen(ira, &instruction->base.base, casted_frame); } -static IrInstruction *ir_analyze_instruction_spill_begin(IrAnalyze *ira, IrInstructionSpillBegin *instruction) { - if (ir_should_inline(ira->new_irb.exec, instruction->base.scope)) - return ir_const_void(ira, &instruction->base); +static IrInstGen *ir_analyze_instruction_spill_begin(IrAnalyze *ira, IrInstSrcSpillBegin *instruction) { + if (ir_should_inline(ira->old_irb.exec, instruction->base.base.scope)) + return ir_const_void(ira, &instruction->base.base); - IrInstruction *operand = instruction->operand->child; + IrInstGen *operand = instruction->operand->child; if (type_is_invalid(operand->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; if (!type_has_bits(operand->value->type)) - return ir_const_void(ira, &instruction->base); + return ir_const_void(ira, &instruction->base.base); - ir_assert(instruction->spill_id == SpillIdRetErrCode, &instruction->base); + ir_assert(instruction->spill_id == SpillIdRetErrCode, &instruction->base.base); ira->new_irb.exec->need_err_code_spill = true; - IrInstructionSpillBegin *result = ir_build_spill_begin(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, operand, instruction->spill_id); - return &result->base; + return ir_build_spill_begin_gen(ira, &instruction->base.base, operand, instruction->spill_id); } -static IrInstruction *ir_analyze_instruction_spill_end(IrAnalyze *ira, IrInstructionSpillEnd *instruction) { - IrInstruction *operand = instruction->begin->operand->child; +static IrInstGen *ir_analyze_instruction_spill_end(IrAnalyze *ira, IrInstSrcSpillEnd *instruction) { + IrInstGen *operand = instruction->begin->operand->child; if (type_is_invalid(operand->value->type)) - return ira->codegen->invalid_instruction; + return ira->codegen->invalid_inst_gen; - if (ir_should_inline(ira->new_irb.exec, instruction->base.scope) || !type_has_bits(operand->value->type)) + if (ir_should_inline(ira->old_irb.exec, instruction->base.base.scope) || !type_has_bits(operand->value->type)) return operand; - ir_assert(instruction->begin->base.child->id == IrInstructionIdSpillBegin, &instruction->base); - IrInstructionSpillBegin *begin = reinterpret_cast(instruction->begin->base.child); + ir_assert(instruction->begin->base.child->id == IrInstGenIdSpillBegin, &instruction->base.base); + IrInstGenSpillBegin *begin = reinterpret_cast(instruction->begin->base.child); - IrInstruction *result = ir_build_spill_end(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, begin); - result->value->type = operand->value->type; - return result; + return ir_build_spill_end_gen(ira, &instruction->base.base, begin, operand->value->type); } -static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) { +static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruction) { switch (instruction->id) { - case IrInstructionIdInvalid: - case IrInstructionIdWidenOrShorten: - case IrInstructionIdStructFieldPtr: - case IrInstructionIdUnionFieldPtr: - case IrInstructionIdOptionalWrap: - case IrInstructionIdErrWrapCode: - case IrInstructionIdErrWrapPayload: - case IrInstructionIdCast: - case IrInstructionIdDeclVarGen: - case IrInstructionIdPtrCastGen: - case IrInstructionIdCmpxchgGen: - case IrInstructionIdArrayToVector: - case IrInstructionIdVectorToArray: - case IrInstructionIdPtrOfArrayToSlice: - case IrInstructionIdAssertZero: - case IrInstructionIdAssertNonNull: - case IrInstructionIdResizeSlice: - case IrInstructionIdLoadPtrGen: - case IrInstructionIdBitCastGen: - case IrInstructionIdCallGen: - case IrInstructionIdReturnPtr: - case IrInstructionIdAllocaGen: - case IrInstructionIdSliceGen: - case IrInstructionIdRefGen: - case IrInstructionIdTestErrGen: - case IrInstructionIdFrameSizeGen: - case IrInstructionIdAwaitGen: - case IrInstructionIdSplatGen: - case IrInstructionIdVectorExtractElem: - case IrInstructionIdVectorStoreElem: - case IrInstructionIdAsmGen: + case IrInstSrcIdInvalid: zig_unreachable(); - case IrInstructionIdReturn: - return ir_analyze_instruction_return(ira, (IrInstructionReturn *)instruction); - case IrInstructionIdConst: - return ir_analyze_instruction_const(ira, (IrInstructionConst *)instruction); - case IrInstructionIdUnOp: - return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction); - case IrInstructionIdBinOp: - return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction); - case IrInstructionIdMergeErrSets: - return ir_analyze_instruction_merge_err_sets(ira, (IrInstructionMergeErrSets *)instruction); - case IrInstructionIdDeclVarSrc: - return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVarSrc *)instruction); - case IrInstructionIdLoadPtr: - return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction); - case IrInstructionIdStorePtr: - return ir_analyze_instruction_store_ptr(ira, (IrInstructionStorePtr *)instruction); - case IrInstructionIdElemPtr: - return ir_analyze_instruction_elem_ptr(ira, (IrInstructionElemPtr *)instruction); - case IrInstructionIdVarPtr: - return ir_analyze_instruction_var_ptr(ira, (IrInstructionVarPtr *)instruction); - case IrInstructionIdFieldPtr: - return ir_analyze_instruction_field_ptr(ira, (IrInstructionFieldPtr *)instruction); - case IrInstructionIdCallSrc: - return ir_analyze_instruction_call(ira, (IrInstructionCallSrc *)instruction); - case IrInstructionIdCallSrcArgs: - return ir_analyze_instruction_call_args(ira, (IrInstructionCallSrcArgs *)instruction); - case IrInstructionIdCallExtra: - return ir_analyze_instruction_call_extra(ira, (IrInstructionCallExtra *)instruction); - case IrInstructionIdBr: - return ir_analyze_instruction_br(ira, (IrInstructionBr *)instruction); - case IrInstructionIdCondBr: - return ir_analyze_instruction_cond_br(ira, (IrInstructionCondBr *)instruction); - case IrInstructionIdUnreachable: - return ir_analyze_instruction_unreachable(ira, (IrInstructionUnreachable *)instruction); - case IrInstructionIdPhi: - return ir_analyze_instruction_phi(ira, (IrInstructionPhi *)instruction); - case IrInstructionIdTypeOf: - return ir_analyze_instruction_typeof(ira, (IrInstructionTypeOf *)instruction); - case IrInstructionIdSetCold: - return ir_analyze_instruction_set_cold(ira, (IrInstructionSetCold *)instruction); - case IrInstructionIdSetRuntimeSafety: - return ir_analyze_instruction_set_runtime_safety(ira, (IrInstructionSetRuntimeSafety *)instruction); - case IrInstructionIdSetFloatMode: - return ir_analyze_instruction_set_float_mode(ira, (IrInstructionSetFloatMode *)instruction); - case IrInstructionIdAnyFrameType: - return ir_analyze_instruction_any_frame_type(ira, (IrInstructionAnyFrameType *)instruction); - case IrInstructionIdSliceType: - return ir_analyze_instruction_slice_type(ira, (IrInstructionSliceType *)instruction); - case IrInstructionIdAsmSrc: - return ir_analyze_instruction_asm(ira, (IrInstructionAsmSrc *)instruction); - case IrInstructionIdArrayType: - return ir_analyze_instruction_array_type(ira, (IrInstructionArrayType *)instruction); - case IrInstructionIdSizeOf: - return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction); - case IrInstructionIdTestNonNull: - return ir_analyze_instruction_test_non_null(ira, (IrInstructionTestNonNull *)instruction); - case IrInstructionIdOptionalUnwrapPtr: - return ir_analyze_instruction_optional_unwrap_ptr(ira, (IrInstructionOptionalUnwrapPtr *)instruction); - case IrInstructionIdClz: - return ir_analyze_instruction_clz(ira, (IrInstructionClz *)instruction); - case IrInstructionIdCtz: - return ir_analyze_instruction_ctz(ira, (IrInstructionCtz *)instruction); - case IrInstructionIdPopCount: - return ir_analyze_instruction_pop_count(ira, (IrInstructionPopCount *)instruction); - case IrInstructionIdBswap: - return ir_analyze_instruction_bswap(ira, (IrInstructionBswap *)instruction); - case IrInstructionIdBitReverse: - return ir_analyze_instruction_bit_reverse(ira, (IrInstructionBitReverse *)instruction); - case IrInstructionIdSwitchBr: - return ir_analyze_instruction_switch_br(ira, (IrInstructionSwitchBr *)instruction); - case IrInstructionIdSwitchTarget: - return ir_analyze_instruction_switch_target(ira, (IrInstructionSwitchTarget *)instruction); - case IrInstructionIdSwitchVar: - return ir_analyze_instruction_switch_var(ira, (IrInstructionSwitchVar *)instruction); - case IrInstructionIdSwitchElseVar: - return ir_analyze_instruction_switch_else_var(ira, (IrInstructionSwitchElseVar *)instruction); - case IrInstructionIdUnionTag: - return ir_analyze_instruction_union_tag(ira, (IrInstructionUnionTag *)instruction); - case IrInstructionIdImport: - return ir_analyze_instruction_import(ira, (IrInstructionImport *)instruction); - case IrInstructionIdRef: - return ir_analyze_instruction_ref(ira, (IrInstructionRef *)instruction); - case IrInstructionIdContainerInitList: - return ir_analyze_instruction_container_init_list(ira, (IrInstructionContainerInitList *)instruction); - case IrInstructionIdContainerInitFields: - return ir_analyze_instruction_container_init_fields(ira, (IrInstructionContainerInitFields *)instruction); - case IrInstructionIdCompileErr: - return ir_analyze_instruction_compile_err(ira, (IrInstructionCompileErr *)instruction); - case IrInstructionIdCompileLog: - return ir_analyze_instruction_compile_log(ira, (IrInstructionCompileLog *)instruction); - case IrInstructionIdErrName: - return ir_analyze_instruction_err_name(ira, (IrInstructionErrName *)instruction); - case IrInstructionIdTypeName: - return ir_analyze_instruction_type_name(ira, (IrInstructionTypeName *)instruction); - case IrInstructionIdCImport: - return ir_analyze_instruction_c_import(ira, (IrInstructionCImport *)instruction); - case IrInstructionIdCInclude: - return ir_analyze_instruction_c_include(ira, (IrInstructionCInclude *)instruction); - case IrInstructionIdCDefine: - return ir_analyze_instruction_c_define(ira, (IrInstructionCDefine *)instruction); - case IrInstructionIdCUndef: - return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction); - case IrInstructionIdEmbedFile: - return ir_analyze_instruction_embed_file(ira, (IrInstructionEmbedFile *)instruction); - case IrInstructionIdCmpxchgSrc: - return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchgSrc *)instruction); - case IrInstructionIdFence: - return ir_analyze_instruction_fence(ira, (IrInstructionFence *)instruction); - case IrInstructionIdTruncate: - return ir_analyze_instruction_truncate(ira, (IrInstructionTruncate *)instruction); - case IrInstructionIdIntCast: - return ir_analyze_instruction_int_cast(ira, (IrInstructionIntCast *)instruction); - case IrInstructionIdFloatCast: - return ir_analyze_instruction_float_cast(ira, (IrInstructionFloatCast *)instruction); - case IrInstructionIdErrSetCast: - return ir_analyze_instruction_err_set_cast(ira, (IrInstructionErrSetCast *)instruction); - case IrInstructionIdFromBytes: - return ir_analyze_instruction_from_bytes(ira, (IrInstructionFromBytes *)instruction); - case IrInstructionIdToBytes: - return ir_analyze_instruction_to_bytes(ira, (IrInstructionToBytes *)instruction); - case IrInstructionIdIntToFloat: - return ir_analyze_instruction_int_to_float(ira, (IrInstructionIntToFloat *)instruction); - case IrInstructionIdFloatToInt: - return ir_analyze_instruction_float_to_int(ira, (IrInstructionFloatToInt *)instruction); - case IrInstructionIdBoolToInt: - return ir_analyze_instruction_bool_to_int(ira, (IrInstructionBoolToInt *)instruction); - case IrInstructionIdIntType: - return ir_analyze_instruction_int_type(ira, (IrInstructionIntType *)instruction); - case IrInstructionIdVectorType: - return ir_analyze_instruction_vector_type(ira, (IrInstructionVectorType *)instruction); - case IrInstructionIdShuffleVector: - return ir_analyze_instruction_shuffle_vector(ira, (IrInstructionShuffleVector *)instruction); - case IrInstructionIdSplatSrc: - return ir_analyze_instruction_splat(ira, (IrInstructionSplatSrc *)instruction); - case IrInstructionIdBoolNot: - return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction); - case IrInstructionIdMemset: - return ir_analyze_instruction_memset(ira, (IrInstructionMemset *)instruction); - case IrInstructionIdMemcpy: - return ir_analyze_instruction_memcpy(ira, (IrInstructionMemcpy *)instruction); - case IrInstructionIdSliceSrc: - return ir_analyze_instruction_slice(ira, (IrInstructionSliceSrc *)instruction); - case IrInstructionIdMemberCount: - return ir_analyze_instruction_member_count(ira, (IrInstructionMemberCount *)instruction); - case IrInstructionIdMemberType: - return ir_analyze_instruction_member_type(ira, (IrInstructionMemberType *)instruction); - case IrInstructionIdMemberName: - return ir_analyze_instruction_member_name(ira, (IrInstructionMemberName *)instruction); - case IrInstructionIdBreakpoint: - return ir_analyze_instruction_breakpoint(ira, (IrInstructionBreakpoint *)instruction); - case IrInstructionIdReturnAddress: - return ir_analyze_instruction_return_address(ira, (IrInstructionReturnAddress *)instruction); - case IrInstructionIdFrameAddress: - return ir_analyze_instruction_frame_address(ira, (IrInstructionFrameAddress *)instruction); - case IrInstructionIdFrameHandle: - return ir_analyze_instruction_frame_handle(ira, (IrInstructionFrameHandle *)instruction); - case IrInstructionIdFrameType: - return ir_analyze_instruction_frame_type(ira, (IrInstructionFrameType *)instruction); - case IrInstructionIdFrameSizeSrc: - return ir_analyze_instruction_frame_size(ira, (IrInstructionFrameSizeSrc *)instruction); - case IrInstructionIdAlignOf: - return ir_analyze_instruction_align_of(ira, (IrInstructionAlignOf *)instruction); - case IrInstructionIdOverflowOp: - return ir_analyze_instruction_overflow_op(ira, (IrInstructionOverflowOp *)instruction); - case IrInstructionIdTestErrSrc: - return ir_analyze_instruction_test_err(ira, (IrInstructionTestErrSrc *)instruction); - case IrInstructionIdUnwrapErrCode: - return ir_analyze_instruction_unwrap_err_code(ira, (IrInstructionUnwrapErrCode *)instruction); - case IrInstructionIdUnwrapErrPayload: - return ir_analyze_instruction_unwrap_err_payload(ira, (IrInstructionUnwrapErrPayload *)instruction); - case IrInstructionIdFnProto: - return ir_analyze_instruction_fn_proto(ira, (IrInstructionFnProto *)instruction); - case IrInstructionIdTestComptime: - return ir_analyze_instruction_test_comptime(ira, (IrInstructionTestComptime *)instruction); - case IrInstructionIdCheckSwitchProngs: - return ir_analyze_instruction_check_switch_prongs(ira, (IrInstructionCheckSwitchProngs *)instruction); - case IrInstructionIdCheckStatementIsVoid: - return ir_analyze_instruction_check_statement_is_void(ira, (IrInstructionCheckStatementIsVoid *)instruction); - case IrInstructionIdDeclRef: - return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction); - case IrInstructionIdPanic: - return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction); - case IrInstructionIdPtrCastSrc: - return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCastSrc *)instruction); - case IrInstructionIdIntToPtr: - return ir_analyze_instruction_int_to_ptr(ira, (IrInstructionIntToPtr *)instruction); - case IrInstructionIdPtrToInt: - return ir_analyze_instruction_ptr_to_int(ira, (IrInstructionPtrToInt *)instruction); - case IrInstructionIdTagName: - return ir_analyze_instruction_enum_tag_name(ira, (IrInstructionTagName *)instruction); - case IrInstructionIdFieldParentPtr: - return ir_analyze_instruction_field_parent_ptr(ira, (IrInstructionFieldParentPtr *)instruction); - case IrInstructionIdByteOffsetOf: - return ir_analyze_instruction_byte_offset_of(ira, (IrInstructionByteOffsetOf *)instruction); - case IrInstructionIdBitOffsetOf: - return ir_analyze_instruction_bit_offset_of(ira, (IrInstructionBitOffsetOf *)instruction); - case IrInstructionIdTypeInfo: - return ir_analyze_instruction_type_info(ira, (IrInstructionTypeInfo *) instruction); - case IrInstructionIdType: - return ir_analyze_instruction_type(ira, (IrInstructionType *)instruction); - case IrInstructionIdHasField: - return ir_analyze_instruction_has_field(ira, (IrInstructionHasField *) instruction); - case IrInstructionIdTypeId: - return ir_analyze_instruction_type_id(ira, (IrInstructionTypeId *)instruction); - case IrInstructionIdSetEvalBranchQuota: - return ir_analyze_instruction_set_eval_branch_quota(ira, (IrInstructionSetEvalBranchQuota *)instruction); - case IrInstructionIdPtrType: - return ir_analyze_instruction_ptr_type(ira, (IrInstructionPtrType *)instruction); - case IrInstructionIdAlignCast: - return ir_analyze_instruction_align_cast(ira, (IrInstructionAlignCast *)instruction); - case IrInstructionIdImplicitCast: - return ir_analyze_instruction_implicit_cast(ira, (IrInstructionImplicitCast *)instruction); - case IrInstructionIdResolveResult: - return ir_analyze_instruction_resolve_result(ira, (IrInstructionResolveResult *)instruction); - case IrInstructionIdResetResult: - return ir_analyze_instruction_reset_result(ira, (IrInstructionResetResult *)instruction); - case IrInstructionIdOpaqueType: - return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction); - case IrInstructionIdSetAlignStack: - return ir_analyze_instruction_set_align_stack(ira, (IrInstructionSetAlignStack *)instruction); - case IrInstructionIdArgType: - return ir_analyze_instruction_arg_type(ira, (IrInstructionArgType *)instruction); - case IrInstructionIdTagType: - return ir_analyze_instruction_tag_type(ira, (IrInstructionTagType *)instruction); - case IrInstructionIdExport: - return ir_analyze_instruction_export(ira, (IrInstructionExport *)instruction); - case IrInstructionIdErrorReturnTrace: - return ir_analyze_instruction_error_return_trace(ira, (IrInstructionErrorReturnTrace *)instruction); - case IrInstructionIdErrorUnion: - return ir_analyze_instruction_error_union(ira, (IrInstructionErrorUnion *)instruction); - case IrInstructionIdAtomicRmw: - return ir_analyze_instruction_atomic_rmw(ira, (IrInstructionAtomicRmw *)instruction); - case IrInstructionIdAtomicLoad: - return ir_analyze_instruction_atomic_load(ira, (IrInstructionAtomicLoad *)instruction); - case IrInstructionIdAtomicStore: - return ir_analyze_instruction_atomic_store(ira, (IrInstructionAtomicStore *)instruction); - case IrInstructionIdSaveErrRetAddr: - return ir_analyze_instruction_save_err_ret_addr(ira, (IrInstructionSaveErrRetAddr *)instruction); - case IrInstructionIdAddImplicitReturnType: - return ir_analyze_instruction_add_implicit_return_type(ira, (IrInstructionAddImplicitReturnType *)instruction); - case IrInstructionIdFloatOp: - return ir_analyze_instruction_float_op(ira, (IrInstructionFloatOp *)instruction); - case IrInstructionIdMulAdd: - return ir_analyze_instruction_mul_add(ira, (IrInstructionMulAdd *)instruction); - case IrInstructionIdIntToErr: - return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction); - case IrInstructionIdErrToInt: - return ir_analyze_instruction_err_to_int(ira, (IrInstructionErrToInt *)instruction); - case IrInstructionIdIntToEnum: - return ir_analyze_instruction_int_to_enum(ira, (IrInstructionIntToEnum *)instruction); - case IrInstructionIdEnumToInt: - return ir_analyze_instruction_enum_to_int(ira, (IrInstructionEnumToInt *)instruction); - case IrInstructionIdCheckRuntimeScope: - return ir_analyze_instruction_check_runtime_scope(ira, (IrInstructionCheckRuntimeScope *)instruction); - case IrInstructionIdHasDecl: - return ir_analyze_instruction_has_decl(ira, (IrInstructionHasDecl *)instruction); - case IrInstructionIdUndeclaredIdent: - return ir_analyze_instruction_undeclared_ident(ira, (IrInstructionUndeclaredIdent *)instruction); - case IrInstructionIdAllocaSrc: + case IrInstSrcIdReturn: + return ir_analyze_instruction_return(ira, (IrInstSrcReturn *)instruction); + case IrInstSrcIdConst: + return ir_analyze_instruction_const(ira, (IrInstSrcConst *)instruction); + case IrInstSrcIdUnOp: + return ir_analyze_instruction_un_op(ira, (IrInstSrcUnOp *)instruction); + case IrInstSrcIdBinOp: + return ir_analyze_instruction_bin_op(ira, (IrInstSrcBinOp *)instruction); + case IrInstSrcIdMergeErrSets: + return ir_analyze_instruction_merge_err_sets(ira, (IrInstSrcMergeErrSets *)instruction); + case IrInstSrcIdDeclVar: + return ir_analyze_instruction_decl_var(ira, (IrInstSrcDeclVar *)instruction); + case IrInstSrcIdLoadPtr: + return ir_analyze_instruction_load_ptr(ira, (IrInstSrcLoadPtr *)instruction); + case IrInstSrcIdStorePtr: + return ir_analyze_instruction_store_ptr(ira, (IrInstSrcStorePtr *)instruction); + case IrInstSrcIdElemPtr: + return ir_analyze_instruction_elem_ptr(ira, (IrInstSrcElemPtr *)instruction); + case IrInstSrcIdVarPtr: + return ir_analyze_instruction_var_ptr(ira, (IrInstSrcVarPtr *)instruction); + case IrInstSrcIdFieldPtr: + return ir_analyze_instruction_field_ptr(ira, (IrInstSrcFieldPtr *)instruction); + case IrInstSrcIdCall: + return ir_analyze_instruction_call(ira, (IrInstSrcCall *)instruction); + case IrInstSrcIdCallArgs: + return ir_analyze_instruction_call_args(ira, (IrInstSrcCallArgs *)instruction); + case IrInstSrcIdCallExtra: + return ir_analyze_instruction_call_extra(ira, (IrInstSrcCallExtra *)instruction); + case IrInstSrcIdBr: + return ir_analyze_instruction_br(ira, (IrInstSrcBr *)instruction); + case IrInstSrcIdCondBr: + return ir_analyze_instruction_cond_br(ira, (IrInstSrcCondBr *)instruction); + case IrInstSrcIdUnreachable: + return ir_analyze_instruction_unreachable(ira, (IrInstSrcUnreachable *)instruction); + case IrInstSrcIdPhi: + return ir_analyze_instruction_phi(ira, (IrInstSrcPhi *)instruction); + case IrInstSrcIdTypeOf: + return ir_analyze_instruction_typeof(ira, (IrInstSrcTypeOf *)instruction); + case IrInstSrcIdSetCold: + return ir_analyze_instruction_set_cold(ira, (IrInstSrcSetCold *)instruction); + case IrInstSrcIdSetRuntimeSafety: + return ir_analyze_instruction_set_runtime_safety(ira, (IrInstSrcSetRuntimeSafety *)instruction); + case IrInstSrcIdSetFloatMode: + return ir_analyze_instruction_set_float_mode(ira, (IrInstSrcSetFloatMode *)instruction); + case IrInstSrcIdAnyFrameType: + return ir_analyze_instruction_any_frame_type(ira, (IrInstSrcAnyFrameType *)instruction); + case IrInstSrcIdSliceType: + return ir_analyze_instruction_slice_type(ira, (IrInstSrcSliceType *)instruction); + case IrInstSrcIdAsm: + return ir_analyze_instruction_asm(ira, (IrInstSrcAsm *)instruction); + case IrInstSrcIdArrayType: + return ir_analyze_instruction_array_type(ira, (IrInstSrcArrayType *)instruction); + case IrInstSrcIdSizeOf: + return ir_analyze_instruction_size_of(ira, (IrInstSrcSizeOf *)instruction); + case IrInstSrcIdTestNonNull: + return ir_analyze_instruction_test_non_null(ira, (IrInstSrcTestNonNull *)instruction); + case IrInstSrcIdOptionalUnwrapPtr: + return ir_analyze_instruction_optional_unwrap_ptr(ira, (IrInstSrcOptionalUnwrapPtr *)instruction); + case IrInstSrcIdClz: + return ir_analyze_instruction_clz(ira, (IrInstSrcClz *)instruction); + case IrInstSrcIdCtz: + return ir_analyze_instruction_ctz(ira, (IrInstSrcCtz *)instruction); + case IrInstSrcIdPopCount: + return ir_analyze_instruction_pop_count(ira, (IrInstSrcPopCount *)instruction); + case IrInstSrcIdBswap: + return ir_analyze_instruction_bswap(ira, (IrInstSrcBswap *)instruction); + case IrInstSrcIdBitReverse: + return ir_analyze_instruction_bit_reverse(ira, (IrInstSrcBitReverse *)instruction); + case IrInstSrcIdSwitchBr: + return ir_analyze_instruction_switch_br(ira, (IrInstSrcSwitchBr *)instruction); + case IrInstSrcIdSwitchTarget: + return ir_analyze_instruction_switch_target(ira, (IrInstSrcSwitchTarget *)instruction); + case IrInstSrcIdSwitchVar: + return ir_analyze_instruction_switch_var(ira, (IrInstSrcSwitchVar *)instruction); + case IrInstSrcIdSwitchElseVar: + return ir_analyze_instruction_switch_else_var(ira, (IrInstSrcSwitchElseVar *)instruction); + case IrInstSrcIdImport: + return ir_analyze_instruction_import(ira, (IrInstSrcImport *)instruction); + case IrInstSrcIdRef: + return ir_analyze_instruction_ref(ira, (IrInstSrcRef *)instruction); + case IrInstSrcIdContainerInitList: + return ir_analyze_instruction_container_init_list(ira, (IrInstSrcContainerInitList *)instruction); + case IrInstSrcIdContainerInitFields: + return ir_analyze_instruction_container_init_fields(ira, (IrInstSrcContainerInitFields *)instruction); + case IrInstSrcIdCompileErr: + return ir_analyze_instruction_compile_err(ira, (IrInstSrcCompileErr *)instruction); + case IrInstSrcIdCompileLog: + return ir_analyze_instruction_compile_log(ira, (IrInstSrcCompileLog *)instruction); + case IrInstSrcIdErrName: + return ir_analyze_instruction_err_name(ira, (IrInstSrcErrName *)instruction); + case IrInstSrcIdTypeName: + return ir_analyze_instruction_type_name(ira, (IrInstSrcTypeName *)instruction); + case IrInstSrcIdCImport: + return ir_analyze_instruction_c_import(ira, (IrInstSrcCImport *)instruction); + case IrInstSrcIdCInclude: + return ir_analyze_instruction_c_include(ira, (IrInstSrcCInclude *)instruction); + case IrInstSrcIdCDefine: + return ir_analyze_instruction_c_define(ira, (IrInstSrcCDefine *)instruction); + case IrInstSrcIdCUndef: + return ir_analyze_instruction_c_undef(ira, (IrInstSrcCUndef *)instruction); + case IrInstSrcIdEmbedFile: + return ir_analyze_instruction_embed_file(ira, (IrInstSrcEmbedFile *)instruction); + case IrInstSrcIdCmpxchg: + return ir_analyze_instruction_cmpxchg(ira, (IrInstSrcCmpxchg *)instruction); + case IrInstSrcIdFence: + return ir_analyze_instruction_fence(ira, (IrInstSrcFence *)instruction); + case IrInstSrcIdTruncate: + return ir_analyze_instruction_truncate(ira, (IrInstSrcTruncate *)instruction); + case IrInstSrcIdIntCast: + return ir_analyze_instruction_int_cast(ira, (IrInstSrcIntCast *)instruction); + case IrInstSrcIdFloatCast: + return ir_analyze_instruction_float_cast(ira, (IrInstSrcFloatCast *)instruction); + case IrInstSrcIdErrSetCast: + return ir_analyze_instruction_err_set_cast(ira, (IrInstSrcErrSetCast *)instruction); + case IrInstSrcIdFromBytes: + return ir_analyze_instruction_from_bytes(ira, (IrInstSrcFromBytes *)instruction); + case IrInstSrcIdToBytes: + return ir_analyze_instruction_to_bytes(ira, (IrInstSrcToBytes *)instruction); + case IrInstSrcIdIntToFloat: + return ir_analyze_instruction_int_to_float(ira, (IrInstSrcIntToFloat *)instruction); + case IrInstSrcIdFloatToInt: + return ir_analyze_instruction_float_to_int(ira, (IrInstSrcFloatToInt *)instruction); + case IrInstSrcIdBoolToInt: + return ir_analyze_instruction_bool_to_int(ira, (IrInstSrcBoolToInt *)instruction); + case IrInstSrcIdIntType: + return ir_analyze_instruction_int_type(ira, (IrInstSrcIntType *)instruction); + case IrInstSrcIdVectorType: + return ir_analyze_instruction_vector_type(ira, (IrInstSrcVectorType *)instruction); + case IrInstSrcIdShuffleVector: + return ir_analyze_instruction_shuffle_vector(ira, (IrInstSrcShuffleVector *)instruction); + case IrInstSrcIdSplat: + return ir_analyze_instruction_splat(ira, (IrInstSrcSplat *)instruction); + case IrInstSrcIdBoolNot: + return ir_analyze_instruction_bool_not(ira, (IrInstSrcBoolNot *)instruction); + case IrInstSrcIdMemset: + return ir_analyze_instruction_memset(ira, (IrInstSrcMemset *)instruction); + case IrInstSrcIdMemcpy: + return ir_analyze_instruction_memcpy(ira, (IrInstSrcMemcpy *)instruction); + case IrInstSrcIdSlice: + return ir_analyze_instruction_slice(ira, (IrInstSrcSlice *)instruction); + case IrInstSrcIdMemberCount: + return ir_analyze_instruction_member_count(ira, (IrInstSrcMemberCount *)instruction); + case IrInstSrcIdMemberType: + return ir_analyze_instruction_member_type(ira, (IrInstSrcMemberType *)instruction); + case IrInstSrcIdMemberName: + return ir_analyze_instruction_member_name(ira, (IrInstSrcMemberName *)instruction); + case IrInstSrcIdBreakpoint: + return ir_analyze_instruction_breakpoint(ira, (IrInstSrcBreakpoint *)instruction); + case IrInstSrcIdReturnAddress: + return ir_analyze_instruction_return_address(ira, (IrInstSrcReturnAddress *)instruction); + case IrInstSrcIdFrameAddress: + return ir_analyze_instruction_frame_address(ira, (IrInstSrcFrameAddress *)instruction); + case IrInstSrcIdFrameHandle: + return ir_analyze_instruction_frame_handle(ira, (IrInstSrcFrameHandle *)instruction); + case IrInstSrcIdFrameType: + return ir_analyze_instruction_frame_type(ira, (IrInstSrcFrameType *)instruction); + case IrInstSrcIdFrameSize: + return ir_analyze_instruction_frame_size(ira, (IrInstSrcFrameSize *)instruction); + case IrInstSrcIdAlignOf: + return ir_analyze_instruction_align_of(ira, (IrInstSrcAlignOf *)instruction); + case IrInstSrcIdOverflowOp: + return ir_analyze_instruction_overflow_op(ira, (IrInstSrcOverflowOp *)instruction); + case IrInstSrcIdTestErr: + return ir_analyze_instruction_test_err(ira, (IrInstSrcTestErr *)instruction); + case IrInstSrcIdUnwrapErrCode: + return ir_analyze_instruction_unwrap_err_code(ira, (IrInstSrcUnwrapErrCode *)instruction); + case IrInstSrcIdUnwrapErrPayload: + return ir_analyze_instruction_unwrap_err_payload(ira, (IrInstSrcUnwrapErrPayload *)instruction); + case IrInstSrcIdFnProto: + return ir_analyze_instruction_fn_proto(ira, (IrInstSrcFnProto *)instruction); + case IrInstSrcIdTestComptime: + return ir_analyze_instruction_test_comptime(ira, (IrInstSrcTestComptime *)instruction); + case IrInstSrcIdCheckSwitchProngs: + return ir_analyze_instruction_check_switch_prongs(ira, (IrInstSrcCheckSwitchProngs *)instruction); + case IrInstSrcIdCheckStatementIsVoid: + return ir_analyze_instruction_check_statement_is_void(ira, (IrInstSrcCheckStatementIsVoid *)instruction); + case IrInstSrcIdDeclRef: + return ir_analyze_instruction_decl_ref(ira, (IrInstSrcDeclRef *)instruction); + case IrInstSrcIdPanic: + return ir_analyze_instruction_panic(ira, (IrInstSrcPanic *)instruction); + case IrInstSrcIdPtrCast: + return ir_analyze_instruction_ptr_cast(ira, (IrInstSrcPtrCast *)instruction); + case IrInstSrcIdIntToPtr: + return ir_analyze_instruction_int_to_ptr(ira, (IrInstSrcIntToPtr *)instruction); + case IrInstSrcIdPtrToInt: + return ir_analyze_instruction_ptr_to_int(ira, (IrInstSrcPtrToInt *)instruction); + case IrInstSrcIdTagName: + return ir_analyze_instruction_enum_tag_name(ira, (IrInstSrcTagName *)instruction); + case IrInstSrcIdFieldParentPtr: + return ir_analyze_instruction_field_parent_ptr(ira, (IrInstSrcFieldParentPtr *)instruction); + case IrInstSrcIdByteOffsetOf: + return ir_analyze_instruction_byte_offset_of(ira, (IrInstSrcByteOffsetOf *)instruction); + case IrInstSrcIdBitOffsetOf: + return ir_analyze_instruction_bit_offset_of(ira, (IrInstSrcBitOffsetOf *)instruction); + case IrInstSrcIdTypeInfo: + return ir_analyze_instruction_type_info(ira, (IrInstSrcTypeInfo *) instruction); + case IrInstSrcIdType: + return ir_analyze_instruction_type(ira, (IrInstSrcType *)instruction); + case IrInstSrcIdHasField: + return ir_analyze_instruction_has_field(ira, (IrInstSrcHasField *) instruction); + case IrInstSrcIdTypeId: + return ir_analyze_instruction_type_id(ira, (IrInstSrcTypeId *)instruction); + case IrInstSrcIdSetEvalBranchQuota: + return ir_analyze_instruction_set_eval_branch_quota(ira, (IrInstSrcSetEvalBranchQuota *)instruction); + case IrInstSrcIdPtrType: + return ir_analyze_instruction_ptr_type(ira, (IrInstSrcPtrType *)instruction); + case IrInstSrcIdAlignCast: + return ir_analyze_instruction_align_cast(ira, (IrInstSrcAlignCast *)instruction); + case IrInstSrcIdImplicitCast: + return ir_analyze_instruction_implicit_cast(ira, (IrInstSrcImplicitCast *)instruction); + case IrInstSrcIdResolveResult: + return ir_analyze_instruction_resolve_result(ira, (IrInstSrcResolveResult *)instruction); + case IrInstSrcIdResetResult: + return ir_analyze_instruction_reset_result(ira, (IrInstSrcResetResult *)instruction); + case IrInstSrcIdOpaqueType: + return ir_analyze_instruction_opaque_type(ira, (IrInstSrcOpaqueType *)instruction); + case IrInstSrcIdSetAlignStack: + return ir_analyze_instruction_set_align_stack(ira, (IrInstSrcSetAlignStack *)instruction); + case IrInstSrcIdArgType: + return ir_analyze_instruction_arg_type(ira, (IrInstSrcArgType *)instruction); + case IrInstSrcIdTagType: + return ir_analyze_instruction_tag_type(ira, (IrInstSrcTagType *)instruction); + case IrInstSrcIdExport: + return ir_analyze_instruction_export(ira, (IrInstSrcExport *)instruction); + case IrInstSrcIdErrorReturnTrace: + return ir_analyze_instruction_error_return_trace(ira, (IrInstSrcErrorReturnTrace *)instruction); + case IrInstSrcIdErrorUnion: + return ir_analyze_instruction_error_union(ira, (IrInstSrcErrorUnion *)instruction); + case IrInstSrcIdAtomicRmw: + return ir_analyze_instruction_atomic_rmw(ira, (IrInstSrcAtomicRmw *)instruction); + case IrInstSrcIdAtomicLoad: + return ir_analyze_instruction_atomic_load(ira, (IrInstSrcAtomicLoad *)instruction); + case IrInstSrcIdAtomicStore: + return ir_analyze_instruction_atomic_store(ira, (IrInstSrcAtomicStore *)instruction); + case IrInstSrcIdSaveErrRetAddr: + return ir_analyze_instruction_save_err_ret_addr(ira, (IrInstSrcSaveErrRetAddr *)instruction); + case IrInstSrcIdAddImplicitReturnType: + return ir_analyze_instruction_add_implicit_return_type(ira, (IrInstSrcAddImplicitReturnType *)instruction); + case IrInstSrcIdFloatOp: + return ir_analyze_instruction_float_op(ira, (IrInstSrcFloatOp *)instruction); + case IrInstSrcIdMulAdd: + return ir_analyze_instruction_mul_add(ira, (IrInstSrcMulAdd *)instruction); + case IrInstSrcIdIntToErr: + return ir_analyze_instruction_int_to_err(ira, (IrInstSrcIntToErr *)instruction); + case IrInstSrcIdErrToInt: + return ir_analyze_instruction_err_to_int(ira, (IrInstSrcErrToInt *)instruction); + case IrInstSrcIdIntToEnum: + return ir_analyze_instruction_int_to_enum(ira, (IrInstSrcIntToEnum *)instruction); + case IrInstSrcIdEnumToInt: + return ir_analyze_instruction_enum_to_int(ira, (IrInstSrcEnumToInt *)instruction); + case IrInstSrcIdCheckRuntimeScope: + return ir_analyze_instruction_check_runtime_scope(ira, (IrInstSrcCheckRuntimeScope *)instruction); + case IrInstSrcIdHasDecl: + return ir_analyze_instruction_has_decl(ira, (IrInstSrcHasDecl *)instruction); + case IrInstSrcIdUndeclaredIdent: + return ir_analyze_instruction_undeclared_ident(ira, (IrInstSrcUndeclaredIdent *)instruction); + case IrInstSrcIdAlloca: return nullptr; - case IrInstructionIdEndExpr: - return ir_analyze_instruction_end_expr(ira, (IrInstructionEndExpr *)instruction); - case IrInstructionIdBitCastSrc: - return ir_analyze_instruction_bit_cast_src(ira, (IrInstructionBitCastSrc *)instruction); - case IrInstructionIdUnionInitNamedField: - return ir_analyze_instruction_union_init_named_field(ira, (IrInstructionUnionInitNamedField *)instruction); - case IrInstructionIdSuspendBegin: - return ir_analyze_instruction_suspend_begin(ira, (IrInstructionSuspendBegin *)instruction); - case IrInstructionIdSuspendFinish: - return ir_analyze_instruction_suspend_finish(ira, (IrInstructionSuspendFinish *)instruction); - case IrInstructionIdResume: - return ir_analyze_instruction_resume(ira, (IrInstructionResume *)instruction); - case IrInstructionIdAwaitSrc: - return ir_analyze_instruction_await(ira, (IrInstructionAwaitSrc *)instruction); - case IrInstructionIdSpillBegin: - return ir_analyze_instruction_spill_begin(ira, (IrInstructionSpillBegin *)instruction); - case IrInstructionIdSpillEnd: - return ir_analyze_instruction_spill_end(ira, (IrInstructionSpillEnd *)instruction); + case IrInstSrcIdEndExpr: + return ir_analyze_instruction_end_expr(ira, (IrInstSrcEndExpr *)instruction); + case IrInstSrcIdBitCast: + return ir_analyze_instruction_bit_cast_src(ira, (IrInstSrcBitCast *)instruction); + case IrInstSrcIdUnionInitNamedField: + return ir_analyze_instruction_union_init_named_field(ira, (IrInstSrcUnionInitNamedField *)instruction); + case IrInstSrcIdSuspendBegin: + return ir_analyze_instruction_suspend_begin(ira, (IrInstSrcSuspendBegin *)instruction); + case IrInstSrcIdSuspendFinish: + return ir_analyze_instruction_suspend_finish(ira, (IrInstSrcSuspendFinish *)instruction); + case IrInstSrcIdResume: + return ir_analyze_instruction_resume(ira, (IrInstSrcResume *)instruction); + case IrInstSrcIdAwait: + return ir_analyze_instruction_await(ira, (IrInstSrcAwait *)instruction); + case IrInstSrcIdSpillBegin: + return ir_analyze_instruction_spill_begin(ira, (IrInstSrcSpillBegin *)instruction); + case IrInstSrcIdSpillEnd: + return ir_analyze_instruction_spill_end(ira, (IrInstSrcSpillEnd *)instruction); } zig_unreachable(); } // This function attempts to evaluate IR code while doing type checking and other analysis. -// It emits a new IrExecutable which is partially evaluated IR code. -ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_exec, +// It emits to a new IrExecutableGen which is partially evaluated IR code. +ZigType *ir_analyze(CodeGen *codegen, IrExecutableSrc *old_exec, IrExecutableGen *new_exec, ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *result_ptr) { assert(old_exec->first_err_trace_msg == nullptr); @@ -28923,9 +29768,9 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_ ira->new_irb.codegen = codegen; ira->new_irb.exec = new_exec; - IrBasicBlock *old_entry_bb = ira->old_irb.exec->basic_block_list.at(0); - IrBasicBlock *new_entry_bb = ir_get_new_bb(ira, old_entry_bb, nullptr); - ir_ref_bb(new_entry_bb); + IrBasicBlockSrc *old_entry_bb = ira->old_irb.exec->basic_block_list.at(0); + IrBasicBlockGen *new_entry_bb = ir_get_new_bb(ira, old_entry_bb, nullptr); + ir_ref_bb_gen(new_entry_bb); ira->new_irb.current_basic_block = new_entry_bb; ira->old_bb_index = 0; @@ -28933,7 +29778,7 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_ if (result_ptr != nullptr) { assert(result_ptr->type->id == ZigTypeIdPointer); - IrInstructionConst *const_inst = ir_create_instruction( + IrInstGenConst *const_inst = ir_create_inst_noval( &ira->new_irb, new_exec->begin_scope, new_exec->source_node); const_inst->base.value = result_ptr; ira->return_ptr = &const_inst->base; @@ -28945,9 +29790,9 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_ } while (ira->old_bb_index < ira->old_irb.exec->basic_block_list.length) { - IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); + IrInstSrc *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); - if (old_instruction->ref_count == 0 && !ir_has_side_effects(old_instruction)) { + if (old_instruction->base.ref_count == 0 && !ir_inst_src_has_side_effects(old_instruction)) { ira->instruction_index += 1; continue; } @@ -28956,14 +29801,14 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_ fprintf(stderr, "~ "); old_instruction->src(); fprintf(stderr, "~ "); - ir_print_instruction(codegen, stderr, old_instruction, 0, IrPassSrc); + ir_print_inst_src(codegen, stderr, old_instruction, 0); bool want_break = false; - if (ira->break_debug_id == old_instruction->debug_id) { + if (ira->break_debug_id == old_instruction->base.debug_id) { want_break = true; - } else if (old_instruction->source_node != nullptr) { + } else if (old_instruction->base.source_node != nullptr) { for (size_t i = 0; i < dbg_ir_breakpoints_count; i += 1) { - if (dbg_ir_breakpoints_buf[i].line == old_instruction->source_node->line + 1 && - buf_ends_with_str(old_instruction->source_node->owner->data.structure.root_struct->path, + if (dbg_ir_breakpoints_buf[i].line == old_instruction->base.source_node->line + 1 && + buf_ends_with_str(old_instruction->base.source_node->owner->data.structure.root_struct->path, dbg_ir_breakpoints_buf[i].src_file)) { want_break = true; @@ -28972,9 +29817,9 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_ } if (want_break) BREAKPOINT; } - IrInstruction *new_instruction = ir_analyze_instruction_base(ira, old_instruction); + IrInstGen *new_instruction = ir_analyze_instruction_base(ira, old_instruction); if (new_instruction != nullptr) { - ir_assert(new_instruction->value->type != nullptr || new_instruction->value->type != nullptr, old_instruction); + ir_assert(new_instruction->value->type != nullptr || new_instruction->value->type != nullptr, &old_instruction->base); old_instruction->child = new_instruction; if (type_is_invalid(new_instruction->value->type)) { @@ -28988,19 +29833,19 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_ new_exec->first_err_trace_msg = ira->codegen->trace_err; } if (new_exec->first_err_trace_msg != nullptr && - !old_instruction->source_node->already_traced_this_node) + !old_instruction->base.source_node->already_traced_this_node) { - old_instruction->source_node->already_traced_this_node = true; + old_instruction->base.source_node->already_traced_this_node = true; new_exec->first_err_trace_msg = add_error_note(ira->codegen, new_exec->first_err_trace_msg, - old_instruction->source_node, buf_create_from_str("referenced here")); + old_instruction->base.source_node, buf_create_from_str("referenced here")); } return ira->codegen->builtin_types.entry_invalid; } else if (ira->codegen->verbose_ir) { fprintf(stderr, "-> "); - if (instr_is_unreachable(new_instruction)) { + if (new_instruction->value->type->id == ZigTypeIdUnreachable) { fprintf(stderr, "(noreturn)\n"); } else { - ir_print_instruction(codegen, stderr, new_instruction, 0, IrPassGen); + ir_print_inst_gen(codegen, stderr, new_instruction, 0); } } @@ -29040,204 +29885,279 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_ return res_type; } -bool ir_has_side_effects(IrInstruction *instruction) { +bool ir_inst_gen_has_side_effects(IrInstGen *instruction) { switch (instruction->id) { - case IrInstructionIdInvalid: + case IrInstGenIdInvalid: zig_unreachable(); - case IrInstructionIdBr: - case IrInstructionIdCondBr: - case IrInstructionIdSwitchBr: - case IrInstructionIdDeclVarSrc: - case IrInstructionIdDeclVarGen: - case IrInstructionIdStorePtr: - case IrInstructionIdVectorStoreElem: - case IrInstructionIdCallExtra: - case IrInstructionIdCallSrc: - case IrInstructionIdCallSrcArgs: - case IrInstructionIdCallGen: - case IrInstructionIdReturn: - case IrInstructionIdUnreachable: - case IrInstructionIdSetCold: - case IrInstructionIdSetRuntimeSafety: - case IrInstructionIdSetFloatMode: - case IrInstructionIdImport: - case IrInstructionIdCompileErr: - case IrInstructionIdCompileLog: - case IrInstructionIdCImport: - case IrInstructionIdCInclude: - case IrInstructionIdCDefine: - case IrInstructionIdCUndef: - case IrInstructionIdFence: - case IrInstructionIdMemset: - case IrInstructionIdMemcpy: - case IrInstructionIdBreakpoint: - case IrInstructionIdOverflowOp: // TODO when we support multiple returns this can be side effect free - case IrInstructionIdCheckSwitchProngs: - case IrInstructionIdCheckStatementIsVoid: - case IrInstructionIdCheckRuntimeScope: - case IrInstructionIdPanic: - case IrInstructionIdSetEvalBranchQuota: - case IrInstructionIdPtrType: - case IrInstructionIdSetAlignStack: - case IrInstructionIdExport: - case IrInstructionIdSaveErrRetAddr: - case IrInstructionIdAddImplicitReturnType: - case IrInstructionIdAtomicRmw: - case IrInstructionIdAtomicStore: - case IrInstructionIdCmpxchgGen: - case IrInstructionIdCmpxchgSrc: - case IrInstructionIdAssertZero: - case IrInstructionIdAssertNonNull: - case IrInstructionIdResizeSlice: - case IrInstructionIdUndeclaredIdent: - case IrInstructionIdEndExpr: - case IrInstructionIdPtrOfArrayToSlice: - case IrInstructionIdSliceGen: - case IrInstructionIdOptionalWrap: - case IrInstructionIdVectorToArray: - case IrInstructionIdResetResult: - case IrInstructionIdSuspendBegin: - case IrInstructionIdSuspendFinish: - case IrInstructionIdResume: - case IrInstructionIdAwaitSrc: - case IrInstructionIdAwaitGen: - case IrInstructionIdSpillBegin: + case IrInstGenIdBr: + case IrInstGenIdCondBr: + case IrInstGenIdSwitchBr: + case IrInstGenIdDeclVar: + case IrInstGenIdStorePtr: + case IrInstGenIdVectorStoreElem: + case IrInstGenIdCall: + case IrInstGenIdReturn: + case IrInstGenIdUnreachable: + case IrInstGenIdFence: + case IrInstGenIdMemset: + case IrInstGenIdMemcpy: + case IrInstGenIdBreakpoint: + case IrInstGenIdOverflowOp: // TODO when we support multiple returns this can be side effect free + case IrInstGenIdPanic: + case IrInstGenIdSaveErrRetAddr: + case IrInstGenIdAtomicRmw: + case IrInstGenIdAtomicStore: + case IrInstGenIdCmpxchg: + case IrInstGenIdAssertZero: + case IrInstGenIdAssertNonNull: + case IrInstGenIdResizeSlice: + case IrInstGenIdPtrOfArrayToSlice: + case IrInstGenIdSlice: + case IrInstGenIdOptionalWrap: + case IrInstGenIdVectorToArray: + case IrInstGenIdSuspendBegin: + case IrInstGenIdSuspendFinish: + case IrInstGenIdResume: + case IrInstGenIdAwait: + case IrInstGenIdSpillBegin: return true; - case IrInstructionIdPhi: - case IrInstructionIdUnOp: - case IrInstructionIdBinOp: - case IrInstructionIdMergeErrSets: - case IrInstructionIdLoadPtr: - case IrInstructionIdConst: - case IrInstructionIdCast: - case IrInstructionIdContainerInitList: - case IrInstructionIdContainerInitFields: - case IrInstructionIdUnionInitNamedField: - case IrInstructionIdFieldPtr: - case IrInstructionIdElemPtr: - case IrInstructionIdVarPtr: - case IrInstructionIdReturnPtr: - case IrInstructionIdTypeOf: - case IrInstructionIdStructFieldPtr: - case IrInstructionIdArrayType: - case IrInstructionIdSliceType: - case IrInstructionIdAnyFrameType: - case IrInstructionIdSizeOf: - case IrInstructionIdTestNonNull: - case IrInstructionIdOptionalUnwrapPtr: - case IrInstructionIdClz: - case IrInstructionIdCtz: - case IrInstructionIdPopCount: - case IrInstructionIdBswap: - case IrInstructionIdBitReverse: - case IrInstructionIdSwitchVar: - case IrInstructionIdSwitchElseVar: - case IrInstructionIdSwitchTarget: - case IrInstructionIdUnionTag: - case IrInstructionIdRef: - case IrInstructionIdEmbedFile: - case IrInstructionIdTruncate: - case IrInstructionIdIntType: - case IrInstructionIdVectorType: - case IrInstructionIdShuffleVector: - case IrInstructionIdSplatSrc: - case IrInstructionIdSplatGen: - case IrInstructionIdBoolNot: - case IrInstructionIdSliceSrc: - case IrInstructionIdMemberCount: - case IrInstructionIdMemberType: - case IrInstructionIdMemberName: - case IrInstructionIdAlignOf: - case IrInstructionIdReturnAddress: - case IrInstructionIdFrameAddress: - case IrInstructionIdFrameHandle: - case IrInstructionIdFrameType: - case IrInstructionIdFrameSizeSrc: - case IrInstructionIdFrameSizeGen: - case IrInstructionIdTestErrSrc: - case IrInstructionIdTestErrGen: - case IrInstructionIdFnProto: - case IrInstructionIdTestComptime: - case IrInstructionIdPtrCastSrc: - case IrInstructionIdPtrCastGen: - case IrInstructionIdBitCastSrc: - case IrInstructionIdBitCastGen: - case IrInstructionIdWidenOrShorten: - case IrInstructionIdPtrToInt: - case IrInstructionIdIntToPtr: - case IrInstructionIdIntToEnum: - case IrInstructionIdIntToErr: - case IrInstructionIdErrToInt: - case IrInstructionIdDeclRef: - case IrInstructionIdErrName: - case IrInstructionIdTypeName: - case IrInstructionIdTagName: - case IrInstructionIdFieldParentPtr: - case IrInstructionIdByteOffsetOf: - case IrInstructionIdBitOffsetOf: - case IrInstructionIdTypeInfo: - case IrInstructionIdType: - case IrInstructionIdHasField: - case IrInstructionIdTypeId: - case IrInstructionIdAlignCast: - case IrInstructionIdImplicitCast: - case IrInstructionIdResolveResult: - case IrInstructionIdOpaqueType: - case IrInstructionIdArgType: - case IrInstructionIdTagType: - case IrInstructionIdErrorReturnTrace: - case IrInstructionIdErrorUnion: - case IrInstructionIdFloatOp: - case IrInstructionIdMulAdd: - case IrInstructionIdAtomicLoad: - case IrInstructionIdIntCast: - case IrInstructionIdFloatCast: - case IrInstructionIdErrSetCast: - case IrInstructionIdIntToFloat: - case IrInstructionIdFloatToInt: - case IrInstructionIdBoolToInt: - case IrInstructionIdFromBytes: - case IrInstructionIdToBytes: - case IrInstructionIdEnumToInt: - case IrInstructionIdArrayToVector: - case IrInstructionIdHasDecl: - case IrInstructionIdAllocaSrc: - case IrInstructionIdAllocaGen: - case IrInstructionIdSpillEnd: - case IrInstructionIdVectorExtractElem: + case IrInstGenIdPhi: + case IrInstGenIdBinOp: + case IrInstGenIdConst: + case IrInstGenIdCast: + case IrInstGenIdElemPtr: + case IrInstGenIdVarPtr: + case IrInstGenIdReturnPtr: + case IrInstGenIdStructFieldPtr: + case IrInstGenIdTestNonNull: + case IrInstGenIdOptionalUnwrapPtr: + case IrInstGenIdClz: + case IrInstGenIdCtz: + case IrInstGenIdPopCount: + case IrInstGenIdBswap: + case IrInstGenIdBitReverse: + case IrInstGenIdUnionTag: + case IrInstGenIdTruncate: + case IrInstGenIdShuffleVector: + case IrInstGenIdSplat: + case IrInstGenIdBoolNot: + case IrInstGenIdReturnAddress: + case IrInstGenIdFrameAddress: + case IrInstGenIdFrameHandle: + case IrInstGenIdFrameSize: + case IrInstGenIdTestErr: + case IrInstGenIdPtrCast: + case IrInstGenIdBitCast: + case IrInstGenIdWidenOrShorten: + case IrInstGenIdPtrToInt: + case IrInstGenIdIntToPtr: + case IrInstGenIdIntToEnum: + case IrInstGenIdIntToErr: + case IrInstGenIdErrToInt: + case IrInstGenIdErrName: + case IrInstGenIdTagName: + case IrInstGenIdFieldParentPtr: + case IrInstGenIdAlignCast: + case IrInstGenIdErrorReturnTrace: + case IrInstGenIdFloatOp: + case IrInstGenIdMulAdd: + case IrInstGenIdAtomicLoad: + case IrInstGenIdArrayToVector: + case IrInstGenIdAlloca: + case IrInstGenIdSpillEnd: + case IrInstGenIdVectorExtractElem: + case IrInstGenIdBinaryNot: + case IrInstGenIdNegation: + case IrInstGenIdNegationWrapping: return false; - case IrInstructionIdAsmSrc: + case IrInstGenIdAsm: { - IrInstructionAsmSrc *asm_instruction = (IrInstructionAsmSrc *)instruction; + IrInstGenAsm *asm_instruction = (IrInstGenAsm *)instruction; return asm_instruction->has_side_effects; } - - case IrInstructionIdAsmGen: + case IrInstGenIdUnwrapErrPayload: { - IrInstructionAsmGen *asm_instruction = (IrInstructionAsmGen *)instruction; - return asm_instruction->has_side_effects; - } - case IrInstructionIdUnwrapErrPayload: - { - IrInstructionUnwrapErrPayload *unwrap_err_payload_instruction = - (IrInstructionUnwrapErrPayload *)instruction; + IrInstGenUnwrapErrPayload *unwrap_err_payload_instruction = + (IrInstGenUnwrapErrPayload *)instruction; return unwrap_err_payload_instruction->safety_check_on || unwrap_err_payload_instruction->initializing; } - case IrInstructionIdUnwrapErrCode: - return reinterpret_cast(instruction)->initializing; - case IrInstructionIdUnionFieldPtr: - return reinterpret_cast(instruction)->initializing; - case IrInstructionIdErrWrapPayload: - return reinterpret_cast(instruction)->result_loc != nullptr; - case IrInstructionIdErrWrapCode: - return reinterpret_cast(instruction)->result_loc != nullptr; - case IrInstructionIdLoadPtrGen: - return reinterpret_cast(instruction)->result_loc != nullptr; - case IrInstructionIdRefGen: - return reinterpret_cast(instruction)->result_loc != nullptr; + case IrInstGenIdUnwrapErrCode: + return reinterpret_cast(instruction)->initializing; + case IrInstGenIdUnionFieldPtr: + return reinterpret_cast(instruction)->initializing; + case IrInstGenIdErrWrapPayload: + return reinterpret_cast(instruction)->result_loc != nullptr; + case IrInstGenIdErrWrapCode: + return reinterpret_cast(instruction)->result_loc != nullptr; + case IrInstGenIdLoadPtr: + return reinterpret_cast(instruction)->result_loc != nullptr; + case IrInstGenIdRef: + return reinterpret_cast(instruction)->result_loc != nullptr; + } + zig_unreachable(); +} + +bool ir_inst_src_has_side_effects(IrInstSrc *instruction) { + switch (instruction->id) { + case IrInstSrcIdInvalid: + zig_unreachable(); + case IrInstSrcIdBr: + case IrInstSrcIdCondBr: + case IrInstSrcIdSwitchBr: + case IrInstSrcIdDeclVar: + case IrInstSrcIdStorePtr: + case IrInstSrcIdCallExtra: + case IrInstSrcIdCall: + case IrInstSrcIdCallArgs: + case IrInstSrcIdReturn: + case IrInstSrcIdUnreachable: + case IrInstSrcIdSetCold: + case IrInstSrcIdSetRuntimeSafety: + case IrInstSrcIdSetFloatMode: + case IrInstSrcIdImport: + case IrInstSrcIdCompileErr: + case IrInstSrcIdCompileLog: + case IrInstSrcIdCImport: + case IrInstSrcIdCInclude: + case IrInstSrcIdCDefine: + case IrInstSrcIdCUndef: + case IrInstSrcIdFence: + case IrInstSrcIdMemset: + case IrInstSrcIdMemcpy: + case IrInstSrcIdBreakpoint: + case IrInstSrcIdOverflowOp: // TODO when we support multiple returns this can be side effect free + case IrInstSrcIdCheckSwitchProngs: + case IrInstSrcIdCheckStatementIsVoid: + case IrInstSrcIdCheckRuntimeScope: + case IrInstSrcIdPanic: + case IrInstSrcIdSetEvalBranchQuota: + case IrInstSrcIdPtrType: + case IrInstSrcIdSetAlignStack: + case IrInstSrcIdExport: + case IrInstSrcIdSaveErrRetAddr: + case IrInstSrcIdAddImplicitReturnType: + case IrInstSrcIdAtomicRmw: + case IrInstSrcIdAtomicStore: + case IrInstSrcIdCmpxchg: + case IrInstSrcIdUndeclaredIdent: + case IrInstSrcIdEndExpr: + case IrInstSrcIdResetResult: + case IrInstSrcIdSuspendBegin: + case IrInstSrcIdSuspendFinish: + case IrInstSrcIdResume: + case IrInstSrcIdAwait: + case IrInstSrcIdSpillBegin: + return true; + + case IrInstSrcIdPhi: + case IrInstSrcIdUnOp: + case IrInstSrcIdBinOp: + case IrInstSrcIdMergeErrSets: + case IrInstSrcIdLoadPtr: + case IrInstSrcIdConst: + case IrInstSrcIdContainerInitList: + case IrInstSrcIdContainerInitFields: + case IrInstSrcIdUnionInitNamedField: + case IrInstSrcIdFieldPtr: + case IrInstSrcIdElemPtr: + case IrInstSrcIdVarPtr: + case IrInstSrcIdTypeOf: + case IrInstSrcIdArrayType: + case IrInstSrcIdSliceType: + case IrInstSrcIdAnyFrameType: + case IrInstSrcIdSizeOf: + case IrInstSrcIdTestNonNull: + case IrInstSrcIdOptionalUnwrapPtr: + case IrInstSrcIdClz: + case IrInstSrcIdCtz: + case IrInstSrcIdPopCount: + case IrInstSrcIdBswap: + case IrInstSrcIdBitReverse: + case IrInstSrcIdSwitchVar: + case IrInstSrcIdSwitchElseVar: + case IrInstSrcIdSwitchTarget: + case IrInstSrcIdRef: + case IrInstSrcIdEmbedFile: + case IrInstSrcIdTruncate: + case IrInstSrcIdIntType: + case IrInstSrcIdVectorType: + case IrInstSrcIdShuffleVector: + case IrInstSrcIdSplat: + case IrInstSrcIdBoolNot: + case IrInstSrcIdSlice: + case IrInstSrcIdMemberCount: + case IrInstSrcIdMemberType: + case IrInstSrcIdMemberName: + case IrInstSrcIdAlignOf: + case IrInstSrcIdReturnAddress: + case IrInstSrcIdFrameAddress: + case IrInstSrcIdFrameHandle: + case IrInstSrcIdFrameType: + case IrInstSrcIdFrameSize: + case IrInstSrcIdTestErr: + case IrInstSrcIdFnProto: + case IrInstSrcIdTestComptime: + case IrInstSrcIdPtrCast: + case IrInstSrcIdBitCast: + case IrInstSrcIdPtrToInt: + case IrInstSrcIdIntToPtr: + case IrInstSrcIdIntToEnum: + case IrInstSrcIdIntToErr: + case IrInstSrcIdErrToInt: + case IrInstSrcIdDeclRef: + case IrInstSrcIdErrName: + case IrInstSrcIdTypeName: + case IrInstSrcIdTagName: + case IrInstSrcIdFieldParentPtr: + case IrInstSrcIdByteOffsetOf: + case IrInstSrcIdBitOffsetOf: + case IrInstSrcIdTypeInfo: + case IrInstSrcIdType: + case IrInstSrcIdHasField: + case IrInstSrcIdTypeId: + case IrInstSrcIdAlignCast: + case IrInstSrcIdImplicitCast: + case IrInstSrcIdResolveResult: + case IrInstSrcIdOpaqueType: + case IrInstSrcIdArgType: + case IrInstSrcIdTagType: + case IrInstSrcIdErrorReturnTrace: + case IrInstSrcIdErrorUnion: + case IrInstSrcIdFloatOp: + case IrInstSrcIdMulAdd: + case IrInstSrcIdAtomicLoad: + case IrInstSrcIdIntCast: + case IrInstSrcIdFloatCast: + case IrInstSrcIdErrSetCast: + case IrInstSrcIdIntToFloat: + case IrInstSrcIdFloatToInt: + case IrInstSrcIdBoolToInt: + case IrInstSrcIdFromBytes: + case IrInstSrcIdToBytes: + case IrInstSrcIdEnumToInt: + case IrInstSrcIdHasDecl: + case IrInstSrcIdAlloca: + case IrInstSrcIdSpillEnd: + return false; + + case IrInstSrcIdAsm: + { + IrInstSrcAsm *asm_instruction = (IrInstSrcAsm *)instruction; + return asm_instruction->has_side_effects; + } + + case IrInstSrcIdUnwrapErrPayload: + { + IrInstSrcUnwrapErrPayload *unwrap_err_payload_instruction = + (IrInstSrcUnwrapErrPayload *)instruction; + return unwrap_err_payload_instruction->safety_check_on || + unwrap_err_payload_instruction->initializing; + } + case IrInstSrcIdUnwrapErrCode: + return reinterpret_cast(instruction)->initializing; } zig_unreachable(); } @@ -29271,14 +30191,14 @@ static ZigType *ir_resolve_lazy_fn_type(IrAnalyze *ira, AstNode *source_node, La param_info->type = nullptr; return get_generic_fn_type(ira->codegen, &fn_type_id); } else { - IrInstruction *param_type_inst = lazy_fn_type->param_types[fn_type_id.next_param_index]; + IrInstGen *param_type_inst = lazy_fn_type->param_types[fn_type_id.next_param_index]; ZigType *param_type = ir_resolve_type(ira, param_type_inst); if (type_is_invalid(param_type)) return nullptr; switch (type_requires_comptime(ira->codegen, param_type)) { case ReqCompTimeYes: if (!calling_convention_allows_zig_types(fn_type_id.cc)) { - ir_add_error(ira, param_type_inst, + ir_add_error(ira, ¶m_type_inst->base, buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'", buf_ptr(¶m_type->name), calling_convention_name(fn_type_id.cc))); return nullptr; @@ -29296,7 +30216,7 @@ static ZigType *ir_resolve_lazy_fn_type(IrAnalyze *ira, AstNode *source_node, La if ((err = type_has_bits2(ira->codegen, param_type, &has_bits))) return nullptr; if (!has_bits) { - ir_add_error(ira, param_type_inst, + ir_add_error(ira, ¶m_type_inst->base, buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'", buf_ptr(¶m_type->name), calling_convention_name(fn_type_id.cc))); return nullptr; @@ -29315,7 +30235,7 @@ static ZigType *ir_resolve_lazy_fn_type(IrAnalyze *ira, AstNode *source_node, La if (type_is_invalid(fn_type_id.return_type)) return nullptr; if (fn_type_id.return_type->id == ZigTypeIdOpaque) { - ir_add_error(ira, lazy_fn_type->return_type, buf_create_from_str("return type cannot be opaque")); + ir_add_error(ira, &lazy_fn_type->return_type->base, buf_create_from_str("return type cannot be opaque")); return nullptr; } @@ -29347,7 +30267,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { case ZigTypeIdBoundFn: case ZigTypeIdVoid: case ZigTypeIdOpaque: - ir_add_error(ira, lazy_align_of->target_type, + ir_add_error(ira, &lazy_align_of->target_type->base, buf_sprintf("no align available for type '%s'", buf_ptr(&lazy_align_of->target_type->value->data.x_type->name))); return ErrorSemanticAnalyzeFail; @@ -29397,7 +30317,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { case ZigTypeIdNull: case ZigTypeIdBoundFn: case ZigTypeIdOpaque: - ir_add_error(ira, lazy_size_of->target_type, + ir_add_error(ira, &lazy_size_of->target_type->base, buf_sprintf("no size available for type '%s'", buf_ptr(&lazy_size_of->target_type->value->data.x_type->name))); return ErrorSemanticAnalyzeFail; @@ -29455,7 +30375,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { if (lazy_slice_type->sentinel != nullptr) { if (type_is_invalid(lazy_slice_type->sentinel->value->type)) return ErrorSemanticAnalyzeFail; - IrInstruction *sentinel = ir_implicit_cast(ira, lazy_slice_type->sentinel, elem_type); + IrInstGen *sentinel = ir_implicit_cast(ira, lazy_slice_type->sentinel, elem_type); if (type_is_invalid(sentinel->value->type)) return ErrorSemanticAnalyzeFail; sentinel_val = ir_resolve_const(ira, sentinel, UndefBad); @@ -29478,7 +30398,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { case ZigTypeIdUndefined: case ZigTypeIdNull: case ZigTypeIdOpaque: - ir_add_error(ira, lazy_slice_type->elem_type, + ir_add_error(ira, &lazy_slice_type->elem_type->base, buf_sprintf("slice of type '%s' not allowed", buf_ptr(&elem_type->name))); return ErrorSemanticAnalyzeFail; case ZigTypeIdMetaType: @@ -29534,7 +30454,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { if (lazy_ptr_type->sentinel != nullptr) { if (type_is_invalid(lazy_ptr_type->sentinel->value->type)) return ErrorSemanticAnalyzeFail; - IrInstruction *sentinel = ir_implicit_cast(ira, lazy_ptr_type->sentinel, elem_type); + IrInstGen *sentinel = ir_implicit_cast(ira, lazy_ptr_type->sentinel, elem_type); if (type_is_invalid(sentinel->value->type)) return ErrorSemanticAnalyzeFail; sentinel_val = ir_resolve_const(ira, sentinel, UndefBad); @@ -29551,11 +30471,11 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { } if (elem_type->id == ZigTypeIdUnreachable) { - ir_add_error(ira, lazy_ptr_type->elem_type, + ir_add_error(ira, &lazy_ptr_type->elem_type->base, buf_create_from_str("pointer to noreturn not allowed")); return ErrorSemanticAnalyzeFail; } else if (elem_type->id == ZigTypeIdOpaque && lazy_ptr_type->ptr_len == PtrLenUnknown) { - ir_add_error(ira, lazy_ptr_type->elem_type, + ir_add_error(ira, &lazy_ptr_type->elem_type->base, buf_create_from_str("unknown-length pointer to opaque")); return ErrorSemanticAnalyzeFail; } else if (lazy_ptr_type->ptr_len == PtrLenC) { @@ -29563,16 +30483,16 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { if ((err = type_allowed_in_extern(ira->codegen, elem_type, &ok_type))) return err; if (!ok_type) { - ir_add_error(ira, lazy_ptr_type->elem_type, + ir_add_error(ira, &lazy_ptr_type->elem_type->base, buf_sprintf("C pointers cannot point to non-C-ABI-compatible type '%s'", buf_ptr(&elem_type->name))); return ErrorSemanticAnalyzeFail; } else if (elem_type->id == ZigTypeIdOpaque) { - ir_add_error(ira, lazy_ptr_type->elem_type, + ir_add_error(ira, &lazy_ptr_type->elem_type->base, buf_sprintf("C pointers cannot point opaque types")); return ErrorSemanticAnalyzeFail; } else if (lazy_ptr_type->is_allowzero) { - ir_add_error(ira, lazy_ptr_type->elem_type, + ir_add_error(ira, &lazy_ptr_type->elem_type->base, buf_sprintf("C pointers always allow address zero")); return ErrorSemanticAnalyzeFail; } @@ -29610,7 +30530,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { case ZigTypeIdUndefined: case ZigTypeIdNull: case ZigTypeIdOpaque: - ir_add_error(ira, lazy_array_type->elem_type, + ir_add_error(ira, &lazy_array_type->elem_type->base, buf_sprintf("array of type '%s' not allowed", buf_ptr(&elem_type->name))); return ErrorSemanticAnalyzeFail; @@ -29645,7 +30565,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { if (lazy_array_type->sentinel != nullptr) { if (type_is_invalid(lazy_array_type->sentinel->value->type)) return ErrorSemanticAnalyzeFail; - IrInstruction *sentinel = ir_implicit_cast(ira, lazy_array_type->sentinel, elem_type); + IrInstGen *sentinel = ir_implicit_cast(ira, lazy_array_type->sentinel, elem_type); if (type_is_invalid(sentinel->value->type)) return ErrorSemanticAnalyzeFail; sentinel_val = ir_resolve_const(ira, sentinel, UndefBad); @@ -29669,7 +30589,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { return ErrorSemanticAnalyzeFail; if (payload_type->id == ZigTypeIdOpaque || payload_type->id == ZigTypeIdUnreachable) { - ir_add_error(ira, lazy_opt_type->payload_type, + ir_add_error(ira, &lazy_opt_type->payload_type->base, buf_sprintf("type '%s' cannot be optional", buf_ptr(&payload_type->name))); return ErrorSemanticAnalyzeFail; } @@ -29711,7 +30631,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { return ErrorSemanticAnalyzeFail; if (err_set_type->id != ZigTypeIdErrorSet) { - ir_add_error(ira, lazy_err_union_type->err_set_type, + ir_add_error(ira, &lazy_err_union_type->err_set_type->base, buf_sprintf("expected error set type, found type '%s'", buf_ptr(&err_set_type->name))); return ErrorSemanticAnalyzeFail; @@ -29747,8 +30667,8 @@ Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ZigValue *val) { return ErrorNone; } -void IrInstruction::src() { - IrInstruction *inst = this; +void IrInst::src() { + IrInst *inst = this; if (inst->source_node != nullptr) { inst->source_node->src(); } else { @@ -29756,26 +30676,45 @@ void IrInstruction::src() { } } -void IrInstruction::dump() { - IrInstruction *inst = this; +void IrInst::dump() { + this->src(); + fprintf(stderr, "IrInst(#%" PRIu32 ")\n", this->debug_id); +} + +void IrInstSrc::src() { + this->base.src(); +} + +void IrInstGen::src() { + this->base.src(); +} + +void IrInstSrc::dump() { + IrInstSrc *inst = this; inst->src(); - IrPass pass = (inst->child == nullptr) ? IrPassGen : IrPassSrc; - if (inst->scope == nullptr) { + if (inst->base.scope == nullptr) { fprintf(stderr, "(null scope)\n"); } else { - ir_print_instruction(inst->scope->codegen, stderr, inst, 0, pass); - if (pass == IrPassSrc) { - fprintf(stderr, "-> "); - ir_print_instruction(inst->scope->codegen, stderr, inst->child, 0, IrPassGen); - } + ir_print_inst_src(inst->base.scope->codegen, stderr, inst, 0); + fprintf(stderr, "-> "); + ir_print_inst_gen(inst->base.scope->codegen, stderr, inst->child, 0); + } +} +void IrInstGen::dump() { + IrInstGen *inst = this; + inst->src(); + if (inst->base.scope == nullptr) { + fprintf(stderr, "(null scope)\n"); + } else { + ir_print_inst_gen(inst->base.scope->codegen, stderr, inst, 0); } } void IrAnalyze::dump() { - ir_print(this->codegen, stderr, this->new_irb.exec, 0, IrPassGen); + ir_print_gen(this->codegen, stderr, this->new_irb.exec, 0); if (this->new_irb.current_basic_block != nullptr) { fprintf(stderr, "Current basic block:\n"); - ir_print_basic_block(this->codegen, stderr, this->new_irb.current_basic_block, 1, IrPassGen); + ir_print_basic_block_gen(this->codegen, stderr, this->new_irb.current_basic_block, 1); } } diff --git a/src/ir.hpp b/src/ir.hpp index 4f9ed6bcdb..58aad6ad9b 100644 --- a/src/ir.hpp +++ b/src/ir.hpp @@ -10,33 +10,33 @@ #include "all_types.hpp" -enum IrPass { - IrPassSrc, - IrPassGen, -}; - -bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable); +bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutableSrc *ir_executable); bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry); +IrInstGen *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn, + ZigType *var_type, const char *name_hint); + Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ZigValue *return_ptr, size_t *backward_branch_count, size_t *backward_branch_quota, ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, - IrExecutable *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef); + IrExecutableGen *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef); Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ZigValue *val); -ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable, +ZigType *ir_analyze(CodeGen *g, IrExecutableSrc *old_executable, IrExecutableGen *new_executable, ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *return_ptr); -bool ir_has_side_effects(IrInstruction *instruction); +bool ir_inst_gen_has_side_effects(IrInstGen *inst); +bool ir_inst_src_has_side_effects(IrInstSrc *inst); struct IrAnalyze; ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_val, AstNode *source_node); -const char *float_op_to_name(BuiltinFnId op); // for debugging purposes void dbg_ir_break(const char *src_file, uint32_t line); void dbg_ir_clear(void); +void destroy_instruction_gen(IrInstGen *inst); + #endif diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 24e030f501..47c984f2ef 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -10,19 +10,35 @@ #include "ir_print.hpp" #include "os.hpp" -static uint32_t hash_instruction_ptr(IrInstruction* instruction) { +static uint32_t hash_inst_src_ptr(IrInstSrc* instruction) { return (uint32_t)(uintptr_t)instruction; } -static bool instruction_ptr_equal(IrInstruction* a, IrInstruction* b) { +static uint32_t hash_inst_gen_ptr(IrInstGen* instruction) { + return (uint32_t)(uintptr_t)instruction; +} + +static bool inst_src_ptr_eql(IrInstSrc* a, IrInstSrc* b) { return a == b; } -using InstructionSet = HashMap; -using InstructionList = ZigList; +static bool inst_gen_ptr_eql(IrInstGen* a, IrInstGen* b) { + return a == b; +} -struct IrPrint { - IrPass pass; +using InstSetSrc = HashMap; +using InstSetGen = HashMap; +using InstListSrc = ZigList; +using InstListGen = ZigList; + +struct IrPrintSrc { + CodeGen *codegen; + FILE *f; + int indent; + int indent_size; +}; + +struct IrPrintGen { CodeGen *codegen; FILE *f; int indent; @@ -32,417 +48,590 @@ struct IrPrint { // present in the instruction list. Thus we track which instructions // are printed (per executable) and after each pass 2 instruction those // var instructions are rendered in a trailing fashion. - InstructionSet printed; - InstructionList pending; + InstSetGen printed; + InstListGen pending; }; -static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction); +static void ir_print_other_inst_src(IrPrintSrc *irp, IrInstSrc *inst); +static void ir_print_other_inst_gen(IrPrintGen *irp, IrInstGen *inst); -const char* ir_instruction_type_str(IrInstructionId id) { +const char* ir_inst_src_type_str(IrInstSrcId id) { switch (id) { - case IrInstructionIdInvalid: - return "Invalid"; - case IrInstructionIdShuffleVector: - return "Shuffle"; - case IrInstructionIdSplatSrc: - return "SplatSrc"; - case IrInstructionIdSplatGen: - return "SplatGen"; - case IrInstructionIdDeclVarSrc: - return "DeclVarSrc"; - case IrInstructionIdDeclVarGen: - return "DeclVarGen"; - case IrInstructionIdBr: - return "Br"; - case IrInstructionIdCondBr: - return "CondBr"; - case IrInstructionIdSwitchBr: - return "SwitchBr"; - case IrInstructionIdSwitchVar: - return "SwitchVar"; - case IrInstructionIdSwitchElseVar: - return "SwitchElseVar"; - case IrInstructionIdSwitchTarget: - return "SwitchTarget"; - case IrInstructionIdPhi: - return "Phi"; - case IrInstructionIdUnOp: - return "UnOp"; - case IrInstructionIdBinOp: - return "BinOp"; - case IrInstructionIdMergeErrSets: - return "MergeErrSets"; - case IrInstructionIdLoadPtr: - return "LoadPtr"; - case IrInstructionIdLoadPtrGen: - return "LoadPtrGen"; - case IrInstructionIdStorePtr: - return "StorePtr"; - case IrInstructionIdVectorStoreElem: - return "VectorStoreElem"; - case IrInstructionIdFieldPtr: - return "FieldPtr"; - case IrInstructionIdStructFieldPtr: - return "StructFieldPtr"; - case IrInstructionIdUnionFieldPtr: - return "UnionFieldPtr"; - case IrInstructionIdElemPtr: - return "ElemPtr"; - case IrInstructionIdVarPtr: - return "VarPtr"; - case IrInstructionIdReturnPtr: - return "ReturnPtr"; - case IrInstructionIdCallExtra: - return "CallExtra"; - case IrInstructionIdCallSrc: - return "CallSrc"; - case IrInstructionIdCallSrcArgs: - return "CallSrcArgs"; - case IrInstructionIdCallGen: - return "CallGen"; - case IrInstructionIdConst: - return "Const"; - case IrInstructionIdReturn: - return "Return"; - case IrInstructionIdCast: - return "Cast"; - case IrInstructionIdResizeSlice: - return "ResizeSlice"; - case IrInstructionIdContainerInitList: - return "ContainerInitList"; - case IrInstructionIdContainerInitFields: - return "ContainerInitFields"; - case IrInstructionIdUnreachable: - return "Unreachable"; - case IrInstructionIdTypeOf: - return "TypeOf"; - case IrInstructionIdSetCold: - return "SetCold"; - case IrInstructionIdSetRuntimeSafety: - return "SetRuntimeSafety"; - case IrInstructionIdSetFloatMode: - return "SetFloatMode"; - case IrInstructionIdArrayType: - return "ArrayType"; - case IrInstructionIdAnyFrameType: - return "AnyFrameType"; - case IrInstructionIdSliceType: - return "SliceType"; - case IrInstructionIdAsmSrc: - return "AsmSrc"; - case IrInstructionIdAsmGen: - return "AsmGen"; - case IrInstructionIdSizeOf: - return "SizeOf"; - case IrInstructionIdTestNonNull: - return "TestNonNull"; - case IrInstructionIdOptionalUnwrapPtr: - return "OptionalUnwrapPtr"; - case IrInstructionIdOptionalWrap: - return "OptionalWrap"; - case IrInstructionIdUnionTag: - return "UnionTag"; - case IrInstructionIdClz: - return "Clz"; - case IrInstructionIdCtz: - return "Ctz"; - case IrInstructionIdPopCount: - return "PopCount"; - case IrInstructionIdBswap: - return "Bswap"; - case IrInstructionIdBitReverse: - return "BitReverse"; - case IrInstructionIdImport: - return "Import"; - case IrInstructionIdCImport: - return "CImport"; - case IrInstructionIdCInclude: - return "CInclude"; - case IrInstructionIdCDefine: - return "CDefine"; - case IrInstructionIdCUndef: - return "CUndef"; - case IrInstructionIdRef: - return "Ref"; - case IrInstructionIdRefGen: - return "RefGen"; - case IrInstructionIdCompileErr: - return "CompileErr"; - case IrInstructionIdCompileLog: - return "CompileLog"; - case IrInstructionIdErrName: - return "ErrName"; - case IrInstructionIdEmbedFile: - return "EmbedFile"; - case IrInstructionIdCmpxchgSrc: - return "CmpxchgSrc"; - case IrInstructionIdCmpxchgGen: - return "CmpxchgGen"; - case IrInstructionIdFence: - return "Fence"; - case IrInstructionIdTruncate: - return "Truncate"; - case IrInstructionIdIntCast: - return "IntCast"; - case IrInstructionIdFloatCast: - return "FloatCast"; - case IrInstructionIdIntToFloat: - return "IntToFloat"; - case IrInstructionIdFloatToInt: - return "FloatToInt"; - case IrInstructionIdBoolToInt: - return "BoolToInt"; - case IrInstructionIdIntType: - return "IntType"; - case IrInstructionIdVectorType: - return "VectorType"; - case IrInstructionIdBoolNot: - return "BoolNot"; - case IrInstructionIdMemset: - return "Memset"; - case IrInstructionIdMemcpy: - return "Memcpy"; - case IrInstructionIdSliceSrc: - return "SliceSrc"; - case IrInstructionIdSliceGen: - return "SliceGen"; - case IrInstructionIdMemberCount: - return "MemberCount"; - case IrInstructionIdMemberType: - return "MemberType"; - case IrInstructionIdMemberName: - return "MemberName"; - case IrInstructionIdBreakpoint: - return "Breakpoint"; - case IrInstructionIdReturnAddress: - return "ReturnAddress"; - case IrInstructionIdFrameAddress: - return "FrameAddress"; - case IrInstructionIdFrameHandle: - return "FrameHandle"; - case IrInstructionIdFrameType: - return "FrameType"; - case IrInstructionIdFrameSizeSrc: - return "FrameSizeSrc"; - case IrInstructionIdFrameSizeGen: - return "FrameSizeGen"; - case IrInstructionIdAlignOf: - return "AlignOf"; - case IrInstructionIdOverflowOp: - return "OverflowOp"; - case IrInstructionIdTestErrSrc: - return "TestErrSrc"; - case IrInstructionIdTestErrGen: - return "TestErrGen"; - case IrInstructionIdMulAdd: - return "MulAdd"; - case IrInstructionIdFloatOp: - return "FloatOp"; - case IrInstructionIdUnwrapErrCode: - return "UnwrapErrCode"; - case IrInstructionIdUnwrapErrPayload: - return "UnwrapErrPayload"; - case IrInstructionIdErrWrapCode: - return "ErrWrapCode"; - case IrInstructionIdErrWrapPayload: - return "ErrWrapPayload"; - case IrInstructionIdFnProto: - return "FnProto"; - case IrInstructionIdTestComptime: - return "TestComptime"; - case IrInstructionIdPtrCastSrc: - return "PtrCastSrc"; - case IrInstructionIdPtrCastGen: - return "PtrCastGen"; - case IrInstructionIdBitCastSrc: - return "BitCastSrc"; - case IrInstructionIdBitCastGen: - return "BitCastGen"; - case IrInstructionIdWidenOrShorten: - return "WidenOrShorten"; - case IrInstructionIdIntToPtr: - return "IntToPtr"; - case IrInstructionIdPtrToInt: - return "PtrToInt"; - case IrInstructionIdIntToEnum: - return "IntToEnum"; - case IrInstructionIdEnumToInt: - return "EnumToInt"; - case IrInstructionIdIntToErr: - return "IntToErr"; - case IrInstructionIdErrToInt: - return "ErrToInt"; - case IrInstructionIdCheckSwitchProngs: - return "CheckSwitchProngs"; - case IrInstructionIdCheckStatementIsVoid: - return "CheckStatementIsVoid"; - case IrInstructionIdTypeName: - return "TypeName"; - case IrInstructionIdDeclRef: - return "DeclRef"; - case IrInstructionIdPanic: - return "Panic"; - case IrInstructionIdTagName: - return "TagName"; - case IrInstructionIdTagType: - return "TagType"; - case IrInstructionIdFieldParentPtr: - return "FieldParentPtr"; - case IrInstructionIdByteOffsetOf: - return "ByteOffsetOf"; - case IrInstructionIdBitOffsetOf: - return "BitOffsetOf"; - case IrInstructionIdTypeInfo: - return "TypeInfo"; - case IrInstructionIdType: - return "Type"; - case IrInstructionIdHasField: - return "HasField"; - case IrInstructionIdTypeId: - return "TypeId"; - case IrInstructionIdSetEvalBranchQuota: - return "SetEvalBranchQuota"; - case IrInstructionIdPtrType: - return "PtrType"; - case IrInstructionIdAlignCast: - return "AlignCast"; - case IrInstructionIdImplicitCast: - return "ImplicitCast"; - case IrInstructionIdResolveResult: - return "ResolveResult"; - case IrInstructionIdResetResult: - return "ResetResult"; - case IrInstructionIdOpaqueType: - return "OpaqueType"; - case IrInstructionIdSetAlignStack: - return "SetAlignStack"; - case IrInstructionIdArgType: - return "ArgType"; - case IrInstructionIdExport: - return "Export"; - case IrInstructionIdErrorReturnTrace: - return "ErrorReturnTrace"; - case IrInstructionIdErrorUnion: - return "ErrorUnion"; - case IrInstructionIdAtomicRmw: - return "AtomicRmw"; - case IrInstructionIdAtomicLoad: - return "AtomicLoad"; - case IrInstructionIdAtomicStore: - return "AtomicStore"; - case IrInstructionIdSaveErrRetAddr: - return "SaveErrRetAddr"; - case IrInstructionIdAddImplicitReturnType: - return "AddImplicitReturnType"; - case IrInstructionIdErrSetCast: - return "ErrSetCast"; - case IrInstructionIdToBytes: - return "ToBytes"; - case IrInstructionIdFromBytes: - return "FromBytes"; - case IrInstructionIdCheckRuntimeScope: - return "CheckRuntimeScope"; - case IrInstructionIdVectorToArray: - return "VectorToArray"; - case IrInstructionIdArrayToVector: - return "ArrayToVector"; - case IrInstructionIdAssertZero: - return "AssertZero"; - case IrInstructionIdAssertNonNull: - return "AssertNonNull"; - case IrInstructionIdHasDecl: - return "HasDecl"; - case IrInstructionIdUndeclaredIdent: - return "UndeclaredIdent"; - case IrInstructionIdAllocaSrc: - return "AllocaSrc"; - case IrInstructionIdAllocaGen: - return "AllocaGen"; - case IrInstructionIdEndExpr: - return "EndExpr"; - case IrInstructionIdPtrOfArrayToSlice: - return "PtrOfArrayToSlice"; - case IrInstructionIdUnionInitNamedField: - return "UnionInitNamedField"; - case IrInstructionIdSuspendBegin: - return "SuspendBegin"; - case IrInstructionIdSuspendFinish: - return "SuspendFinish"; - case IrInstructionIdAwaitSrc: - return "AwaitSrc"; - case IrInstructionIdAwaitGen: - return "AwaitGen"; - case IrInstructionIdResume: - return "Resume"; - case IrInstructionIdSpillBegin: - return "SpillBegin"; - case IrInstructionIdSpillEnd: - return "SpillEnd"; - case IrInstructionIdVectorExtractElem: - return "VectorExtractElem"; + case IrInstSrcIdInvalid: + return "SrcInvalid"; + case IrInstSrcIdShuffleVector: + return "SrcShuffle"; + case IrInstSrcIdSplat: + return "SrcSplat"; + case IrInstSrcIdDeclVar: + return "SrcDeclVar"; + case IrInstSrcIdBr: + return "SrcBr"; + case IrInstSrcIdCondBr: + return "SrcCondBr"; + case IrInstSrcIdSwitchBr: + return "SrcSwitchBr"; + case IrInstSrcIdSwitchVar: + return "SrcSwitchVar"; + case IrInstSrcIdSwitchElseVar: + return "SrcSwitchElseVar"; + case IrInstSrcIdSwitchTarget: + return "SrcSwitchTarget"; + case IrInstSrcIdPhi: + return "SrcPhi"; + case IrInstSrcIdUnOp: + return "SrcUnOp"; + case IrInstSrcIdBinOp: + return "SrcBinOp"; + case IrInstSrcIdMergeErrSets: + return "SrcMergeErrSets"; + case IrInstSrcIdLoadPtr: + return "SrcLoadPtr"; + case IrInstSrcIdStorePtr: + return "SrcStorePtr"; + case IrInstSrcIdFieldPtr: + return "SrcFieldPtr"; + case IrInstSrcIdElemPtr: + return "SrcElemPtr"; + case IrInstSrcIdVarPtr: + return "SrcVarPtr"; + case IrInstSrcIdCallExtra: + return "SrcCallExtra"; + case IrInstSrcIdCall: + return "SrcCall"; + case IrInstSrcIdCallArgs: + return "SrcCallArgs"; + case IrInstSrcIdConst: + return "SrcConst"; + case IrInstSrcIdReturn: + return "SrcReturn"; + case IrInstSrcIdContainerInitList: + return "SrcContainerInitList"; + case IrInstSrcIdContainerInitFields: + return "SrcContainerInitFields"; + case IrInstSrcIdUnreachable: + return "SrcUnreachable"; + case IrInstSrcIdTypeOf: + return "SrcTypeOf"; + case IrInstSrcIdSetCold: + return "SrcSetCold"; + case IrInstSrcIdSetRuntimeSafety: + return "SrcSetRuntimeSafety"; + case IrInstSrcIdSetFloatMode: + return "SrcSetFloatMode"; + case IrInstSrcIdArrayType: + return "SrcArrayType"; + case IrInstSrcIdAnyFrameType: + return "SrcAnyFrameType"; + case IrInstSrcIdSliceType: + return "SrcSliceType"; + case IrInstSrcIdAsm: + return "SrcAsm"; + case IrInstSrcIdSizeOf: + return "SrcSizeOf"; + case IrInstSrcIdTestNonNull: + return "SrcTestNonNull"; + case IrInstSrcIdOptionalUnwrapPtr: + return "SrcOptionalUnwrapPtr"; + case IrInstSrcIdClz: + return "SrcClz"; + case IrInstSrcIdCtz: + return "SrcCtz"; + case IrInstSrcIdPopCount: + return "SrcPopCount"; + case IrInstSrcIdBswap: + return "SrcBswap"; + case IrInstSrcIdBitReverse: + return "SrcBitReverse"; + case IrInstSrcIdImport: + return "SrcImport"; + case IrInstSrcIdCImport: + return "SrcCImport"; + case IrInstSrcIdCInclude: + return "SrcCInclude"; + case IrInstSrcIdCDefine: + return "SrcCDefine"; + case IrInstSrcIdCUndef: + return "SrcCUndef"; + case IrInstSrcIdRef: + return "SrcRef"; + case IrInstSrcIdCompileErr: + return "SrcCompileErr"; + case IrInstSrcIdCompileLog: + return "SrcCompileLog"; + case IrInstSrcIdErrName: + return "SrcErrName"; + case IrInstSrcIdEmbedFile: + return "SrcEmbedFile"; + case IrInstSrcIdCmpxchg: + return "SrcCmpxchg"; + case IrInstSrcIdFence: + return "SrcFence"; + case IrInstSrcIdTruncate: + return "SrcTruncate"; + case IrInstSrcIdIntCast: + return "SrcIntCast"; + case IrInstSrcIdFloatCast: + return "SrcFloatCast"; + case IrInstSrcIdIntToFloat: + return "SrcIntToFloat"; + case IrInstSrcIdFloatToInt: + return "SrcFloatToInt"; + case IrInstSrcIdBoolToInt: + return "SrcBoolToInt"; + case IrInstSrcIdIntType: + return "SrcIntType"; + case IrInstSrcIdVectorType: + return "SrcVectorType"; + case IrInstSrcIdBoolNot: + return "SrcBoolNot"; + case IrInstSrcIdMemset: + return "SrcMemset"; + case IrInstSrcIdMemcpy: + return "SrcMemcpy"; + case IrInstSrcIdSlice: + return "SrcSlice"; + case IrInstSrcIdMemberCount: + return "SrcMemberCount"; + case IrInstSrcIdMemberType: + return "SrcMemberType"; + case IrInstSrcIdMemberName: + return "SrcMemberName"; + case IrInstSrcIdBreakpoint: + return "SrcBreakpoint"; + case IrInstSrcIdReturnAddress: + return "SrcReturnAddress"; + case IrInstSrcIdFrameAddress: + return "SrcFrameAddress"; + case IrInstSrcIdFrameHandle: + return "SrcFrameHandle"; + case IrInstSrcIdFrameType: + return "SrcFrameType"; + case IrInstSrcIdFrameSize: + return "SrcFrameSize"; + case IrInstSrcIdAlignOf: + return "SrcAlignOf"; + case IrInstSrcIdOverflowOp: + return "SrcOverflowOp"; + case IrInstSrcIdTestErr: + return "SrcTestErr"; + case IrInstSrcIdMulAdd: + return "SrcMulAdd"; + case IrInstSrcIdFloatOp: + return "SrcFloatOp"; + case IrInstSrcIdUnwrapErrCode: + return "SrcUnwrapErrCode"; + case IrInstSrcIdUnwrapErrPayload: + return "SrcUnwrapErrPayload"; + case IrInstSrcIdFnProto: + return "SrcFnProto"; + case IrInstSrcIdTestComptime: + return "SrcTestComptime"; + case IrInstSrcIdPtrCast: + return "SrcPtrCast"; + case IrInstSrcIdBitCast: + return "SrcBitCast"; + case IrInstSrcIdIntToPtr: + return "SrcIntToPtr"; + case IrInstSrcIdPtrToInt: + return "SrcPtrToInt"; + case IrInstSrcIdIntToEnum: + return "SrcIntToEnum"; + case IrInstSrcIdEnumToInt: + return "SrcEnumToInt"; + case IrInstSrcIdIntToErr: + return "SrcIntToErr"; + case IrInstSrcIdErrToInt: + return "SrcErrToInt"; + case IrInstSrcIdCheckSwitchProngs: + return "SrcCheckSwitchProngs"; + case IrInstSrcIdCheckStatementIsVoid: + return "SrcCheckStatementIsVoid"; + case IrInstSrcIdTypeName: + return "SrcTypeName"; + case IrInstSrcIdDeclRef: + return "SrcDeclRef"; + case IrInstSrcIdPanic: + return "SrcPanic"; + case IrInstSrcIdTagName: + return "SrcTagName"; + case IrInstSrcIdTagType: + return "SrcTagType"; + case IrInstSrcIdFieldParentPtr: + return "SrcFieldParentPtr"; + case IrInstSrcIdByteOffsetOf: + return "SrcByteOffsetOf"; + case IrInstSrcIdBitOffsetOf: + return "SrcBitOffsetOf"; + case IrInstSrcIdTypeInfo: + return "SrcTypeInfo"; + case IrInstSrcIdType: + return "SrcType"; + case IrInstSrcIdHasField: + return "SrcHasField"; + case IrInstSrcIdTypeId: + return "SrcTypeId"; + case IrInstSrcIdSetEvalBranchQuota: + return "SrcSetEvalBranchQuota"; + case IrInstSrcIdPtrType: + return "SrcPtrType"; + case IrInstSrcIdAlignCast: + return "SrcAlignCast"; + case IrInstSrcIdImplicitCast: + return "SrcImplicitCast"; + case IrInstSrcIdResolveResult: + return "SrcResolveResult"; + case IrInstSrcIdResetResult: + return "SrcResetResult"; + case IrInstSrcIdOpaqueType: + return "SrcOpaqueType"; + case IrInstSrcIdSetAlignStack: + return "SrcSetAlignStack"; + case IrInstSrcIdArgType: + return "SrcArgType"; + case IrInstSrcIdExport: + return "SrcExport"; + case IrInstSrcIdErrorReturnTrace: + return "SrcErrorReturnTrace"; + case IrInstSrcIdErrorUnion: + return "SrcErrorUnion"; + case IrInstSrcIdAtomicRmw: + return "SrcAtomicRmw"; + case IrInstSrcIdAtomicLoad: + return "SrcAtomicLoad"; + case IrInstSrcIdAtomicStore: + return "SrcAtomicStore"; + case IrInstSrcIdSaveErrRetAddr: + return "SrcSaveErrRetAddr"; + case IrInstSrcIdAddImplicitReturnType: + return "SrcAddImplicitReturnType"; + case IrInstSrcIdErrSetCast: + return "SrcErrSetCast"; + case IrInstSrcIdToBytes: + return "SrcToBytes"; + case IrInstSrcIdFromBytes: + return "SrcFromBytes"; + case IrInstSrcIdCheckRuntimeScope: + return "SrcCheckRuntimeScope"; + case IrInstSrcIdHasDecl: + return "SrcHasDecl"; + case IrInstSrcIdUndeclaredIdent: + return "SrcUndeclaredIdent"; + case IrInstSrcIdAlloca: + return "SrcAlloca"; + case IrInstSrcIdEndExpr: + return "SrcEndExpr"; + case IrInstSrcIdUnionInitNamedField: + return "SrcUnionInitNamedField"; + case IrInstSrcIdSuspendBegin: + return "SrcSuspendBegin"; + case IrInstSrcIdSuspendFinish: + return "SrcSuspendFinish"; + case IrInstSrcIdAwait: + return "SrcAwaitSr"; + case IrInstSrcIdResume: + return "SrcResume"; + case IrInstSrcIdSpillBegin: + return "SrcSpillBegin"; + case IrInstSrcIdSpillEnd: + return "SrcSpillEnd"; } zig_unreachable(); } -static void ir_print_indent(IrPrint *irp) { +const char* ir_inst_gen_type_str(IrInstGenId id) { + switch (id) { + case IrInstGenIdInvalid: + return "GenInvalid"; + case IrInstGenIdShuffleVector: + return "GenShuffle"; + case IrInstGenIdSplat: + return "GenSplat"; + case IrInstGenIdDeclVar: + return "GenDeclVar"; + case IrInstGenIdBr: + return "GenBr"; + case IrInstGenIdCondBr: + return "GenCondBr"; + case IrInstGenIdSwitchBr: + return "GenSwitchBr"; + case IrInstGenIdPhi: + return "GenPhi"; + case IrInstGenIdBinOp: + return "GenBinOp"; + case IrInstGenIdLoadPtr: + return "GenLoadPtr"; + case IrInstGenIdStorePtr: + return "GenStorePtr"; + case IrInstGenIdVectorStoreElem: + return "GenVectorStoreElem"; + case IrInstGenIdStructFieldPtr: + return "GenStructFieldPtr"; + case IrInstGenIdUnionFieldPtr: + return "GenUnionFieldPtr"; + case IrInstGenIdElemPtr: + return "GenElemPtr"; + case IrInstGenIdVarPtr: + return "GenVarPtr"; + case IrInstGenIdReturnPtr: + return "GenReturnPtr"; + case IrInstGenIdCall: + return "GenCall"; + case IrInstGenIdConst: + return "GenConst"; + case IrInstGenIdReturn: + return "GenReturn"; + case IrInstGenIdCast: + return "GenCast"; + case IrInstGenIdResizeSlice: + return "GenResizeSlice"; + case IrInstGenIdUnreachable: + return "GenUnreachable"; + case IrInstGenIdAsm: + return "GenAsm"; + case IrInstGenIdTestNonNull: + return "GenTestNonNull"; + case IrInstGenIdOptionalUnwrapPtr: + return "GenOptionalUnwrapPtr"; + case IrInstGenIdOptionalWrap: + return "GenOptionalWrap"; + case IrInstGenIdUnionTag: + return "GenUnionTag"; + case IrInstGenIdClz: + return "GenClz"; + case IrInstGenIdCtz: + return "GenCtz"; + case IrInstGenIdPopCount: + return "GenPopCount"; + case IrInstGenIdBswap: + return "GenBswap"; + case IrInstGenIdBitReverse: + return "GenBitReverse"; + case IrInstGenIdRef: + return "GenRef"; + case IrInstGenIdErrName: + return "GenErrName"; + case IrInstGenIdCmpxchg: + return "GenCmpxchg"; + case IrInstGenIdFence: + return "GenFence"; + case IrInstGenIdTruncate: + return "GenTruncate"; + case IrInstGenIdBoolNot: + return "GenBoolNot"; + case IrInstGenIdMemset: + return "GenMemset"; + case IrInstGenIdMemcpy: + return "GenMemcpy"; + case IrInstGenIdSlice: + return "GenSlice"; + case IrInstGenIdBreakpoint: + return "GenBreakpoint"; + case IrInstGenIdReturnAddress: + return "GenReturnAddress"; + case IrInstGenIdFrameAddress: + return "GenFrameAddress"; + case IrInstGenIdFrameHandle: + return "GenFrameHandle"; + case IrInstGenIdFrameSize: + return "GenFrameSize"; + case IrInstGenIdOverflowOp: + return "GenOverflowOp"; + case IrInstGenIdTestErr: + return "GenTestErr"; + case IrInstGenIdMulAdd: + return "GenMulAdd"; + case IrInstGenIdFloatOp: + return "GenFloatOp"; + case IrInstGenIdUnwrapErrCode: + return "GenUnwrapErrCode"; + case IrInstGenIdUnwrapErrPayload: + return "GenUnwrapErrPayload"; + case IrInstGenIdErrWrapCode: + return "GenErrWrapCode"; + case IrInstGenIdErrWrapPayload: + return "GenErrWrapPayload"; + case IrInstGenIdPtrCast: + return "GenPtrCast"; + case IrInstGenIdBitCast: + return "GenBitCast"; + case IrInstGenIdWidenOrShorten: + return "GenWidenOrShorten"; + case IrInstGenIdIntToPtr: + return "GenIntToPtr"; + case IrInstGenIdPtrToInt: + return "GenPtrToInt"; + case IrInstGenIdIntToEnum: + return "GenIntToEnum"; + case IrInstGenIdIntToErr: + return "GenIntToErr"; + case IrInstGenIdErrToInt: + return "GenErrToInt"; + case IrInstGenIdPanic: + return "GenPanic"; + case IrInstGenIdTagName: + return "GenTagName"; + case IrInstGenIdFieldParentPtr: + return "GenFieldParentPtr"; + case IrInstGenIdAlignCast: + return "GenAlignCast"; + case IrInstGenIdErrorReturnTrace: + return "GenErrorReturnTrace"; + case IrInstGenIdAtomicRmw: + return "GenAtomicRmw"; + case IrInstGenIdAtomicLoad: + return "GenAtomicLoad"; + case IrInstGenIdAtomicStore: + return "GenAtomicStore"; + case IrInstGenIdSaveErrRetAddr: + return "GenSaveErrRetAddr"; + case IrInstGenIdVectorToArray: + return "GenVectorToArray"; + case IrInstGenIdArrayToVector: + return "GenArrayToVector"; + case IrInstGenIdAssertZero: + return "GenAssertZero"; + case IrInstGenIdAssertNonNull: + return "GenAssertNonNull"; + case IrInstGenIdAlloca: + return "GenAlloca"; + case IrInstGenIdPtrOfArrayToSlice: + return "GenPtrOfArrayToSlice"; + case IrInstGenIdSuspendBegin: + return "GenSuspendBegin"; + case IrInstGenIdSuspendFinish: + return "GenSuspendFinish"; + case IrInstGenIdAwait: + return "GenAwait"; + case IrInstGenIdResume: + return "GenResume"; + case IrInstGenIdSpillBegin: + return "GenSpillBegin"; + case IrInstGenIdSpillEnd: + return "GenSpillEnd"; + case IrInstGenIdVectorExtractElem: + return "GenVectorExtractElem"; + case IrInstGenIdBinaryNot: + return "GenBinaryNot"; + case IrInstGenIdNegation: + return "GenNegation"; + case IrInstGenIdNegationWrapping: + return "GenNegationWrapping"; + } + zig_unreachable(); +} + +static void ir_print_indent_src(IrPrintSrc *irp) { for (int i = 0; i < irp->indent; i += 1) { fprintf(irp->f, " "); } } -static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction, bool trailing) { - ir_print_indent(irp); - const char mark = trailing ? ':' : '#'; - const char *type_name = instruction->value->type ? buf_ptr(&instruction->value->type->name) : "(unknown)"; - const char *ref_count = ir_has_side_effects(instruction) ? - "-" : buf_ptr(buf_sprintf("%" PRIu32 "", instruction->ref_count)); - fprintf(irp->f, "%c%-3" PRIu32 "| %-22s| %-12s| %-2s| ", mark, instruction->debug_id, - ir_instruction_type_str(instruction->id), type_name, ref_count); -} - -static void ir_print_const_value(IrPrint *irp, ZigValue *const_val) { - Buf buf = BUF_INIT; - buf_resize(&buf, 0); - render_const_value(irp->codegen, &buf, const_val); - fprintf(irp->f, "%s", buf_ptr(&buf)); -} - -static void ir_print_var_instruction(IrPrint *irp, IrInstruction *instruction) { - fprintf(irp->f, "#%" PRIu32 "", instruction->debug_id); - if (irp->pass != IrPassSrc && irp->printed.maybe_get(instruction) == nullptr) { - irp->printed.put(instruction, 0); - irp->pending.append(instruction); +static void ir_print_indent_gen(IrPrintGen *irp) { + for (int i = 0; i < irp->indent; i += 1) { + fprintf(irp->f, " "); } } -static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction) { - if (instruction == nullptr) { +static void ir_print_prefix_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trailing) { + ir_print_indent_src(irp); + const char mark = trailing ? ':' : '#'; + const char *type_name; + if (instruction->id == IrInstSrcIdConst) { + type_name = buf_ptr(&reinterpret_cast(instruction)->value->type->name); + } else if (instruction->is_noreturn) { + type_name = "noreturn"; + } else { + type_name = "(unknown)"; + } + const char *ref_count = ir_inst_src_has_side_effects(instruction) ? + "-" : buf_ptr(buf_sprintf("%" PRIu32 "", instruction->base.ref_count)); + fprintf(irp->f, "%c%-3" PRIu32 "| %-22s| %-12s| %-2s| ", mark, instruction->base.debug_id, + ir_inst_src_type_str(instruction->id), type_name, ref_count); +} + +static void ir_print_prefix_gen(IrPrintGen *irp, IrInstGen *instruction, bool trailing) { + ir_print_indent_gen(irp); + const char mark = trailing ? ':' : '#'; + const char *type_name = instruction->value->type ? buf_ptr(&instruction->value->type->name) : "(unknown)"; + const char *ref_count = ir_inst_gen_has_side_effects(instruction) ? + "-" : buf_ptr(buf_sprintf("%" PRIu32 "", instruction->base.ref_count)); + fprintf(irp->f, "%c%-3" PRIu32 "| %-22s| %-12s| %-2s| ", mark, instruction->base.debug_id, + ir_inst_gen_type_str(instruction->id), type_name, ref_count); +} + +static void ir_print_var_src(IrPrintSrc *irp, IrInstSrc *inst) { + fprintf(irp->f, "#%" PRIu32 "", inst->base.debug_id); +} + +static void ir_print_var_gen(IrPrintGen *irp, IrInstGen *inst) { + fprintf(irp->f, "#%" PRIu32 "", inst->base.debug_id); + if (irp->printed.maybe_get(inst) == nullptr) { + irp->printed.put(inst, 0); + irp->pending.append(inst); + } +} + +static void ir_print_other_inst_src(IrPrintSrc *irp, IrInstSrc *inst) { + if (inst == nullptr) { + fprintf(irp->f, "(null)"); + return; + } + ir_print_var_src(irp, inst); +} + +static void ir_print_const_value(CodeGen *g, FILE *f, ZigValue *const_val) { + Buf buf = BUF_INIT; + buf_resize(&buf, 0); + render_const_value(g, &buf, const_val); + fprintf(f, "%s", buf_ptr(&buf)); +} + +static void ir_print_other_inst_gen(IrPrintGen *irp, IrInstGen *inst) { + if (inst == nullptr) { fprintf(irp->f, "(null)"); return; } - if (instruction->value->special != ConstValSpecialRuntime) { - ir_print_const_value(irp, instruction->value); + if (inst->value->special != ConstValSpecialRuntime) { + ir_print_const_value(irp->codegen, irp->f, inst->value); } else { - ir_print_var_instruction(irp, instruction); + ir_print_var_gen(irp, inst); } } -static void ir_print_other_block(IrPrint *irp, IrBasicBlock *bb) { +static void ir_print_other_block(IrPrintSrc *irp, IrBasicBlockSrc *bb) { if (bb == nullptr) { fprintf(irp->f, "(null block)"); } else { - fprintf(irp->f, "$%s_%" ZIG_PRI_usize "", bb->name_hint, bb->debug_id); + fprintf(irp->f, "$%s_%" PRIu32 "", bb->name_hint, bb->debug_id); } } -static void ir_print_return(IrPrint *irp, IrInstructionReturn *instruction) { - fprintf(irp->f, "return "); - ir_print_other_instruction(irp, instruction->operand); +static void ir_print_other_block_gen(IrPrintGen *irp, IrBasicBlockGen *bb) { + if (bb == nullptr) { + fprintf(irp->f, "(null block)"); + } else { + fprintf(irp->f, "$%s_%" PRIu32 "", bb->name_hint, bb->debug_id); + } } -static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) { - ir_print_const_value(irp, const_instruction->base.value); +static void ir_print_return_src(IrPrintSrc *irp, IrInstSrcReturn *inst) { + fprintf(irp->f, "return "); + ir_print_other_inst_src(irp, inst->operand); +} + +static void ir_print_return_gen(IrPrintGen *irp, IrInstGenReturn *inst) { + fprintf(irp->f, "return "); + ir_print_other_inst_gen(irp, inst->operand); +} + +static void ir_print_const(IrPrintSrc *irp, IrInstSrcConst *const_instruction) { + ir_print_const_value(irp->codegen, irp->f, const_instruction->value); +} + +static void ir_print_const(IrPrintGen *irp, IrInstGenConst *const_instruction) { + ir_print_const_value(irp->codegen, irp->f, const_instruction->base.value); } static const char *ir_bin_op_id_str(IrBinOp op_id) { @@ -531,89 +720,111 @@ static const char *ir_un_op_id_str(IrUnOp op_id) { zig_unreachable(); } -static void ir_print_un_op(IrPrint *irp, IrInstructionUnOp *un_op_instruction) { - fprintf(irp->f, "%s ", ir_un_op_id_str(un_op_instruction->op_id)); - ir_print_other_instruction(irp, un_op_instruction->value); +static void ir_print_un_op(IrPrintSrc *irp, IrInstSrcUnOp *inst) { + fprintf(irp->f, "%s ", ir_un_op_id_str(inst->op_id)); + ir_print_other_inst_src(irp, inst->value); } -static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction) { - ir_print_other_instruction(irp, bin_op_instruction->op1); +static void ir_print_bin_op(IrPrintSrc *irp, IrInstSrcBinOp *bin_op_instruction) { + ir_print_other_inst_src(irp, bin_op_instruction->op1); fprintf(irp->f, " %s ", ir_bin_op_id_str(bin_op_instruction->op_id)); - ir_print_other_instruction(irp, bin_op_instruction->op2); + ir_print_other_inst_src(irp, bin_op_instruction->op2); if (!bin_op_instruction->safety_check_on) { fprintf(irp->f, " // no safety"); } } -static void ir_print_merge_err_sets(IrPrint *irp, IrInstructionMergeErrSets *instruction) { - ir_print_other_instruction(irp, instruction->op1); +static void ir_print_bin_op(IrPrintGen *irp, IrInstGenBinOp *bin_op_instruction) { + ir_print_other_inst_gen(irp, bin_op_instruction->op1); + fprintf(irp->f, " %s ", ir_bin_op_id_str(bin_op_instruction->op_id)); + ir_print_other_inst_gen(irp, bin_op_instruction->op2); + if (!bin_op_instruction->safety_check_on) { + fprintf(irp->f, " // no safety"); + } +} + +static void ir_print_merge_err_sets(IrPrintSrc *irp, IrInstSrcMergeErrSets *instruction) { + ir_print_other_inst_src(irp, instruction->op1); fprintf(irp->f, " || "); - ir_print_other_instruction(irp, instruction->op2); + ir_print_other_inst_src(irp, instruction->op2); if (instruction->type_name != nullptr) { fprintf(irp->f, " // name=%s", buf_ptr(instruction->type_name)); } } -static void ir_print_decl_var_src(IrPrint *irp, IrInstructionDeclVarSrc *decl_var_instruction) { +static void ir_print_decl_var_src(IrPrintSrc *irp, IrInstSrcDeclVar *decl_var_instruction) { const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var"; const char *name = decl_var_instruction->var->name; if (decl_var_instruction->var_type) { fprintf(irp->f, "%s %s: ", var_or_const, name); - ir_print_other_instruction(irp, decl_var_instruction->var_type); + ir_print_other_inst_src(irp, decl_var_instruction->var_type); fprintf(irp->f, " "); } else { fprintf(irp->f, "%s %s ", var_or_const, name); } if (decl_var_instruction->align_value) { fprintf(irp->f, "align "); - ir_print_other_instruction(irp, decl_var_instruction->align_value); + ir_print_other_inst_src(irp, decl_var_instruction->align_value); fprintf(irp->f, " "); } fprintf(irp->f, "= "); - ir_print_other_instruction(irp, decl_var_instruction->ptr); + ir_print_other_inst_src(irp, decl_var_instruction->ptr); if (decl_var_instruction->var->is_comptime != nullptr) { fprintf(irp->f, " // comptime = "); - ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime); + ir_print_other_inst_src(irp, decl_var_instruction->var->is_comptime); } } -static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) { - fprintf(irp->f, "cast "); - ir_print_other_instruction(irp, cast_instruction->value); - fprintf(irp->f, " to %s", buf_ptr(&cast_instruction->dest_type->name)); +static const char *cast_op_str(CastOp op) { + switch (op) { + case CastOpNoCast: return "NoCast"; + case CastOpNoop: return "NoOp"; + case CastOpIntToFloat: return "IntToFloat"; + case CastOpFloatToInt: return "FloatToInt"; + case CastOpBoolToInt: return "BoolToInt"; + case CastOpNumLitToConcrete: return "NumLitToConcrate"; + case CastOpErrSet: return "ErrSet"; + case CastOpBitCast: return "BitCast"; + } + zig_unreachable(); } -static void ir_print_result_loc_var(IrPrint *irp, ResultLocVar *result_loc_var) { +static void ir_print_cast(IrPrintGen *irp, IrInstGenCast *cast_instruction) { + fprintf(irp->f, "%s cast ", cast_op_str(cast_instruction->cast_op)); + ir_print_other_inst_gen(irp, cast_instruction->value); +} + +static void ir_print_result_loc_var(IrPrintSrc *irp, ResultLocVar *result_loc_var) { fprintf(irp->f, "var("); - ir_print_other_instruction(irp, result_loc_var->base.source_instruction); + ir_print_other_inst_src(irp, result_loc_var->base.source_instruction); fprintf(irp->f, ")"); } -static void ir_print_result_loc_instruction(IrPrint *irp, ResultLocInstruction *result_loc_inst) { +static void ir_print_result_loc_instruction(IrPrintSrc *irp, ResultLocInstruction *result_loc_inst) { fprintf(irp->f, "inst("); - ir_print_other_instruction(irp, result_loc_inst->base.source_instruction); + ir_print_other_inst_src(irp, result_loc_inst->base.source_instruction); fprintf(irp->f, ")"); } -static void ir_print_result_loc_peer(IrPrint *irp, ResultLocPeer *result_loc_peer) { +static void ir_print_result_loc_peer(IrPrintSrc *irp, ResultLocPeer *result_loc_peer) { fprintf(irp->f, "peer(next="); ir_print_other_block(irp, result_loc_peer->next_bb); fprintf(irp->f, ")"); } -static void ir_print_result_loc_bit_cast(IrPrint *irp, ResultLocBitCast *result_loc_bit_cast) { +static void ir_print_result_loc_bit_cast(IrPrintSrc *irp, ResultLocBitCast *result_loc_bit_cast) { fprintf(irp->f, "bitcast(ty="); - ir_print_other_instruction(irp, result_loc_bit_cast->base.source_instruction); + ir_print_other_inst_src(irp, result_loc_bit_cast->base.source_instruction); fprintf(irp->f, ")"); } -static void ir_print_result_loc_cast(IrPrint *irp, ResultLocCast *result_loc_cast) { +static void ir_print_result_loc_cast(IrPrintSrc *irp, ResultLocCast *result_loc_cast) { fprintf(irp->f, "cast(ty="); - ir_print_other_instruction(irp, result_loc_cast->base.source_instruction); + ir_print_other_inst_src(irp, result_loc_cast->base.source_instruction); fprintf(irp->f, ")"); } -static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) { +static void ir_print_result_loc(IrPrintSrc *irp, ResultLoc *result_loc) { switch (result_loc->id) { case ResultLocIdInvalid: zig_unreachable(); @@ -640,34 +851,34 @@ static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) { zig_unreachable(); } -static void ir_print_call_extra(IrPrint *irp, IrInstructionCallExtra *instruction) { +static void ir_print_call_extra(IrPrintSrc *irp, IrInstSrcCallExtra *instruction) { fprintf(irp->f, "opts="); - ir_print_other_instruction(irp, instruction->options); + ir_print_other_inst_src(irp, instruction->options); fprintf(irp->f, ", fn="); - ir_print_other_instruction(irp, instruction->fn_ref); + ir_print_other_inst_src(irp, instruction->fn_ref); fprintf(irp->f, ", args="); - ir_print_other_instruction(irp, instruction->args); + ir_print_other_inst_src(irp, instruction->args); fprintf(irp->f, ", result="); ir_print_result_loc(irp, instruction->result_loc); } -static void ir_print_call_src_args(IrPrint *irp, IrInstructionCallSrcArgs *instruction) { +static void ir_print_call_args(IrPrintSrc *irp, IrInstSrcCallArgs *instruction) { fprintf(irp->f, "opts="); - ir_print_other_instruction(irp, instruction->options); + ir_print_other_inst_src(irp, instruction->options); fprintf(irp->f, ", fn="); - ir_print_other_instruction(irp, instruction->fn_ref); + ir_print_other_inst_src(irp, instruction->fn_ref); fprintf(irp->f, ", args=("); for (size_t i = 0; i < instruction->args_len; i += 1) { - IrInstruction *arg = instruction->args_ptr[i]; + IrInstSrc *arg = instruction->args_ptr[i]; if (i != 0) fprintf(irp->f, ", "); - ir_print_other_instruction(irp, arg); + ir_print_other_inst_src(irp, arg); } fprintf(irp->f, "), result="); ir_print_result_loc(irp, instruction->result_loc); } -static void ir_print_call_src(IrPrint *irp, IrInstructionCallSrc *call_instruction) { +static void ir_print_call_src(IrPrintSrc *irp, IrInstSrcCall *call_instruction) { switch (call_instruction->modifier) { case CallModifierNone: break; @@ -699,20 +910,20 @@ static void ir_print_call_src(IrPrint *irp, IrInstructionCallSrc *call_instructi fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name)); } else { assert(call_instruction->fn_ref); - ir_print_other_instruction(irp, call_instruction->fn_ref); + ir_print_other_inst_src(irp, call_instruction->fn_ref); } fprintf(irp->f, "("); for (size_t i = 0; i < call_instruction->arg_count; i += 1) { - IrInstruction *arg = call_instruction->args[i]; + IrInstSrc *arg = call_instruction->args[i]; if (i != 0) fprintf(irp->f, ", "); - ir_print_other_instruction(irp, arg); + ir_print_other_inst_src(irp, arg); } fprintf(irp->f, ")result="); ir_print_result_loc(irp, call_instruction->result_loc); } -static void ir_print_call_gen(IrPrint *irp, IrInstructionCallGen *call_instruction) { +static void ir_print_call_gen(IrPrintGen *irp, IrInstGenCall *call_instruction) { switch (call_instruction->modifier) { case CallModifierNone: break; @@ -744,221 +955,291 @@ static void ir_print_call_gen(IrPrint *irp, IrInstructionCallGen *call_instructi fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name)); } else { assert(call_instruction->fn_ref); - ir_print_other_instruction(irp, call_instruction->fn_ref); + ir_print_other_inst_gen(irp, call_instruction->fn_ref); } fprintf(irp->f, "("); for (size_t i = 0; i < call_instruction->arg_count; i += 1) { - IrInstruction *arg = call_instruction->args[i]; + IrInstGen *arg = call_instruction->args[i]; if (i != 0) fprintf(irp->f, ", "); - ir_print_other_instruction(irp, arg); + ir_print_other_inst_gen(irp, arg); } fprintf(irp->f, ")result="); - ir_print_other_instruction(irp, call_instruction->result_loc); + ir_print_other_inst_gen(irp, call_instruction->result_loc); } -static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) { +static void ir_print_cond_br(IrPrintSrc *irp, IrInstSrcCondBr *inst) { fprintf(irp->f, "if ("); - ir_print_other_instruction(irp, cond_br_instruction->condition); + ir_print_other_inst_src(irp, inst->condition); fprintf(irp->f, ") "); - ir_print_other_block(irp, cond_br_instruction->then_block); + ir_print_other_block(irp, inst->then_block); fprintf(irp->f, " else "); - ir_print_other_block(irp, cond_br_instruction->else_block); - if (cond_br_instruction->is_comptime != nullptr) { + ir_print_other_block(irp, inst->else_block); + if (inst->is_comptime != nullptr) { fprintf(irp->f, " // comptime = "); - ir_print_other_instruction(irp, cond_br_instruction->is_comptime); + ir_print_other_inst_src(irp, inst->is_comptime); } } -static void ir_print_br(IrPrint *irp, IrInstructionBr *br_instruction) { +static void ir_print_cond_br(IrPrintGen *irp, IrInstGenCondBr *inst) { + fprintf(irp->f, "if ("); + ir_print_other_inst_gen(irp, inst->condition); + fprintf(irp->f, ") "); + ir_print_other_block_gen(irp, inst->then_block); + fprintf(irp->f, " else "); + ir_print_other_block_gen(irp, inst->else_block); +} + +static void ir_print_br(IrPrintSrc *irp, IrInstSrcBr *br_instruction) { fprintf(irp->f, "goto "); ir_print_other_block(irp, br_instruction->dest_block); if (br_instruction->is_comptime != nullptr) { fprintf(irp->f, " // comptime = "); - ir_print_other_instruction(irp, br_instruction->is_comptime); + ir_print_other_inst_src(irp, br_instruction->is_comptime); } } -static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) { +static void ir_print_br(IrPrintGen *irp, IrInstGenBr *inst) { + fprintf(irp->f, "goto "); + ir_print_other_block_gen(irp, inst->dest_block); +} + +static void ir_print_phi(IrPrintSrc *irp, IrInstSrcPhi *phi_instruction) { assert(phi_instruction->incoming_count != 0); assert(phi_instruction->incoming_count != SIZE_MAX); for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) { - IrBasicBlock *incoming_block = phi_instruction->incoming_blocks[i]; - IrInstruction *incoming_value = phi_instruction->incoming_values[i]; + IrBasicBlockSrc *incoming_block = phi_instruction->incoming_blocks[i]; + IrInstSrc *incoming_value = phi_instruction->incoming_values[i]; if (i != 0) fprintf(irp->f, " "); ir_print_other_block(irp, incoming_block); fprintf(irp->f, ":"); - ir_print_other_instruction(irp, incoming_value); + ir_print_other_inst_src(irp, incoming_value); } } -static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerInitList *instruction) { +static void ir_print_phi(IrPrintGen *irp, IrInstGenPhi *phi_instruction) { + assert(phi_instruction->incoming_count != 0); + assert(phi_instruction->incoming_count != SIZE_MAX); + for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) { + IrBasicBlockGen *incoming_block = phi_instruction->incoming_blocks[i]; + IrInstGen *incoming_value = phi_instruction->incoming_values[i]; + if (i != 0) + fprintf(irp->f, " "); + ir_print_other_block_gen(irp, incoming_block); + fprintf(irp->f, ":"); + ir_print_other_inst_gen(irp, incoming_value); + } +} + +static void ir_print_container_init_list(IrPrintSrc *irp, IrInstSrcContainerInitList *instruction) { fprintf(irp->f, "{"); if (instruction->item_count > 50) { fprintf(irp->f, "...(%" ZIG_PRI_usize " items)...", instruction->item_count); } else { for (size_t i = 0; i < instruction->item_count; i += 1) { - IrInstruction *result_loc = instruction->elem_result_loc_list[i]; + IrInstSrc *result_loc = instruction->elem_result_loc_list[i]; if (i != 0) fprintf(irp->f, ", "); - ir_print_other_instruction(irp, result_loc); + ir_print_other_inst_src(irp, result_loc); } } fprintf(irp->f, "}result="); - ir_print_other_instruction(irp, instruction->result_loc); + ir_print_other_inst_src(irp, instruction->result_loc); } -static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerInitFields *instruction) { +static void ir_print_container_init_fields(IrPrintSrc *irp, IrInstSrcContainerInitFields *instruction) { fprintf(irp->f, "{"); for (size_t i = 0; i < instruction->field_count; i += 1) { - IrInstructionContainerInitFieldsField *field = &instruction->fields[i]; + IrInstSrcContainerInitFieldsField *field = &instruction->fields[i]; const char *comma = (i == 0) ? "" : ", "; fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field->name)); - ir_print_other_instruction(irp, field->result_loc); + ir_print_other_inst_src(irp, field->result_loc); } fprintf(irp->f, "}result="); - ir_print_other_instruction(irp, instruction->result_loc); + ir_print_other_inst_src(irp, instruction->result_loc); } -static void ir_print_unreachable(IrPrint *irp, IrInstructionUnreachable *instruction) { +static void ir_print_unreachable(IrPrintSrc *irp, IrInstSrcUnreachable *instruction) { fprintf(irp->f, "unreachable"); } -static void ir_print_elem_ptr(IrPrint *irp, IrInstructionElemPtr *instruction) { +static void ir_print_unreachable(IrPrintGen *irp, IrInstGenUnreachable *instruction) { + fprintf(irp->f, "unreachable"); +} + +static void ir_print_elem_ptr(IrPrintSrc *irp, IrInstSrcElemPtr *instruction) { fprintf(irp->f, "&"); - ir_print_other_instruction(irp, instruction->array_ptr); + ir_print_other_inst_src(irp, instruction->array_ptr); fprintf(irp->f, "["); - ir_print_other_instruction(irp, instruction->elem_index); + ir_print_other_inst_src(irp, instruction->elem_index); fprintf(irp->f, "]"); if (!instruction->safety_check_on) { fprintf(irp->f, " // no safety"); } } -static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) { +static void ir_print_elem_ptr(IrPrintGen *irp, IrInstGenElemPtr *instruction) { + fprintf(irp->f, "&"); + ir_print_other_inst_gen(irp, instruction->array_ptr); + fprintf(irp->f, "["); + ir_print_other_inst_gen(irp, instruction->elem_index); + fprintf(irp->f, "]"); + if (!instruction->safety_check_on) { + fprintf(irp->f, " // no safety"); + } +} + +static void ir_print_var_ptr(IrPrintSrc *irp, IrInstSrcVarPtr *instruction) { fprintf(irp->f, "&%s", instruction->var->name); } -static void ir_print_return_ptr(IrPrint *irp, IrInstructionReturnPtr *instruction) { +static void ir_print_var_ptr(IrPrintGen *irp, IrInstGenVarPtr *instruction) { + fprintf(irp->f, "&%s", instruction->var->name); +} + +static void ir_print_return_ptr(IrPrintGen *irp, IrInstGenReturnPtr *instruction) { fprintf(irp->f, "@ReturnPtr"); } -static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) { - ir_print_other_instruction(irp, instruction->ptr); +static void ir_print_load_ptr(IrPrintSrc *irp, IrInstSrcLoadPtr *instruction) { + ir_print_other_inst_src(irp, instruction->ptr); fprintf(irp->f, ".*"); } -static void ir_print_load_ptr_gen(IrPrint *irp, IrInstructionLoadPtrGen *instruction) { +static void ir_print_load_ptr_gen(IrPrintGen *irp, IrInstGenLoadPtr *instruction) { fprintf(irp->f, "loadptr("); - ir_print_other_instruction(irp, instruction->ptr); + ir_print_other_inst_gen(irp, instruction->ptr); fprintf(irp->f, ")result="); - ir_print_other_instruction(irp, instruction->result_loc); + ir_print_other_inst_gen(irp, instruction->result_loc); } -static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) { +static void ir_print_store_ptr(IrPrintSrc *irp, IrInstSrcStorePtr *instruction) { fprintf(irp->f, "*"); - ir_print_var_instruction(irp, instruction->ptr); + ir_print_var_src(irp, instruction->ptr); fprintf(irp->f, " = "); - ir_print_other_instruction(irp, instruction->value); + ir_print_other_inst_src(irp, instruction->value); } -static void ir_print_vector_store_elem(IrPrint *irp, IrInstructionVectorStoreElem *instruction) { +static void ir_print_store_ptr(IrPrintGen *irp, IrInstGenStorePtr *instruction) { + fprintf(irp->f, "*"); + ir_print_var_gen(irp, instruction->ptr); + fprintf(irp->f, " = "); + ir_print_other_inst_gen(irp, instruction->value); +} + +static void ir_print_vector_store_elem(IrPrintGen *irp, IrInstGenVectorStoreElem *instruction) { fprintf(irp->f, "vector_ptr="); - ir_print_var_instruction(irp, instruction->vector_ptr); + ir_print_var_gen(irp, instruction->vector_ptr); fprintf(irp->f, ",index="); - ir_print_var_instruction(irp, instruction->index); + ir_print_var_gen(irp, instruction->index); fprintf(irp->f, ",value="); - ir_print_other_instruction(irp, instruction->value); + ir_print_other_inst_gen(irp, instruction->value); } -static void ir_print_typeof(IrPrint *irp, IrInstructionTypeOf *instruction) { +static void ir_print_typeof(IrPrintSrc *irp, IrInstSrcTypeOf *instruction) { fprintf(irp->f, "@TypeOf("); - ir_print_other_instruction(irp, instruction->value); + ir_print_other_inst_src(irp, instruction->value); fprintf(irp->f, ")"); } -static void ir_print_field_ptr(IrPrint *irp, IrInstructionFieldPtr *instruction) { +static void ir_print_binary_not(IrPrintGen *irp, IrInstGenBinaryNot *instruction) { + fprintf(irp->f, "~"); + ir_print_other_inst_gen(irp, instruction->operand); +} + +static void ir_print_negation(IrPrintGen *irp, IrInstGenNegation *instruction) { + fprintf(irp->f, "-"); + ir_print_other_inst_gen(irp, instruction->operand); +} + +static void ir_print_negation_wrapping(IrPrintGen *irp, IrInstGenNegationWrapping *instruction) { + fprintf(irp->f, "-%%"); + ir_print_other_inst_gen(irp, instruction->operand); +} + + +static void ir_print_field_ptr(IrPrintSrc *irp, IrInstSrcFieldPtr *instruction) { if (instruction->field_name_buffer) { fprintf(irp->f, "fieldptr "); - ir_print_other_instruction(irp, instruction->container_ptr); + ir_print_other_inst_src(irp, instruction->container_ptr); fprintf(irp->f, ".%s", buf_ptr(instruction->field_name_buffer)); } else { assert(instruction->field_name_expr); fprintf(irp->f, "@field("); - ir_print_other_instruction(irp, instruction->container_ptr); + ir_print_other_inst_src(irp, instruction->container_ptr); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->field_name_expr); + ir_print_other_inst_src(irp, instruction->field_name_expr); fprintf(irp->f, ")"); } } -static void ir_print_struct_field_ptr(IrPrint *irp, IrInstructionStructFieldPtr *instruction) { +static void ir_print_struct_field_ptr(IrPrintGen *irp, IrInstGenStructFieldPtr *instruction) { fprintf(irp->f, "@StructFieldPtr(&"); - ir_print_other_instruction(irp, instruction->struct_ptr); + ir_print_other_inst_gen(irp, instruction->struct_ptr); fprintf(irp->f, ".%s", buf_ptr(instruction->field->name)); fprintf(irp->f, ")"); } -static void ir_print_union_field_ptr(IrPrint *irp, IrInstructionUnionFieldPtr *instruction) { +static void ir_print_union_field_ptr(IrPrintGen *irp, IrInstGenUnionFieldPtr *instruction) { fprintf(irp->f, "@UnionFieldPtr(&"); - ir_print_other_instruction(irp, instruction->union_ptr); + ir_print_other_inst_gen(irp, instruction->union_ptr); fprintf(irp->f, ".%s", buf_ptr(instruction->field->enum_field->name)); fprintf(irp->f, ")"); } -static void ir_print_set_cold(IrPrint *irp, IrInstructionSetCold *instruction) { +static void ir_print_set_cold(IrPrintSrc *irp, IrInstSrcSetCold *instruction) { fprintf(irp->f, "@setCold("); - ir_print_other_instruction(irp, instruction->is_cold); + ir_print_other_inst_src(irp, instruction->is_cold); fprintf(irp->f, ")"); } -static void ir_print_set_runtime_safety(IrPrint *irp, IrInstructionSetRuntimeSafety *instruction) { +static void ir_print_set_runtime_safety(IrPrintSrc *irp, IrInstSrcSetRuntimeSafety *instruction) { fprintf(irp->f, "@setRuntimeSafety("); - ir_print_other_instruction(irp, instruction->safety_on); + ir_print_other_inst_src(irp, instruction->safety_on); fprintf(irp->f, ")"); } -static void ir_print_set_float_mode(IrPrint *irp, IrInstructionSetFloatMode *instruction) { +static void ir_print_set_float_mode(IrPrintSrc *irp, IrInstSrcSetFloatMode *instruction) { fprintf(irp->f, "@setFloatMode("); - ir_print_other_instruction(irp, instruction->scope_value); + ir_print_other_inst_src(irp, instruction->scope_value); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->mode_value); + ir_print_other_inst_src(irp, instruction->mode_value); fprintf(irp->f, ")"); } -static void ir_print_array_type(IrPrint *irp, IrInstructionArrayType *instruction) { +static void ir_print_array_type(IrPrintSrc *irp, IrInstSrcArrayType *instruction) { fprintf(irp->f, "["); - ir_print_other_instruction(irp, instruction->size); + ir_print_other_inst_src(irp, instruction->size); if (instruction->sentinel != nullptr) { fprintf(irp->f, ":"); - ir_print_other_instruction(irp, instruction->sentinel); + ir_print_other_inst_src(irp, instruction->sentinel); } fprintf(irp->f, "]"); - ir_print_other_instruction(irp, instruction->child_type); + ir_print_other_inst_src(irp, instruction->child_type); } -static void ir_print_slice_type(IrPrint *irp, IrInstructionSliceType *instruction) { +static void ir_print_slice_type(IrPrintSrc *irp, IrInstSrcSliceType *instruction) { const char *const_kw = instruction->is_const ? "const " : ""; fprintf(irp->f, "[]%s", const_kw); - ir_print_other_instruction(irp, instruction->child_type); + ir_print_other_inst_src(irp, instruction->child_type); } -static void ir_print_any_frame_type(IrPrint *irp, IrInstructionAnyFrameType *instruction) { +static void ir_print_any_frame_type(IrPrintSrc *irp, IrInstSrcAnyFrameType *instruction) { if (instruction->payload_type == nullptr) { fprintf(irp->f, "anyframe"); } else { fprintf(irp->f, "anyframe->"); - ir_print_other_instruction(irp, instruction->payload_type); + ir_print_other_inst_src(irp, instruction->payload_type); } } -static void ir_print_asm_src(IrPrint *irp, IrInstructionAsmSrc *instruction) { - assert(instruction->base.source_node->type == NodeTypeAsmExpr); - AstNodeAsmExpr *asm_expr = &instruction->base.source_node->data.asm_expr; +static void ir_print_asm_src(IrPrintSrc *irp, IrInstSrcAsm *instruction) { + assert(instruction->base.base.source_node->type == NodeTypeAsmExpr); + AstNodeAsmExpr *asm_expr = &instruction->base.base.source_node->data.asm_expr; const char *volatile_kw = instruction->has_side_effects ? " volatile" : ""; fprintf(irp->f, "asm%s (", volatile_kw); - ir_print_other_instruction(irp, instruction->asm_template); + ir_print_other_inst_src(irp, instruction->asm_template); for (size_t i = 0; i < asm_expr->output_list.length; i += 1) { AsmOutput *asm_output = asm_expr->output_list.at(i); @@ -969,7 +1250,7 @@ static void ir_print_asm_src(IrPrint *irp, IrInstructionAsmSrc *instruction) { buf_ptr(asm_output->constraint)); if (asm_output->return_type) { fprintf(irp->f, "-> "); - ir_print_other_instruction(irp, instruction->output_types[i]); + ir_print_other_inst_src(irp, instruction->output_types[i]); } else { fprintf(irp->f, "%s", buf_ptr(asm_output->variable_name)); } @@ -984,7 +1265,7 @@ static void ir_print_asm_src(IrPrint *irp, IrInstructionAsmSrc *instruction) { fprintf(irp->f, "[%s] \"%s\" (", buf_ptr(asm_input->asm_symbolic_name), buf_ptr(asm_input->constraint)); - ir_print_other_instruction(irp, instruction->input_list[i]); + ir_print_other_inst_src(irp, instruction->input_list[i]); fprintf(irp->f, ")"); } fprintf(irp->f, " : "); @@ -996,9 +1277,9 @@ static void ir_print_asm_src(IrPrint *irp, IrInstructionAsmSrc *instruction) { fprintf(irp->f, ")"); } -static void ir_print_asm_gen(IrPrint *irp, IrInstructionAsmGen *instruction) { - assert(instruction->base.source_node->type == NodeTypeAsmExpr); - AstNodeAsmExpr *asm_expr = &instruction->base.source_node->data.asm_expr; +static void ir_print_asm_gen(IrPrintGen *irp, IrInstGenAsm *instruction) { + assert(instruction->base.base.source_node->type == NodeTypeAsmExpr); + AstNodeAsmExpr *asm_expr = &instruction->base.base.source_node->data.asm_expr; const char *volatile_kw = instruction->has_side_effects ? " volatile" : ""; fprintf(irp->f, "asm%s (\"%s\") : ", volatile_kw, buf_ptr(instruction->asm_template)); @@ -1011,7 +1292,7 @@ static void ir_print_asm_gen(IrPrint *irp, IrInstructionAsmGen *instruction) { buf_ptr(asm_output->constraint)); if (asm_output->return_type) { fprintf(irp->f, "-> "); - ir_print_other_instruction(irp, instruction->output_types[i]); + ir_print_other_inst_gen(irp, instruction->output_types[i]); } else { fprintf(irp->f, "%s", buf_ptr(asm_output->variable_name)); } @@ -1026,7 +1307,7 @@ static void ir_print_asm_gen(IrPrint *irp, IrInstructionAsmGen *instruction) { fprintf(irp->f, "[%s] \"%s\" (", buf_ptr(asm_input->asm_symbolic_name), buf_ptr(asm_input->constraint)); - ir_print_other_instruction(irp, instruction->input_list[i]); + ir_print_other_inst_gen(irp, instruction->input_list[i]); fprintf(irp->f, ")"); } fprintf(irp->f, " : "); @@ -1038,96 +1319,120 @@ static void ir_print_asm_gen(IrPrint *irp, IrInstructionAsmGen *instruction) { fprintf(irp->f, ")"); } -static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) { +static void ir_print_size_of(IrPrintSrc *irp, IrInstSrcSizeOf *instruction) { if (instruction->bit_size) fprintf(irp->f, "@bitSizeOf("); else fprintf(irp->f, "@sizeOf("); - ir_print_other_instruction(irp, instruction->type_value); + ir_print_other_inst_src(irp, instruction->type_value); fprintf(irp->f, ")"); } -static void ir_print_test_non_null(IrPrint *irp, IrInstructionTestNonNull *instruction) { - ir_print_other_instruction(irp, instruction->value); +static void ir_print_test_non_null(IrPrintSrc *irp, IrInstSrcTestNonNull *instruction) { + ir_print_other_inst_src(irp, instruction->value); fprintf(irp->f, " != null"); } -static void ir_print_optional_unwrap_ptr(IrPrint *irp, IrInstructionOptionalUnwrapPtr *instruction) { +static void ir_print_test_non_null(IrPrintGen *irp, IrInstGenTestNonNull *instruction) { + ir_print_other_inst_gen(irp, instruction->value); + fprintf(irp->f, " != null"); +} + +static void ir_print_optional_unwrap_ptr(IrPrintSrc *irp, IrInstSrcOptionalUnwrapPtr *instruction) { fprintf(irp->f, "&"); - ir_print_other_instruction(irp, instruction->base_ptr); + ir_print_other_inst_src(irp, instruction->base_ptr); fprintf(irp->f, ".*.?"); if (!instruction->safety_check_on) { fprintf(irp->f, " // no safety"); } } -static void ir_print_clz(IrPrint *irp, IrInstructionClz *instruction) { +static void ir_print_optional_unwrap_ptr(IrPrintGen *irp, IrInstGenOptionalUnwrapPtr *instruction) { + fprintf(irp->f, "&"); + ir_print_other_inst_gen(irp, instruction->base_ptr); + fprintf(irp->f, ".*.?"); + if (!instruction->safety_check_on) { + fprintf(irp->f, " // no safety"); + } +} + +static void ir_print_clz(IrPrintSrc *irp, IrInstSrcClz *instruction) { fprintf(irp->f, "@clz("); - if (instruction->type != nullptr) { - ir_print_other_instruction(irp, instruction->type); - } else { - fprintf(irp->f, "null"); - } + ir_print_other_inst_src(irp, instruction->type); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->op); + ir_print_other_inst_src(irp, instruction->op); fprintf(irp->f, ")"); } -static void ir_print_ctz(IrPrint *irp, IrInstructionCtz *instruction) { +static void ir_print_clz(IrPrintGen *irp, IrInstGenClz *instruction) { + fprintf(irp->f, "@clz("); + ir_print_other_inst_gen(irp, instruction->op); + fprintf(irp->f, ")"); +} + +static void ir_print_ctz(IrPrintSrc *irp, IrInstSrcCtz *instruction) { fprintf(irp->f, "@ctz("); - if (instruction->type != nullptr) { - ir_print_other_instruction(irp, instruction->type); - } else { - fprintf(irp->f, "null"); - } + ir_print_other_inst_src(irp, instruction->type); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->op); + ir_print_other_inst_src(irp, instruction->op); fprintf(irp->f, ")"); } -static void ir_print_pop_count(IrPrint *irp, IrInstructionPopCount *instruction) { +static void ir_print_ctz(IrPrintGen *irp, IrInstGenCtz *instruction) { + fprintf(irp->f, "@ctz("); + ir_print_other_inst_gen(irp, instruction->op); + fprintf(irp->f, ")"); +} + +static void ir_print_pop_count(IrPrintSrc *irp, IrInstSrcPopCount *instruction) { fprintf(irp->f, "@popCount("); - if (instruction->type != nullptr) { - ir_print_other_instruction(irp, instruction->type); - } else { - fprintf(irp->f, "null"); - } + ir_print_other_inst_src(irp, instruction->type); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->op); + ir_print_other_inst_src(irp, instruction->op); fprintf(irp->f, ")"); } -static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) { +static void ir_print_pop_count(IrPrintGen *irp, IrInstGenPopCount *instruction) { + fprintf(irp->f, "@popCount("); + ir_print_other_inst_gen(irp, instruction->op); + fprintf(irp->f, ")"); +} + +static void ir_print_bswap(IrPrintSrc *irp, IrInstSrcBswap *instruction) { fprintf(irp->f, "@byteSwap("); - if (instruction->type != nullptr) { - ir_print_other_instruction(irp, instruction->type); - } else { - fprintf(irp->f, "null"); - } + ir_print_other_inst_src(irp, instruction->type); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->op); + ir_print_other_inst_src(irp, instruction->op); fprintf(irp->f, ")"); } -static void ir_print_bit_reverse(IrPrint *irp, IrInstructionBitReverse *instruction) { +static void ir_print_bswap(IrPrintGen *irp, IrInstGenBswap *instruction) { + fprintf(irp->f, "@byteSwap("); + ir_print_other_inst_gen(irp, instruction->op); + fprintf(irp->f, ")"); +} + +static void ir_print_bit_reverse(IrPrintSrc *irp, IrInstSrcBitReverse *instruction) { fprintf(irp->f, "@bitReverse("); - if (instruction->type != nullptr) { - ir_print_other_instruction(irp, instruction->type); - } else { - fprintf(irp->f, "null"); - } + ir_print_other_inst_src(irp, instruction->type); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->op); + ir_print_other_inst_src(irp, instruction->op); fprintf(irp->f, ")"); } -static void ir_print_switch_br(IrPrint *irp, IrInstructionSwitchBr *instruction) { +static void ir_print_bit_reverse(IrPrintGen *irp, IrInstGenBitReverse *instruction) { + fprintf(irp->f, "@bitReverse("); + ir_print_other_inst_gen(irp, instruction->op); + fprintf(irp->f, ")"); +} + +static void ir_print_switch_br(IrPrintSrc *irp, IrInstSrcSwitchBr *instruction) { fprintf(irp->f, "switch ("); - ir_print_other_instruction(irp, instruction->target_value); + ir_print_other_inst_src(irp, instruction->target_value); fprintf(irp->f, ") "); for (size_t i = 0; i < instruction->case_count; i += 1) { - IrInstructionSwitchBrCase *this_case = &instruction->cases[i]; - ir_print_other_instruction(irp, this_case->value); + IrInstSrcSwitchBrCase *this_case = &instruction->cases[i]; + ir_print_other_inst_src(irp, this_case->value); fprintf(irp->f, " => "); ir_print_other_block(irp, this_case->block); fprintf(irp->f, ", "); @@ -1136,359 +1441,453 @@ static void ir_print_switch_br(IrPrint *irp, IrInstructionSwitchBr *instruction) ir_print_other_block(irp, instruction->else_block); if (instruction->is_comptime != nullptr) { fprintf(irp->f, " // comptime = "); - ir_print_other_instruction(irp, instruction->is_comptime); + ir_print_other_inst_src(irp, instruction->is_comptime); } } -static void ir_print_switch_var(IrPrint *irp, IrInstructionSwitchVar *instruction) { +static void ir_print_switch_br(IrPrintGen *irp, IrInstGenSwitchBr *instruction) { + fprintf(irp->f, "switch ("); + ir_print_other_inst_gen(irp, instruction->target_value); + fprintf(irp->f, ") "); + for (size_t i = 0; i < instruction->case_count; i += 1) { + IrInstGenSwitchBrCase *this_case = &instruction->cases[i]; + ir_print_other_inst_gen(irp, this_case->value); + fprintf(irp->f, " => "); + ir_print_other_block_gen(irp, this_case->block); + fprintf(irp->f, ", "); + } + fprintf(irp->f, "else => "); + ir_print_other_block_gen(irp, instruction->else_block); +} + +static void ir_print_switch_var(IrPrintSrc *irp, IrInstSrcSwitchVar *instruction) { fprintf(irp->f, "switchvar "); - ir_print_other_instruction(irp, instruction->target_value_ptr); + ir_print_other_inst_src(irp, instruction->target_value_ptr); for (size_t i = 0; i < instruction->prongs_len; i += 1) { fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->prongs_ptr[i]); + ir_print_other_inst_src(irp, instruction->prongs_ptr[i]); } } -static void ir_print_switch_else_var(IrPrint *irp, IrInstructionSwitchElseVar *instruction) { +static void ir_print_switch_else_var(IrPrintSrc *irp, IrInstSrcSwitchElseVar *instruction) { fprintf(irp->f, "switchelsevar "); - ir_print_other_instruction(irp, &instruction->switch_br->base); + ir_print_other_inst_src(irp, &instruction->switch_br->base); } -static void ir_print_switch_target(IrPrint *irp, IrInstructionSwitchTarget *instruction) { +static void ir_print_switch_target(IrPrintSrc *irp, IrInstSrcSwitchTarget *instruction) { fprintf(irp->f, "switchtarget "); - ir_print_other_instruction(irp, instruction->target_value_ptr); + ir_print_other_inst_src(irp, instruction->target_value_ptr); } -static void ir_print_union_tag(IrPrint *irp, IrInstructionUnionTag *instruction) { +static void ir_print_union_tag(IrPrintGen *irp, IrInstGenUnionTag *instruction) { fprintf(irp->f, "uniontag "); - ir_print_other_instruction(irp, instruction->value); + ir_print_other_inst_gen(irp, instruction->value); } -static void ir_print_import(IrPrint *irp, IrInstructionImport *instruction) { +static void ir_print_import(IrPrintSrc *irp, IrInstSrcImport *instruction) { fprintf(irp->f, "@import("); - ir_print_other_instruction(irp, instruction->name); + ir_print_other_inst_src(irp, instruction->name); fprintf(irp->f, ")"); } -static void ir_print_ref(IrPrint *irp, IrInstructionRef *instruction) { +static void ir_print_ref(IrPrintSrc *irp, IrInstSrcRef *instruction) { const char *const_str = instruction->is_const ? "const " : ""; const char *volatile_str = instruction->is_volatile ? "volatile " : ""; fprintf(irp->f, "%s%sref ", const_str, volatile_str); - ir_print_other_instruction(irp, instruction->value); + ir_print_other_inst_src(irp, instruction->value); } -static void ir_print_ref_gen(IrPrint *irp, IrInstructionRefGen *instruction) { +static void ir_print_ref_gen(IrPrintGen *irp, IrInstGenRef *instruction) { fprintf(irp->f, "@ref("); - ir_print_other_instruction(irp, instruction->operand); + ir_print_other_inst_gen(irp, instruction->operand); fprintf(irp->f, ")result="); - ir_print_other_instruction(irp, instruction->result_loc); + ir_print_other_inst_gen(irp, instruction->result_loc); } -static void ir_print_compile_err(IrPrint *irp, IrInstructionCompileErr *instruction) { +static void ir_print_compile_err(IrPrintSrc *irp, IrInstSrcCompileErr *instruction) { fprintf(irp->f, "@compileError("); - ir_print_other_instruction(irp, instruction->msg); + ir_print_other_inst_src(irp, instruction->msg); fprintf(irp->f, ")"); } -static void ir_print_compile_log(IrPrint *irp, IrInstructionCompileLog *instruction) { +static void ir_print_compile_log(IrPrintSrc *irp, IrInstSrcCompileLog *instruction) { fprintf(irp->f, "@compileLog("); for (size_t i = 0; i < instruction->msg_count; i += 1) { if (i != 0) fprintf(irp->f, ","); - IrInstruction *msg = instruction->msg_list[i]; - ir_print_other_instruction(irp, msg); + IrInstSrc *msg = instruction->msg_list[i]; + ir_print_other_inst_src(irp, msg); } fprintf(irp->f, ")"); } -static void ir_print_err_name(IrPrint *irp, IrInstructionErrName *instruction) { +static void ir_print_err_name(IrPrintSrc *irp, IrInstSrcErrName *instruction) { fprintf(irp->f, "@errorName("); - ir_print_other_instruction(irp, instruction->value); + ir_print_other_inst_src(irp, instruction->value); fprintf(irp->f, ")"); } -static void ir_print_c_import(IrPrint *irp, IrInstructionCImport *instruction) { +static void ir_print_err_name(IrPrintGen *irp, IrInstGenErrName *instruction) { + fprintf(irp->f, "@errorName("); + ir_print_other_inst_gen(irp, instruction->value); + fprintf(irp->f, ")"); +} + +static void ir_print_c_import(IrPrintSrc *irp, IrInstSrcCImport *instruction) { fprintf(irp->f, "@cImport(...)"); } -static void ir_print_c_include(IrPrint *irp, IrInstructionCInclude *instruction) { +static void ir_print_c_include(IrPrintSrc *irp, IrInstSrcCInclude *instruction) { fprintf(irp->f, "@cInclude("); - ir_print_other_instruction(irp, instruction->name); + ir_print_other_inst_src(irp, instruction->name); fprintf(irp->f, ")"); } -static void ir_print_c_define(IrPrint *irp, IrInstructionCDefine *instruction) { +static void ir_print_c_define(IrPrintSrc *irp, IrInstSrcCDefine *instruction) { fprintf(irp->f, "@cDefine("); - ir_print_other_instruction(irp, instruction->name); + ir_print_other_inst_src(irp, instruction->name); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->value); + ir_print_other_inst_src(irp, instruction->value); fprintf(irp->f, ")"); } -static void ir_print_c_undef(IrPrint *irp, IrInstructionCUndef *instruction) { +static void ir_print_c_undef(IrPrintSrc *irp, IrInstSrcCUndef *instruction) { fprintf(irp->f, "@cUndef("); - ir_print_other_instruction(irp, instruction->name); + ir_print_other_inst_src(irp, instruction->name); fprintf(irp->f, ")"); } -static void ir_print_embed_file(IrPrint *irp, IrInstructionEmbedFile *instruction) { +static void ir_print_embed_file(IrPrintSrc *irp, IrInstSrcEmbedFile *instruction) { fprintf(irp->f, "@embedFile("); - ir_print_other_instruction(irp, instruction->name); + ir_print_other_inst_src(irp, instruction->name); fprintf(irp->f, ")"); } -static void ir_print_cmpxchg_src(IrPrint *irp, IrInstructionCmpxchgSrc *instruction) { +static void ir_print_cmpxchg_src(IrPrintSrc *irp, IrInstSrcCmpxchg *instruction) { fprintf(irp->f, "@cmpxchg("); - ir_print_other_instruction(irp, instruction->ptr); + ir_print_other_inst_src(irp, instruction->ptr); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->cmp_value); + ir_print_other_inst_src(irp, instruction->cmp_value); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->new_value); + ir_print_other_inst_src(irp, instruction->new_value); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->success_order_value); + ir_print_other_inst_src(irp, instruction->success_order_value); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->failure_order_value); + ir_print_other_inst_src(irp, instruction->failure_order_value); fprintf(irp->f, ")result="); ir_print_result_loc(irp, instruction->result_loc); } -static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruction) { +static void ir_print_cmpxchg_gen(IrPrintGen *irp, IrInstGenCmpxchg *instruction) { fprintf(irp->f, "@cmpxchg("); - ir_print_other_instruction(irp, instruction->ptr); + ir_print_other_inst_gen(irp, instruction->ptr); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->cmp_value); + ir_print_other_inst_gen(irp, instruction->cmp_value); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->new_value); + ir_print_other_inst_gen(irp, instruction->new_value); fprintf(irp->f, ", TODO print atomic orders)result="); - ir_print_other_instruction(irp, instruction->result_loc); + ir_print_other_inst_gen(irp, instruction->result_loc); } -static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) { +static void ir_print_fence(IrPrintSrc *irp, IrInstSrcFence *instruction) { fprintf(irp->f, "@fence("); - ir_print_other_instruction(irp, instruction->order_value); + ir_print_other_inst_src(irp, instruction->order); fprintf(irp->f, ")"); } -static void ir_print_truncate(IrPrint *irp, IrInstructionTruncate *instruction) { +static const char *atomic_order_str(AtomicOrder order) { + switch (order) { + case AtomicOrderUnordered: return "Unordered"; + case AtomicOrderMonotonic: return "Monotonic"; + case AtomicOrderAcquire: return "Acquire"; + case AtomicOrderRelease: return "Release"; + case AtomicOrderAcqRel: return "AcqRel"; + case AtomicOrderSeqCst: return "SeqCst"; + } + zig_unreachable(); +} + +static void ir_print_fence(IrPrintGen *irp, IrInstGenFence *instruction) { + fprintf(irp->f, "fence %s", atomic_order_str(instruction->order)); +} + +static void ir_print_truncate(IrPrintSrc *irp, IrInstSrcTruncate *instruction) { fprintf(irp->f, "@truncate("); - ir_print_other_instruction(irp, instruction->dest_type); + ir_print_other_inst_src(irp, instruction->dest_type); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_src(irp, instruction->target); fprintf(irp->f, ")"); } -static void ir_print_int_cast(IrPrint *irp, IrInstructionIntCast *instruction) { +static void ir_print_truncate(IrPrintGen *irp, IrInstGenTruncate *instruction) { + fprintf(irp->f, "@truncate("); + ir_print_other_inst_gen(irp, instruction->target); + fprintf(irp->f, ")"); +} + +static void ir_print_int_cast(IrPrintSrc *irp, IrInstSrcIntCast *instruction) { fprintf(irp->f, "@intCast("); - ir_print_other_instruction(irp, instruction->dest_type); + ir_print_other_inst_src(irp, instruction->dest_type); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_src(irp, instruction->target); fprintf(irp->f, ")"); } -static void ir_print_float_cast(IrPrint *irp, IrInstructionFloatCast *instruction) { +static void ir_print_float_cast(IrPrintSrc *irp, IrInstSrcFloatCast *instruction) { fprintf(irp->f, "@floatCast("); - ir_print_other_instruction(irp, instruction->dest_type); + ir_print_other_inst_src(irp, instruction->dest_type); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_src(irp, instruction->target); fprintf(irp->f, ")"); } -static void ir_print_err_set_cast(IrPrint *irp, IrInstructionErrSetCast *instruction) { +static void ir_print_err_set_cast(IrPrintSrc *irp, IrInstSrcErrSetCast *instruction) { fprintf(irp->f, "@errSetCast("); - ir_print_other_instruction(irp, instruction->dest_type); + ir_print_other_inst_src(irp, instruction->dest_type); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_src(irp, instruction->target); fprintf(irp->f, ")"); } -static void ir_print_from_bytes(IrPrint *irp, IrInstructionFromBytes *instruction) { +static void ir_print_from_bytes(IrPrintSrc *irp, IrInstSrcFromBytes *instruction) { fprintf(irp->f, "@bytesToSlice("); - ir_print_other_instruction(irp, instruction->dest_child_type); + ir_print_other_inst_src(irp, instruction->dest_child_type); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_src(irp, instruction->target); fprintf(irp->f, ")"); } -static void ir_print_to_bytes(IrPrint *irp, IrInstructionToBytes *instruction) { +static void ir_print_to_bytes(IrPrintSrc *irp, IrInstSrcToBytes *instruction) { fprintf(irp->f, "@sliceToBytes("); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_src(irp, instruction->target); fprintf(irp->f, ")"); } -static void ir_print_int_to_float(IrPrint *irp, IrInstructionIntToFloat *instruction) { +static void ir_print_int_to_float(IrPrintSrc *irp, IrInstSrcIntToFloat *instruction) { fprintf(irp->f, "@intToFloat("); - ir_print_other_instruction(irp, instruction->dest_type); + ir_print_other_inst_src(irp, instruction->dest_type); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_src(irp, instruction->target); fprintf(irp->f, ")"); } -static void ir_print_float_to_int(IrPrint *irp, IrInstructionFloatToInt *instruction) { +static void ir_print_float_to_int(IrPrintSrc *irp, IrInstSrcFloatToInt *instruction) { fprintf(irp->f, "@floatToInt("); - ir_print_other_instruction(irp, instruction->dest_type); + ir_print_other_inst_src(irp, instruction->dest_type); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_src(irp, instruction->target); fprintf(irp->f, ")"); } -static void ir_print_bool_to_int(IrPrint *irp, IrInstructionBoolToInt *instruction) { +static void ir_print_bool_to_int(IrPrintSrc *irp, IrInstSrcBoolToInt *instruction) { fprintf(irp->f, "@boolToInt("); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_src(irp, instruction->target); fprintf(irp->f, ")"); } -static void ir_print_int_type(IrPrint *irp, IrInstructionIntType *instruction) { +static void ir_print_int_type(IrPrintSrc *irp, IrInstSrcIntType *instruction) { fprintf(irp->f, "@IntType("); - ir_print_other_instruction(irp, instruction->is_signed); + ir_print_other_inst_src(irp, instruction->is_signed); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->bit_count); + ir_print_other_inst_src(irp, instruction->bit_count); fprintf(irp->f, ")"); } -static void ir_print_vector_type(IrPrint *irp, IrInstructionVectorType *instruction) { +static void ir_print_vector_type(IrPrintSrc *irp, IrInstSrcVectorType *instruction) { fprintf(irp->f, "@Vector("); - ir_print_other_instruction(irp, instruction->len); + ir_print_other_inst_src(irp, instruction->len); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->elem_type); + ir_print_other_inst_src(irp, instruction->elem_type); fprintf(irp->f, ")"); } -static void ir_print_shuffle_vector(IrPrint *irp, IrInstructionShuffleVector *instruction) { +static void ir_print_shuffle_vector(IrPrintSrc *irp, IrInstSrcShuffleVector *instruction) { fprintf(irp->f, "@shuffle("); - ir_print_other_instruction(irp, instruction->scalar_type); + ir_print_other_inst_src(irp, instruction->scalar_type); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->a); + ir_print_other_inst_src(irp, instruction->a); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->b); + ir_print_other_inst_src(irp, instruction->b); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->mask); + ir_print_other_inst_src(irp, instruction->mask); fprintf(irp->f, ")"); } -static void ir_print_splat_src(IrPrint *irp, IrInstructionSplatSrc *instruction) { +static void ir_print_shuffle_vector(IrPrintGen *irp, IrInstGenShuffleVector *instruction) { + fprintf(irp->f, "@shuffle("); + ir_print_other_inst_gen(irp, instruction->a); + fprintf(irp->f, ", "); + ir_print_other_inst_gen(irp, instruction->b); + fprintf(irp->f, ", "); + ir_print_other_inst_gen(irp, instruction->mask); + fprintf(irp->f, ")"); +} + +static void ir_print_splat_src(IrPrintSrc *irp, IrInstSrcSplat *instruction) { fprintf(irp->f, "@splat("); - ir_print_other_instruction(irp, instruction->len); + ir_print_other_inst_src(irp, instruction->len); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->scalar); + ir_print_other_inst_src(irp, instruction->scalar); fprintf(irp->f, ")"); } -static void ir_print_splat_gen(IrPrint *irp, IrInstructionSplatGen *instruction) { +static void ir_print_splat_gen(IrPrintGen *irp, IrInstGenSplat *instruction) { fprintf(irp->f, "@splat("); - ir_print_other_instruction(irp, instruction->scalar); + ir_print_other_inst_gen(irp, instruction->scalar); fprintf(irp->f, ")"); } -static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) { +static void ir_print_bool_not(IrPrintSrc *irp, IrInstSrcBoolNot *instruction) { fprintf(irp->f, "! "); - ir_print_other_instruction(irp, instruction->value); + ir_print_other_inst_src(irp, instruction->value); } -static void ir_print_memset(IrPrint *irp, IrInstructionMemset *instruction) { +static void ir_print_bool_not(IrPrintGen *irp, IrInstGenBoolNot *instruction) { + fprintf(irp->f, "! "); + ir_print_other_inst_gen(irp, instruction->value); +} + +static void ir_print_memset(IrPrintSrc *irp, IrInstSrcMemset *instruction) { fprintf(irp->f, "@memset("); - ir_print_other_instruction(irp, instruction->dest_ptr); + ir_print_other_inst_src(irp, instruction->dest_ptr); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->byte); + ir_print_other_inst_src(irp, instruction->byte); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->count); + ir_print_other_inst_src(irp, instruction->count); fprintf(irp->f, ")"); } -static void ir_print_memcpy(IrPrint *irp, IrInstructionMemcpy *instruction) { +static void ir_print_memset(IrPrintGen *irp, IrInstGenMemset *instruction) { + fprintf(irp->f, "@memset("); + ir_print_other_inst_gen(irp, instruction->dest_ptr); + fprintf(irp->f, ", "); + ir_print_other_inst_gen(irp, instruction->byte); + fprintf(irp->f, ", "); + ir_print_other_inst_gen(irp, instruction->count); + fprintf(irp->f, ")"); +} + +static void ir_print_memcpy(IrPrintSrc *irp, IrInstSrcMemcpy *instruction) { fprintf(irp->f, "@memcpy("); - ir_print_other_instruction(irp, instruction->dest_ptr); + ir_print_other_inst_src(irp, instruction->dest_ptr); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->src_ptr); + ir_print_other_inst_src(irp, instruction->src_ptr); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->count); + ir_print_other_inst_src(irp, instruction->count); fprintf(irp->f, ")"); } -static void ir_print_slice_src(IrPrint *irp, IrInstructionSliceSrc *instruction) { - ir_print_other_instruction(irp, instruction->ptr); +static void ir_print_memcpy(IrPrintGen *irp, IrInstGenMemcpy *instruction) { + fprintf(irp->f, "@memcpy("); + ir_print_other_inst_gen(irp, instruction->dest_ptr); + fprintf(irp->f, ", "); + ir_print_other_inst_gen(irp, instruction->src_ptr); + fprintf(irp->f, ", "); + ir_print_other_inst_gen(irp, instruction->count); + fprintf(irp->f, ")"); +} + +static void ir_print_slice_src(IrPrintSrc *irp, IrInstSrcSlice *instruction) { + ir_print_other_inst_src(irp, instruction->ptr); fprintf(irp->f, "["); - ir_print_other_instruction(irp, instruction->start); + ir_print_other_inst_src(irp, instruction->start); fprintf(irp->f, ".."); if (instruction->end) - ir_print_other_instruction(irp, instruction->end); + ir_print_other_inst_src(irp, instruction->end); fprintf(irp->f, "]result="); ir_print_result_loc(irp, instruction->result_loc); } -static void ir_print_slice_gen(IrPrint *irp, IrInstructionSliceGen *instruction) { - ir_print_other_instruction(irp, instruction->ptr); +static void ir_print_slice_gen(IrPrintGen *irp, IrInstGenSlice *instruction) { + ir_print_other_inst_gen(irp, instruction->ptr); fprintf(irp->f, "["); - ir_print_other_instruction(irp, instruction->start); + ir_print_other_inst_gen(irp, instruction->start); fprintf(irp->f, ".."); if (instruction->end) - ir_print_other_instruction(irp, instruction->end); + ir_print_other_inst_gen(irp, instruction->end); fprintf(irp->f, "]result="); - ir_print_other_instruction(irp, instruction->result_loc); + ir_print_other_inst_gen(irp, instruction->result_loc); } -static void ir_print_member_count(IrPrint *irp, IrInstructionMemberCount *instruction) { +static void ir_print_member_count(IrPrintSrc *irp, IrInstSrcMemberCount *instruction) { fprintf(irp->f, "@memberCount("); - ir_print_other_instruction(irp, instruction->container); + ir_print_other_inst_src(irp, instruction->container); fprintf(irp->f, ")"); } -static void ir_print_member_type(IrPrint *irp, IrInstructionMemberType *instruction) { +static void ir_print_member_type(IrPrintSrc *irp, IrInstSrcMemberType *instruction) { fprintf(irp->f, "@memberType("); - ir_print_other_instruction(irp, instruction->container_type); + ir_print_other_inst_src(irp, instruction->container_type); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->member_index); + ir_print_other_inst_src(irp, instruction->member_index); fprintf(irp->f, ")"); } -static void ir_print_member_name(IrPrint *irp, IrInstructionMemberName *instruction) { +static void ir_print_member_name(IrPrintSrc *irp, IrInstSrcMemberName *instruction) { fprintf(irp->f, "@memberName("); - ir_print_other_instruction(irp, instruction->container_type); + ir_print_other_inst_src(irp, instruction->container_type); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->member_index); + ir_print_other_inst_src(irp, instruction->member_index); fprintf(irp->f, ")"); } -static void ir_print_breakpoint(IrPrint *irp, IrInstructionBreakpoint *instruction) { +static void ir_print_breakpoint(IrPrintSrc *irp, IrInstSrcBreakpoint *instruction) { fprintf(irp->f, "@breakpoint()"); } -static void ir_print_frame_address(IrPrint *irp, IrInstructionFrameAddress *instruction) { +static void ir_print_breakpoint(IrPrintGen *irp, IrInstGenBreakpoint *instruction) { + fprintf(irp->f, "@breakpoint()"); +} + +static void ir_print_frame_address(IrPrintSrc *irp, IrInstSrcFrameAddress *instruction) { fprintf(irp->f, "@frameAddress()"); } -static void ir_print_handle(IrPrint *irp, IrInstructionFrameHandle *instruction) { +static void ir_print_frame_address(IrPrintGen *irp, IrInstGenFrameAddress *instruction) { + fprintf(irp->f, "@frameAddress()"); +} + +static void ir_print_handle(IrPrintSrc *irp, IrInstSrcFrameHandle *instruction) { fprintf(irp->f, "@frame()"); } -static void ir_print_frame_type(IrPrint *irp, IrInstructionFrameType *instruction) { +static void ir_print_handle(IrPrintGen *irp, IrInstGenFrameHandle *instruction) { + fprintf(irp->f, "@frame()"); +} + +static void ir_print_frame_type(IrPrintSrc *irp, IrInstSrcFrameType *instruction) { fprintf(irp->f, "@Frame("); - ir_print_other_instruction(irp, instruction->fn); + ir_print_other_inst_src(irp, instruction->fn); fprintf(irp->f, ")"); } -static void ir_print_frame_size_src(IrPrint *irp, IrInstructionFrameSizeSrc *instruction) { +static void ir_print_frame_size_src(IrPrintSrc *irp, IrInstSrcFrameSize *instruction) { fprintf(irp->f, "@frameSize("); - ir_print_other_instruction(irp, instruction->fn); + ir_print_other_inst_src(irp, instruction->fn); fprintf(irp->f, ")"); } -static void ir_print_frame_size_gen(IrPrint *irp, IrInstructionFrameSizeGen *instruction) { +static void ir_print_frame_size_gen(IrPrintGen *irp, IrInstGenFrameSize *instruction) { fprintf(irp->f, "@frameSize("); - ir_print_other_instruction(irp, instruction->fn); + ir_print_other_inst_gen(irp, instruction->fn); fprintf(irp->f, ")"); } -static void ir_print_return_address(IrPrint *irp, IrInstructionReturnAddress *instruction) { +static void ir_print_return_address(IrPrintSrc *irp, IrInstSrcReturnAddress *instruction) { fprintf(irp->f, "@returnAddress()"); } -static void ir_print_align_of(IrPrint *irp, IrInstructionAlignOf *instruction) { +static void ir_print_return_address(IrPrintGen *irp, IrInstGenReturnAddress *instruction) { + fprintf(irp->f, "@returnAddress()"); +} + +static void ir_print_align_of(IrPrintSrc *irp, IrInstSrcAlignOf *instruction) { fprintf(irp->f, "@alignOf("); - ir_print_other_instruction(irp, instruction->type_value); + ir_print_other_inst_src(irp, instruction->type_value); fprintf(irp->f, ")"); } -static void ir_print_overflow_op(IrPrint *irp, IrInstructionOverflowOp *instruction) { +static void ir_print_overflow_op(IrPrintSrc *irp, IrInstSrcOverflowOp *instruction) { switch (instruction->op) { case IrOverflowOpAdd: fprintf(irp->f, "@addWithOverflow("); @@ -1503,1146 +1902,1457 @@ static void ir_print_overflow_op(IrPrint *irp, IrInstructionOverflowOp *instruct fprintf(irp->f, "@shlWithOverflow("); break; } - ir_print_other_instruction(irp, instruction->type_value); + ir_print_other_inst_src(irp, instruction->type_value); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->op1); + ir_print_other_inst_src(irp, instruction->op1); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->op2); + ir_print_other_inst_src(irp, instruction->op2); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->result_ptr); + ir_print_other_inst_src(irp, instruction->result_ptr); fprintf(irp->f, ")"); } -static void ir_print_test_err_src(IrPrint *irp, IrInstructionTestErrSrc *instruction) { +static void ir_print_overflow_op(IrPrintGen *irp, IrInstGenOverflowOp *instruction) { + switch (instruction->op) { + case IrOverflowOpAdd: + fprintf(irp->f, "@addWithOverflow("); + break; + case IrOverflowOpSub: + fprintf(irp->f, "@subWithOverflow("); + break; + case IrOverflowOpMul: + fprintf(irp->f, "@mulWithOverflow("); + break; + case IrOverflowOpShl: + fprintf(irp->f, "@shlWithOverflow("); + break; + } + ir_print_other_inst_gen(irp, instruction->op1); + fprintf(irp->f, ", "); + ir_print_other_inst_gen(irp, instruction->op2); + fprintf(irp->f, ", "); + ir_print_other_inst_gen(irp, instruction->result_ptr); + fprintf(irp->f, ")"); +} + +static void ir_print_test_err_src(IrPrintSrc *irp, IrInstSrcTestErr *instruction) { fprintf(irp->f, "@testError("); - ir_print_other_instruction(irp, instruction->base_ptr); + ir_print_other_inst_src(irp, instruction->base_ptr); fprintf(irp->f, ")"); } -static void ir_print_test_err_gen(IrPrint *irp, IrInstructionTestErrGen *instruction) { +static void ir_print_test_err_gen(IrPrintGen *irp, IrInstGenTestErr *instruction) { fprintf(irp->f, "@testError("); - ir_print_other_instruction(irp, instruction->err_union); + ir_print_other_inst_gen(irp, instruction->err_union); fprintf(irp->f, ")"); } -static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) { +static void ir_print_unwrap_err_code(IrPrintSrc *irp, IrInstSrcUnwrapErrCode *instruction) { fprintf(irp->f, "UnwrapErrorCode("); - ir_print_other_instruction(irp, instruction->err_union_ptr); + ir_print_other_inst_src(irp, instruction->err_union_ptr); fprintf(irp->f, ")"); } -static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) { +static void ir_print_unwrap_err_code(IrPrintGen *irp, IrInstGenUnwrapErrCode *instruction) { + fprintf(irp->f, "UnwrapErrorCode("); + ir_print_other_inst_gen(irp, instruction->err_union_ptr); + fprintf(irp->f, ")"); +} + +static void ir_print_unwrap_err_payload(IrPrintSrc *irp, IrInstSrcUnwrapErrPayload *instruction) { fprintf(irp->f, "ErrorUnionFieldPayload("); - ir_print_other_instruction(irp, instruction->value); + ir_print_other_inst_src(irp, instruction->value); fprintf(irp->f, ")safety=%d,init=%d",instruction->safety_check_on, instruction->initializing); } -static void ir_print_optional_wrap(IrPrint *irp, IrInstructionOptionalWrap *instruction) { +static void ir_print_unwrap_err_payload(IrPrintGen *irp, IrInstGenUnwrapErrPayload *instruction) { + fprintf(irp->f, "ErrorUnionFieldPayload("); + ir_print_other_inst_gen(irp, instruction->value); + fprintf(irp->f, ")safety=%d,init=%d",instruction->safety_check_on, instruction->initializing); +} + +static void ir_print_optional_wrap(IrPrintGen *irp, IrInstGenOptionalWrap *instruction) { fprintf(irp->f, "@optionalWrap("); - ir_print_other_instruction(irp, instruction->operand); + ir_print_other_inst_gen(irp, instruction->operand); fprintf(irp->f, ")result="); - ir_print_other_instruction(irp, instruction->result_loc); + ir_print_other_inst_gen(irp, instruction->result_loc); } -static void ir_print_err_wrap_code(IrPrint *irp, IrInstructionErrWrapCode *instruction) { +static void ir_print_err_wrap_code(IrPrintGen *irp, IrInstGenErrWrapCode *instruction) { fprintf(irp->f, "@errWrapCode("); - ir_print_other_instruction(irp, instruction->operand); + ir_print_other_inst_gen(irp, instruction->operand); fprintf(irp->f, ")result="); - ir_print_other_instruction(irp, instruction->result_loc); + ir_print_other_inst_gen(irp, instruction->result_loc); } -static void ir_print_err_wrap_payload(IrPrint *irp, IrInstructionErrWrapPayload *instruction) { +static void ir_print_err_wrap_payload(IrPrintGen *irp, IrInstGenErrWrapPayload *instruction) { fprintf(irp->f, "@errWrapPayload("); - ir_print_other_instruction(irp, instruction->operand); + ir_print_other_inst_gen(irp, instruction->operand); fprintf(irp->f, ")result="); - ir_print_other_instruction(irp, instruction->result_loc); + ir_print_other_inst_gen(irp, instruction->result_loc); } -static void ir_print_fn_proto(IrPrint *irp, IrInstructionFnProto *instruction) { +static void ir_print_fn_proto(IrPrintSrc *irp, IrInstSrcFnProto *instruction) { fprintf(irp->f, "fn("); - for (size_t i = 0; i < instruction->base.source_node->data.fn_proto.params.length; i += 1) { + for (size_t i = 0; i < instruction->base.base.source_node->data.fn_proto.params.length; i += 1) { if (i != 0) fprintf(irp->f, ","); - if (instruction->is_var_args && i == instruction->base.source_node->data.fn_proto.params.length - 1) { + if (instruction->is_var_args && i == instruction->base.base.source_node->data.fn_proto.params.length - 1) { fprintf(irp->f, "..."); } else { - ir_print_other_instruction(irp, instruction->param_types[i]); + ir_print_other_inst_src(irp, instruction->param_types[i]); } } fprintf(irp->f, ")"); if (instruction->align_value != nullptr) { fprintf(irp->f, " align "); - ir_print_other_instruction(irp, instruction->align_value); + ir_print_other_inst_src(irp, instruction->align_value); fprintf(irp->f, " "); } fprintf(irp->f, "->"); - ir_print_other_instruction(irp, instruction->return_type); + ir_print_other_inst_src(irp, instruction->return_type); } -static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *instruction) { +static void ir_print_test_comptime(IrPrintSrc *irp, IrInstSrcTestComptime *instruction) { fprintf(irp->f, "@testComptime("); - ir_print_other_instruction(irp, instruction->value); + ir_print_other_inst_src(irp, instruction->value); fprintf(irp->f, ")"); } -static void ir_print_ptr_cast_src(IrPrint *irp, IrInstructionPtrCastSrc *instruction) { +static void ir_print_ptr_cast_src(IrPrintSrc *irp, IrInstSrcPtrCast *instruction) { fprintf(irp->f, "@ptrCast("); if (instruction->dest_type) { - ir_print_other_instruction(irp, instruction->dest_type); + ir_print_other_inst_src(irp, instruction->dest_type); } fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->ptr); + ir_print_other_inst_src(irp, instruction->ptr); fprintf(irp->f, ")"); } -static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruction) { +static void ir_print_ptr_cast_gen(IrPrintGen *irp, IrInstGenPtrCast *instruction) { fprintf(irp->f, "@ptrCast("); - ir_print_other_instruction(irp, instruction->ptr); + ir_print_other_inst_gen(irp, instruction->ptr); fprintf(irp->f, ")"); } -static void ir_print_implicit_cast(IrPrint *irp, IrInstructionImplicitCast *instruction) { +static void ir_print_implicit_cast(IrPrintSrc *irp, IrInstSrcImplicitCast *instruction) { fprintf(irp->f, "@implicitCast("); - ir_print_other_instruction(irp, instruction->operand); + ir_print_other_inst_src(irp, instruction->operand); fprintf(irp->f, ")result="); ir_print_result_loc(irp, &instruction->result_loc_cast->base); } -static void ir_print_bit_cast_src(IrPrint *irp, IrInstructionBitCastSrc *instruction) { +static void ir_print_bit_cast_src(IrPrintSrc *irp, IrInstSrcBitCast *instruction) { fprintf(irp->f, "@bitCast("); - ir_print_other_instruction(irp, instruction->operand); + ir_print_other_inst_src(irp, instruction->operand); fprintf(irp->f, ")result="); ir_print_result_loc(irp, &instruction->result_loc_bit_cast->base); } -static void ir_print_bit_cast_gen(IrPrint *irp, IrInstructionBitCastGen *instruction) { +static void ir_print_bit_cast_gen(IrPrintGen *irp, IrInstGenBitCast *instruction) { fprintf(irp->f, "@bitCast("); - ir_print_other_instruction(irp, instruction->operand); + ir_print_other_inst_gen(irp, instruction->operand); fprintf(irp->f, ")"); } -static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) { +static void ir_print_widen_or_shorten(IrPrintGen *irp, IrInstGenWidenOrShorten *instruction) { fprintf(irp->f, "WidenOrShorten("); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_gen(irp, instruction->target); fprintf(irp->f, ")"); } -static void ir_print_ptr_to_int(IrPrint *irp, IrInstructionPtrToInt *instruction) { +static void ir_print_ptr_to_int(IrPrintSrc *irp, IrInstSrcPtrToInt *instruction) { fprintf(irp->f, "@ptrToInt("); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_src(irp, instruction->target); fprintf(irp->f, ")"); } -static void ir_print_int_to_ptr(IrPrint *irp, IrInstructionIntToPtr *instruction) { +static void ir_print_ptr_to_int(IrPrintGen *irp, IrInstGenPtrToInt *instruction) { + fprintf(irp->f, "@ptrToInt("); + ir_print_other_inst_gen(irp, instruction->target); + fprintf(irp->f, ")"); +} + +static void ir_print_int_to_ptr(IrPrintSrc *irp, IrInstSrcIntToPtr *instruction) { fprintf(irp->f, "@intToPtr("); - if (instruction->dest_type == nullptr) { - fprintf(irp->f, "(null)"); - } else { - ir_print_other_instruction(irp, instruction->dest_type); - } + ir_print_other_inst_src(irp, instruction->dest_type); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_src(irp, instruction->target); fprintf(irp->f, ")"); } -static void ir_print_int_to_enum(IrPrint *irp, IrInstructionIntToEnum *instruction) { +static void ir_print_int_to_ptr(IrPrintGen *irp, IrInstGenIntToPtr *instruction) { + fprintf(irp->f, "@intToPtr("); + ir_print_other_inst_gen(irp, instruction->target); + fprintf(irp->f, ")"); +} + +static void ir_print_int_to_enum(IrPrintSrc *irp, IrInstSrcIntToEnum *instruction) { fprintf(irp->f, "@intToEnum("); - if (instruction->dest_type == nullptr) { - fprintf(irp->f, "(null)"); - } else { - ir_print_other_instruction(irp, instruction->dest_type); - } - ir_print_other_instruction(irp, instruction->target); - fprintf(irp->f, ")"); -} - -static void ir_print_enum_to_int(IrPrint *irp, IrInstructionEnumToInt *instruction) { - fprintf(irp->f, "@enumToInt("); - ir_print_other_instruction(irp, instruction->target); - fprintf(irp->f, ")"); -} - -static void ir_print_check_runtime_scope(IrPrint *irp, IrInstructionCheckRuntimeScope *instruction) { - fprintf(irp->f, "@checkRuntimeScope("); - ir_print_other_instruction(irp, instruction->scope_is_comptime); + ir_print_other_inst_src(irp, instruction->dest_type); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->is_comptime); + ir_print_other_inst_src(irp, instruction->target); fprintf(irp->f, ")"); } -static void ir_print_array_to_vector(IrPrint *irp, IrInstructionArrayToVector *instruction) { +static void ir_print_int_to_enum(IrPrintGen *irp, IrInstGenIntToEnum *instruction) { + fprintf(irp->f, "@intToEnum("); + ir_print_other_inst_gen(irp, instruction->target); + fprintf(irp->f, ")"); +} + +static void ir_print_enum_to_int(IrPrintSrc *irp, IrInstSrcEnumToInt *instruction) { + fprintf(irp->f, "@enumToInt("); + ir_print_other_inst_src(irp, instruction->target); + fprintf(irp->f, ")"); +} + +static void ir_print_check_runtime_scope(IrPrintSrc *irp, IrInstSrcCheckRuntimeScope *instruction) { + fprintf(irp->f, "@checkRuntimeScope("); + ir_print_other_inst_src(irp, instruction->scope_is_comptime); + fprintf(irp->f, ","); + ir_print_other_inst_src(irp, instruction->is_comptime); + fprintf(irp->f, ")"); +} + +static void ir_print_array_to_vector(IrPrintGen *irp, IrInstGenArrayToVector *instruction) { fprintf(irp->f, "ArrayToVector("); - ir_print_other_instruction(irp, instruction->array); + ir_print_other_inst_gen(irp, instruction->array); fprintf(irp->f, ")"); } -static void ir_print_vector_to_array(IrPrint *irp, IrInstructionVectorToArray *instruction) { +static void ir_print_vector_to_array(IrPrintGen *irp, IrInstGenVectorToArray *instruction) { fprintf(irp->f, "VectorToArray("); - ir_print_other_instruction(irp, instruction->vector); + ir_print_other_inst_gen(irp, instruction->vector); fprintf(irp->f, ")result="); - ir_print_other_instruction(irp, instruction->result_loc); + ir_print_other_inst_gen(irp, instruction->result_loc); } -static void ir_print_ptr_of_array_to_slice(IrPrint *irp, IrInstructionPtrOfArrayToSlice *instruction) { +static void ir_print_ptr_of_array_to_slice(IrPrintGen *irp, IrInstGenPtrOfArrayToSlice *instruction) { fprintf(irp->f, "PtrOfArrayToSlice("); - ir_print_other_instruction(irp, instruction->operand); + ir_print_other_inst_gen(irp, instruction->operand); fprintf(irp->f, ")result="); - ir_print_other_instruction(irp, instruction->result_loc); + ir_print_other_inst_gen(irp, instruction->result_loc); } -static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruction) { +static void ir_print_assert_zero(IrPrintGen *irp, IrInstGenAssertZero *instruction) { fprintf(irp->f, "AssertZero("); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_gen(irp, instruction->target); fprintf(irp->f, ")"); } -static void ir_print_assert_non_null(IrPrint *irp, IrInstructionAssertNonNull *instruction) { +static void ir_print_assert_non_null(IrPrintGen *irp, IrInstGenAssertNonNull *instruction) { fprintf(irp->f, "AssertNonNull("); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_gen(irp, instruction->target); fprintf(irp->f, ")"); } -static void ir_print_resize_slice(IrPrint *irp, IrInstructionResizeSlice *instruction) { +static void ir_print_resize_slice(IrPrintGen *irp, IrInstGenResizeSlice *instruction) { fprintf(irp->f, "@resizeSlice("); - ir_print_other_instruction(irp, instruction->operand); + ir_print_other_inst_gen(irp, instruction->operand); fprintf(irp->f, ")result="); - ir_print_other_instruction(irp, instruction->result_loc); + ir_print_other_inst_gen(irp, instruction->result_loc); } -static void ir_print_alloca_src(IrPrint *irp, IrInstructionAllocaSrc *instruction) { +static void ir_print_alloca_src(IrPrintSrc *irp, IrInstSrcAlloca *instruction) { fprintf(irp->f, "Alloca(align="); - ir_print_other_instruction(irp, instruction->align); + ir_print_other_inst_src(irp, instruction->align); fprintf(irp->f, ",name=%s)", instruction->name_hint); } -static void ir_print_alloca_gen(IrPrint *irp, IrInstructionAllocaGen *instruction) { +static void ir_print_alloca_gen(IrPrintGen *irp, IrInstGenAlloca *instruction) { fprintf(irp->f, "Alloca(align=%" PRIu32 ",name=%s)", instruction->align, instruction->name_hint); } -static void ir_print_end_expr(IrPrint *irp, IrInstructionEndExpr *instruction) { +static void ir_print_end_expr(IrPrintSrc *irp, IrInstSrcEndExpr *instruction) { fprintf(irp->f, "EndExpr(result="); ir_print_result_loc(irp, instruction->result_loc); fprintf(irp->f, ",value="); - ir_print_other_instruction(irp, instruction->value); + ir_print_other_inst_src(irp, instruction->value); fprintf(irp->f, ")"); } -static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) { +static void ir_print_int_to_err(IrPrintSrc *irp, IrInstSrcIntToErr *instruction) { fprintf(irp->f, "inttoerr "); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_src(irp, instruction->target); } -static void ir_print_err_to_int(IrPrint *irp, IrInstructionErrToInt *instruction) { +static void ir_print_int_to_err(IrPrintGen *irp, IrInstGenIntToErr *instruction) { + fprintf(irp->f, "inttoerr "); + ir_print_other_inst_gen(irp, instruction->target); +} + +static void ir_print_err_to_int(IrPrintSrc *irp, IrInstSrcErrToInt *instruction) { fprintf(irp->f, "errtoint "); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_src(irp, instruction->target); } -static void ir_print_check_switch_prongs(IrPrint *irp, IrInstructionCheckSwitchProngs *instruction) { +static void ir_print_err_to_int(IrPrintGen *irp, IrInstGenErrToInt *instruction) { + fprintf(irp->f, "errtoint "); + ir_print_other_inst_gen(irp, instruction->target); +} + +static void ir_print_check_switch_prongs(IrPrintSrc *irp, IrInstSrcCheckSwitchProngs *instruction) { fprintf(irp->f, "@checkSwitchProngs("); - ir_print_other_instruction(irp, instruction->target_value); + ir_print_other_inst_src(irp, instruction->target_value); fprintf(irp->f, ","); for (size_t i = 0; i < instruction->range_count; i += 1) { if (i != 0) fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->ranges[i].start); + ir_print_other_inst_src(irp, instruction->ranges[i].start); fprintf(irp->f, "..."); - ir_print_other_instruction(irp, instruction->ranges[i].end); + ir_print_other_inst_src(irp, instruction->ranges[i].end); } const char *have_else_str = instruction->have_else_prong ? "yes" : "no"; fprintf(irp->f, ")else:%s", have_else_str); } -static void ir_print_check_statement_is_void(IrPrint *irp, IrInstructionCheckStatementIsVoid *instruction) { +static void ir_print_check_statement_is_void(IrPrintSrc *irp, IrInstSrcCheckStatementIsVoid *instruction) { fprintf(irp->f, "@checkStatementIsVoid("); - ir_print_other_instruction(irp, instruction->statement_value); + ir_print_other_inst_src(irp, instruction->statement_value); fprintf(irp->f, ")"); } -static void ir_print_type_name(IrPrint *irp, IrInstructionTypeName *instruction) { +static void ir_print_type_name(IrPrintSrc *irp, IrInstSrcTypeName *instruction) { fprintf(irp->f, "typename "); - ir_print_other_instruction(irp, instruction->type_value); + ir_print_other_inst_src(irp, instruction->type_value); } -static void ir_print_tag_name(IrPrint *irp, IrInstructionTagName *instruction) { +static void ir_print_tag_name(IrPrintSrc *irp, IrInstSrcTagName *instruction) { fprintf(irp->f, "tagname "); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_src(irp, instruction->target); } -static void ir_print_ptr_type(IrPrint *irp, IrInstructionPtrType *instruction) { +static void ir_print_tag_name(IrPrintGen *irp, IrInstGenTagName *instruction) { + fprintf(irp->f, "tagname "); + ir_print_other_inst_gen(irp, instruction->target); +} + +static void ir_print_ptr_type(IrPrintSrc *irp, IrInstSrcPtrType *instruction) { fprintf(irp->f, "&"); if (instruction->align_value != nullptr) { fprintf(irp->f, "align("); - ir_print_other_instruction(irp, instruction->align_value); + ir_print_other_inst_src(irp, instruction->align_value); fprintf(irp->f, ")"); } const char *const_str = instruction->is_const ? "const " : ""; const char *volatile_str = instruction->is_volatile ? "volatile " : ""; fprintf(irp->f, ":%" PRIu32 ":%" PRIu32 " %s%s", instruction->bit_offset_start, instruction->host_int_bytes, const_str, volatile_str); - ir_print_other_instruction(irp, instruction->child_type); + ir_print_other_inst_src(irp, instruction->child_type); } -static void ir_print_decl_ref(IrPrint *irp, IrInstructionDeclRef *instruction) { +static void ir_print_decl_ref(IrPrintSrc *irp, IrInstSrcDeclRef *instruction) { const char *ptr_str = (instruction->lval == LValPtr) ? "ptr " : ""; fprintf(irp->f, "declref %s%s", ptr_str, buf_ptr(instruction->tld->name)); } -static void ir_print_panic(IrPrint *irp, IrInstructionPanic *instruction) { +static void ir_print_panic(IrPrintSrc *irp, IrInstSrcPanic *instruction) { fprintf(irp->f, "@panic("); - ir_print_other_instruction(irp, instruction->msg); + ir_print_other_inst_src(irp, instruction->msg); fprintf(irp->f, ")"); } -static void ir_print_field_parent_ptr(IrPrint *irp, IrInstructionFieldParentPtr *instruction) { +static void ir_print_panic(IrPrintGen *irp, IrInstGenPanic *instruction) { + fprintf(irp->f, "@panic("); + ir_print_other_inst_gen(irp, instruction->msg); + fprintf(irp->f, ")"); +} + +static void ir_print_field_parent_ptr(IrPrintSrc *irp, IrInstSrcFieldParentPtr *instruction) { fprintf(irp->f, "@fieldParentPtr("); - ir_print_other_instruction(irp, instruction->type_value); + ir_print_other_inst_src(irp, instruction->type_value); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->field_name); + ir_print_other_inst_src(irp, instruction->field_name); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->field_ptr); + ir_print_other_inst_src(irp, instruction->field_ptr); fprintf(irp->f, ")"); } -static void ir_print_byte_offset_of(IrPrint *irp, IrInstructionByteOffsetOf *instruction) { +static void ir_print_field_parent_ptr(IrPrintGen *irp, IrInstGenFieldParentPtr *instruction) { + fprintf(irp->f, "@fieldParentPtr(%s,", buf_ptr(instruction->field->name)); + ir_print_other_inst_gen(irp, instruction->field_ptr); + fprintf(irp->f, ")"); +} + +static void ir_print_byte_offset_of(IrPrintSrc *irp, IrInstSrcByteOffsetOf *instruction) { fprintf(irp->f, "@byte_offset_of("); - ir_print_other_instruction(irp, instruction->type_value); + ir_print_other_inst_src(irp, instruction->type_value); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->field_name); + ir_print_other_inst_src(irp, instruction->field_name); fprintf(irp->f, ")"); } -static void ir_print_bit_offset_of(IrPrint *irp, IrInstructionBitOffsetOf *instruction) { +static void ir_print_bit_offset_of(IrPrintSrc *irp, IrInstSrcBitOffsetOf *instruction) { fprintf(irp->f, "@bit_offset_of("); - ir_print_other_instruction(irp, instruction->type_value); + ir_print_other_inst_src(irp, instruction->type_value); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->field_name); + ir_print_other_inst_src(irp, instruction->field_name); fprintf(irp->f, ")"); } -static void ir_print_type_info(IrPrint *irp, IrInstructionTypeInfo *instruction) { +static void ir_print_type_info(IrPrintSrc *irp, IrInstSrcTypeInfo *instruction) { fprintf(irp->f, "@typeInfo("); - ir_print_other_instruction(irp, instruction->type_value); + ir_print_other_inst_src(irp, instruction->type_value); fprintf(irp->f, ")"); } -static void ir_print_type(IrPrint *irp, IrInstructionType *instruction) { +static void ir_print_type(IrPrintSrc *irp, IrInstSrcType *instruction) { fprintf(irp->f, "@Type("); - ir_print_other_instruction(irp, instruction->type_info); + ir_print_other_inst_src(irp, instruction->type_info); fprintf(irp->f, ")"); } -static void ir_print_has_field(IrPrint *irp, IrInstructionHasField *instruction) { +static void ir_print_has_field(IrPrintSrc *irp, IrInstSrcHasField *instruction) { fprintf(irp->f, "@hasField("); - ir_print_other_instruction(irp, instruction->container_type); + ir_print_other_inst_src(irp, instruction->container_type); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->field_name); + ir_print_other_inst_src(irp, instruction->field_name); fprintf(irp->f, ")"); } -static void ir_print_type_id(IrPrint *irp, IrInstructionTypeId *instruction) { +static void ir_print_type_id(IrPrintSrc *irp, IrInstSrcTypeId *instruction) { fprintf(irp->f, "@typeId("); - ir_print_other_instruction(irp, instruction->type_value); + ir_print_other_inst_src(irp, instruction->type_value); fprintf(irp->f, ")"); } -static void ir_print_set_eval_branch_quota(IrPrint *irp, IrInstructionSetEvalBranchQuota *instruction) { +static void ir_print_set_eval_branch_quota(IrPrintSrc *irp, IrInstSrcSetEvalBranchQuota *instruction) { fprintf(irp->f, "@setEvalBranchQuota("); - ir_print_other_instruction(irp, instruction->new_quota); + ir_print_other_inst_src(irp, instruction->new_quota); fprintf(irp->f, ")"); } -static void ir_print_align_cast(IrPrint *irp, IrInstructionAlignCast *instruction) { +static void ir_print_align_cast(IrPrintSrc *irp, IrInstSrcAlignCast *instruction) { fprintf(irp->f, "@alignCast("); - if (instruction->align_bytes == nullptr) { - fprintf(irp->f, "null"); - } else { - ir_print_other_instruction(irp, instruction->align_bytes); - } + ir_print_other_inst_src(irp, instruction->align_bytes); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_src(irp, instruction->target); fprintf(irp->f, ")"); } -static void ir_print_resolve_result(IrPrint *irp, IrInstructionResolveResult *instruction) { +static void ir_print_align_cast(IrPrintGen *irp, IrInstGenAlignCast *instruction) { + fprintf(irp->f, "@alignCast("); + ir_print_other_inst_gen(irp, instruction->target); + fprintf(irp->f, ")"); +} + +static void ir_print_resolve_result(IrPrintSrc *irp, IrInstSrcResolveResult *instruction) { fprintf(irp->f, "ResolveResult("); ir_print_result_loc(irp, instruction->result_loc); fprintf(irp->f, ")"); } -static void ir_print_reset_result(IrPrint *irp, IrInstructionResetResult *instruction) { +static void ir_print_reset_result(IrPrintSrc *irp, IrInstSrcResetResult *instruction) { fprintf(irp->f, "ResetResult("); ir_print_result_loc(irp, instruction->result_loc); fprintf(irp->f, ")"); } -static void ir_print_opaque_type(IrPrint *irp, IrInstructionOpaqueType *instruction) { +static void ir_print_opaque_type(IrPrintSrc *irp, IrInstSrcOpaqueType *instruction) { fprintf(irp->f, "@OpaqueType()"); } -static void ir_print_set_align_stack(IrPrint *irp, IrInstructionSetAlignStack *instruction) { +static void ir_print_set_align_stack(IrPrintSrc *irp, IrInstSrcSetAlignStack *instruction) { fprintf(irp->f, "@setAlignStack("); - ir_print_other_instruction(irp, instruction->align_bytes); + ir_print_other_inst_src(irp, instruction->align_bytes); fprintf(irp->f, ")"); } -static void ir_print_arg_type(IrPrint *irp, IrInstructionArgType *instruction) { +static void ir_print_arg_type(IrPrintSrc *irp, IrInstSrcArgType *instruction) { fprintf(irp->f, "@ArgType("); - ir_print_other_instruction(irp, instruction->fn_type); + ir_print_other_inst_src(irp, instruction->fn_type); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->arg_index); + ir_print_other_inst_src(irp, instruction->arg_index); fprintf(irp->f, ")"); } -static void ir_print_enum_tag_type(IrPrint *irp, IrInstructionTagType *instruction) { +static void ir_print_enum_tag_type(IrPrintSrc *irp, IrInstSrcTagType *instruction) { fprintf(irp->f, "@TagType("); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_src(irp, instruction->target); fprintf(irp->f, ")"); } -static void ir_print_export(IrPrint *irp, IrInstructionExport *instruction) { +static void ir_print_export(IrPrintSrc *irp, IrInstSrcExport *instruction) { fprintf(irp->f, "@export("); - ir_print_other_instruction(irp, instruction->target); + ir_print_other_inst_src(irp, instruction->target); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->options); + ir_print_other_inst_src(irp, instruction->options); fprintf(irp->f, ")"); } -static void ir_print_error_return_trace(IrPrint *irp, IrInstructionErrorReturnTrace *instruction) { +static void ir_print_error_return_trace(IrPrintSrc *irp, IrInstSrcErrorReturnTrace *instruction) { fprintf(irp->f, "@errorReturnTrace("); switch (instruction->optional) { - case IrInstructionErrorReturnTrace::Null: + case IrInstErrorReturnTraceNull: fprintf(irp->f, "Null"); break; - case IrInstructionErrorReturnTrace::NonNull: + case IrInstErrorReturnTraceNonNull: fprintf(irp->f, "NonNull"); break; } fprintf(irp->f, ")"); } -static void ir_print_error_union(IrPrint *irp, IrInstructionErrorUnion *instruction) { - ir_print_other_instruction(irp, instruction->err_set); +static void ir_print_error_return_trace(IrPrintGen *irp, IrInstGenErrorReturnTrace *instruction) { + fprintf(irp->f, "@errorReturnTrace("); + switch (instruction->optional) { + case IrInstErrorReturnTraceNull: + fprintf(irp->f, "Null"); + break; + case IrInstErrorReturnTraceNonNull: + fprintf(irp->f, "NonNull"); + break; + } + fprintf(irp->f, ")"); +} + +static void ir_print_error_union(IrPrintSrc *irp, IrInstSrcErrorUnion *instruction) { + ir_print_other_inst_src(irp, instruction->err_set); fprintf(irp->f, "!"); - ir_print_other_instruction(irp, instruction->payload); + ir_print_other_inst_src(irp, instruction->payload); } -static void ir_print_atomic_rmw(IrPrint *irp, IrInstructionAtomicRmw *instruction) { +static void ir_print_atomic_rmw(IrPrintSrc *irp, IrInstSrcAtomicRmw *instruction) { fprintf(irp->f, "@atomicRmw("); - if (instruction->operand_type != nullptr) { - ir_print_other_instruction(irp, instruction->operand_type); - } else { - fprintf(irp->f, "[TODO print]"); - } + ir_print_other_inst_src(irp, instruction->operand_type); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->ptr); + ir_print_other_inst_src(irp, instruction->ptr); fprintf(irp->f, ","); - if (instruction->op != nullptr) { - ir_print_other_instruction(irp, instruction->op); - } else { - fprintf(irp->f, "[TODO print]"); - } + ir_print_other_inst_src(irp, instruction->op); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->operand); + ir_print_other_inst_src(irp, instruction->operand); fprintf(irp->f, ","); - if (instruction->ordering != nullptr) { - ir_print_other_instruction(irp, instruction->ordering); - } else { - fprintf(irp->f, "[TODO print]"); - } + ir_print_other_inst_src(irp, instruction->ordering); fprintf(irp->f, ")"); } -static void ir_print_atomic_load(IrPrint *irp, IrInstructionAtomicLoad *instruction) { +static void ir_print_atomic_rmw(IrPrintGen *irp, IrInstGenAtomicRmw *instruction) { + fprintf(irp->f, "@atomicRmw("); + ir_print_other_inst_gen(irp, instruction->ptr); + fprintf(irp->f, ",[TODO print op],"); + ir_print_other_inst_gen(irp, instruction->operand); + fprintf(irp->f, ",%s)", atomic_order_str(instruction->ordering)); +} + +static void ir_print_atomic_load(IrPrintSrc *irp, IrInstSrcAtomicLoad *instruction) { fprintf(irp->f, "@atomicLoad("); - if (instruction->operand_type != nullptr) { - ir_print_other_instruction(irp, instruction->operand_type); - } else { - fprintf(irp->f, "[TODO print]"); - } + ir_print_other_inst_src(irp, instruction->operand_type); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->ptr); + ir_print_other_inst_src(irp, instruction->ptr); fprintf(irp->f, ","); - if (instruction->ordering != nullptr) { - ir_print_other_instruction(irp, instruction->ordering); - } else { - fprintf(irp->f, "[TODO print]"); - } + ir_print_other_inst_src(irp, instruction->ordering); fprintf(irp->f, ")"); } -static void ir_print_atomic_store(IrPrint *irp, IrInstructionAtomicStore *instruction) { +static void ir_print_atomic_load(IrPrintGen *irp, IrInstGenAtomicLoad *instruction) { + fprintf(irp->f, "@atomicLoad("); + ir_print_other_inst_gen(irp, instruction->ptr); + fprintf(irp->f, ",%s)", atomic_order_str(instruction->ordering)); +} + +static void ir_print_atomic_store(IrPrintSrc *irp, IrInstSrcAtomicStore *instruction) { fprintf(irp->f, "@atomicStore("); - if (instruction->operand_type != nullptr) { - ir_print_other_instruction(irp, instruction->operand_type); - } else { - fprintf(irp->f, "[TODO print]"); - } + ir_print_other_inst_src(irp, instruction->operand_type); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->ptr); + ir_print_other_inst_src(irp, instruction->ptr); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->value); + ir_print_other_inst_src(irp, instruction->value); fprintf(irp->f, ","); - if (instruction->ordering != nullptr) { - ir_print_other_instruction(irp, instruction->ordering); - } else { - fprintf(irp->f, "[TODO print]"); - } + ir_print_other_inst_src(irp, instruction->ordering); fprintf(irp->f, ")"); } +static void ir_print_atomic_store(IrPrintGen *irp, IrInstGenAtomicStore *instruction) { + fprintf(irp->f, "@atomicStore("); + ir_print_other_inst_gen(irp, instruction->ptr); + fprintf(irp->f, ","); + ir_print_other_inst_gen(irp, instruction->value); + fprintf(irp->f, ",%s)", atomic_order_str(instruction->ordering)); +} -static void ir_print_save_err_ret_addr(IrPrint *irp, IrInstructionSaveErrRetAddr *instruction) { + +static void ir_print_save_err_ret_addr(IrPrintSrc *irp, IrInstSrcSaveErrRetAddr *instruction) { fprintf(irp->f, "@saveErrRetAddr()"); } -static void ir_print_add_implicit_return_type(IrPrint *irp, IrInstructionAddImplicitReturnType *instruction) { +static void ir_print_save_err_ret_addr(IrPrintGen *irp, IrInstGenSaveErrRetAddr *instruction) { + fprintf(irp->f, "@saveErrRetAddr()"); +} + +static void ir_print_add_implicit_return_type(IrPrintSrc *irp, IrInstSrcAddImplicitReturnType *instruction) { fprintf(irp->f, "@addImplicitReturnType("); - ir_print_other_instruction(irp, instruction->value); + ir_print_other_inst_src(irp, instruction->value); fprintf(irp->f, ")"); } -static void ir_print_float_op(IrPrint *irp, IrInstructionFloatOp *instruction) { +static void ir_print_float_op(IrPrintSrc *irp, IrInstSrcFloatOp *instruction) { fprintf(irp->f, "@%s(", float_op_to_name(instruction->fn_id)); - ir_print_other_instruction(irp, instruction->operand); + ir_print_other_inst_src(irp, instruction->operand); fprintf(irp->f, ")"); } -static void ir_print_mul_add(IrPrint *irp, IrInstructionMulAdd *instruction) { +static void ir_print_float_op(IrPrintGen *irp, IrInstGenFloatOp *instruction) { + fprintf(irp->f, "@%s(", float_op_to_name(instruction->fn_id)); + ir_print_other_inst_gen(irp, instruction->operand); + fprintf(irp->f, ")"); +} + +static void ir_print_mul_add(IrPrintSrc *irp, IrInstSrcMulAdd *instruction) { fprintf(irp->f, "@mulAdd("); - if (instruction->type_value != nullptr) { - ir_print_other_instruction(irp, instruction->type_value); - } else { - fprintf(irp->f, "null"); - } + ir_print_other_inst_src(irp, instruction->type_value); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->op1); + ir_print_other_inst_src(irp, instruction->op1); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->op2); + ir_print_other_inst_src(irp, instruction->op2); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->op3); + ir_print_other_inst_src(irp, instruction->op3); fprintf(irp->f, ")"); } -static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_var_instruction) { +static void ir_print_mul_add(IrPrintGen *irp, IrInstGenMulAdd *instruction) { + fprintf(irp->f, "@mulAdd("); + ir_print_other_inst_gen(irp, instruction->op1); + fprintf(irp->f, ","); + ir_print_other_inst_gen(irp, instruction->op2); + fprintf(irp->f, ","); + ir_print_other_inst_gen(irp, instruction->op3); + fprintf(irp->f, ")"); +} + +static void ir_print_decl_var_gen(IrPrintGen *irp, IrInstGenDeclVar *decl_var_instruction) { ZigVar *var = decl_var_instruction->var; const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var"; const char *name = decl_var_instruction->var->name; fprintf(irp->f, "%s %s: %s align(%u) = ", var_or_const, name, buf_ptr(&var->var_type->name), var->align_bytes); - ir_print_other_instruction(irp, decl_var_instruction->var_ptr); - if (decl_var_instruction->var->is_comptime != nullptr) { - fprintf(irp->f, " // comptime = "); - ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime); - } + ir_print_other_inst_gen(irp, decl_var_instruction->var_ptr); } -static void ir_print_has_decl(IrPrint *irp, IrInstructionHasDecl *instruction) { +static void ir_print_has_decl(IrPrintSrc *irp, IrInstSrcHasDecl *instruction) { fprintf(irp->f, "@hasDecl("); - ir_print_other_instruction(irp, instruction->container); + ir_print_other_inst_src(irp, instruction->container); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->name); + ir_print_other_inst_src(irp, instruction->name); fprintf(irp->f, ")"); } -static void ir_print_undeclared_ident(IrPrint *irp, IrInstructionUndeclaredIdent *instruction) { +static void ir_print_undeclared_ident(IrPrintSrc *irp, IrInstSrcUndeclaredIdent *instruction) { fprintf(irp->f, "@undeclaredIdent(%s)", buf_ptr(instruction->name)); } -static void ir_print_union_init_named_field(IrPrint *irp, IrInstructionUnionInitNamedField *instruction) { +static void ir_print_union_init_named_field(IrPrintSrc *irp, IrInstSrcUnionInitNamedField *instruction) { fprintf(irp->f, "@unionInit("); - ir_print_other_instruction(irp, instruction->union_type); + ir_print_other_inst_src(irp, instruction->union_type); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->field_name); + ir_print_other_inst_src(irp, instruction->field_name); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->field_result_loc); + ir_print_other_inst_src(irp, instruction->field_result_loc); fprintf(irp->f, ", "); - ir_print_other_instruction(irp, instruction->result_loc); + ir_print_other_inst_src(irp, instruction->result_loc); fprintf(irp->f, ")"); } -static void ir_print_suspend_begin(IrPrint *irp, IrInstructionSuspendBegin *instruction) { +static void ir_print_suspend_begin(IrPrintSrc *irp, IrInstSrcSuspendBegin *instruction) { fprintf(irp->f, "@suspendBegin()"); } -static void ir_print_suspend_finish(IrPrint *irp, IrInstructionSuspendFinish *instruction) { +static void ir_print_suspend_begin(IrPrintGen *irp, IrInstGenSuspendBegin *instruction) { + fprintf(irp->f, "@suspendBegin()"); +} + +static void ir_print_suspend_finish(IrPrintSrc *irp, IrInstSrcSuspendFinish *instruction) { fprintf(irp->f, "@suspendFinish()"); } -static void ir_print_resume(IrPrint *irp, IrInstructionResume *instruction) { - fprintf(irp->f, "resume "); - ir_print_other_instruction(irp, instruction->frame); +static void ir_print_suspend_finish(IrPrintGen *irp, IrInstGenSuspendFinish *instruction) { + fprintf(irp->f, "@suspendFinish()"); } -static void ir_print_await_src(IrPrint *irp, IrInstructionAwaitSrc *instruction) { +static void ir_print_resume(IrPrintSrc *irp, IrInstSrcResume *instruction) { + fprintf(irp->f, "resume "); + ir_print_other_inst_src(irp, instruction->frame); +} + +static void ir_print_resume(IrPrintGen *irp, IrInstGenResume *instruction) { + fprintf(irp->f, "resume "); + ir_print_other_inst_gen(irp, instruction->frame); +} + +static void ir_print_await_src(IrPrintSrc *irp, IrInstSrcAwait *instruction) { fprintf(irp->f, "@await("); - ir_print_other_instruction(irp, instruction->frame); + ir_print_other_inst_src(irp, instruction->frame); fprintf(irp->f, ","); ir_print_result_loc(irp, instruction->result_loc); fprintf(irp->f, ")"); } -static void ir_print_await_gen(IrPrint *irp, IrInstructionAwaitGen *instruction) { +static void ir_print_await_gen(IrPrintGen *irp, IrInstGenAwait *instruction) { fprintf(irp->f, "@await("); - ir_print_other_instruction(irp, instruction->frame); + ir_print_other_inst_gen(irp, instruction->frame); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->result_loc); + ir_print_other_inst_gen(irp, instruction->result_loc); fprintf(irp->f, ")"); } -static void ir_print_spill_begin(IrPrint *irp, IrInstructionSpillBegin *instruction) { +static void ir_print_spill_begin(IrPrintSrc *irp, IrInstSrcSpillBegin *instruction) { fprintf(irp->f, "@spillBegin("); - ir_print_other_instruction(irp, instruction->operand); + ir_print_other_inst_src(irp, instruction->operand); fprintf(irp->f, ")"); } -static void ir_print_spill_end(IrPrint *irp, IrInstructionSpillEnd *instruction) { +static void ir_print_spill_begin(IrPrintGen *irp, IrInstGenSpillBegin *instruction) { + fprintf(irp->f, "@spillBegin("); + ir_print_other_inst_gen(irp, instruction->operand); + fprintf(irp->f, ")"); +} + +static void ir_print_spill_end(IrPrintSrc *irp, IrInstSrcSpillEnd *instruction) { fprintf(irp->f, "@spillEnd("); - ir_print_other_instruction(irp, &instruction->begin->base); + ir_print_other_inst_src(irp, &instruction->begin->base); fprintf(irp->f, ")"); } -static void ir_print_vector_extract_elem(IrPrint *irp, IrInstructionVectorExtractElem *instruction) { +static void ir_print_spill_end(IrPrintGen *irp, IrInstGenSpillEnd *instruction) { + fprintf(irp->f, "@spillEnd("); + ir_print_other_inst_gen(irp, &instruction->begin->base); + fprintf(irp->f, ")"); +} + +static void ir_print_vector_extract_elem(IrPrintGen *irp, IrInstGenVectorExtractElem *instruction) { fprintf(irp->f, "@vectorExtractElem("); - ir_print_other_instruction(irp, instruction->vector); + ir_print_other_inst_gen(irp, instruction->vector); fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->index); + ir_print_other_inst_gen(irp, instruction->index); fprintf(irp->f, ")"); } -static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool trailing) { - ir_print_prefix(irp, instruction, trailing); +static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trailing) { + ir_print_prefix_src(irp, instruction, trailing); switch (instruction->id) { - case IrInstructionIdInvalid: + case IrInstSrcIdInvalid: zig_unreachable(); - case IrInstructionIdReturn: - ir_print_return(irp, (IrInstructionReturn *)instruction); + case IrInstSrcIdReturn: + ir_print_return_src(irp, (IrInstSrcReturn *)instruction); break; - case IrInstructionIdConst: - ir_print_const(irp, (IrInstructionConst *)instruction); + case IrInstSrcIdConst: + ir_print_const(irp, (IrInstSrcConst *)instruction); break; - case IrInstructionIdBinOp: - ir_print_bin_op(irp, (IrInstructionBinOp *)instruction); + case IrInstSrcIdBinOp: + ir_print_bin_op(irp, (IrInstSrcBinOp *)instruction); break; - case IrInstructionIdMergeErrSets: - ir_print_merge_err_sets(irp, (IrInstructionMergeErrSets *)instruction); + case IrInstSrcIdMergeErrSets: + ir_print_merge_err_sets(irp, (IrInstSrcMergeErrSets *)instruction); break; - case IrInstructionIdDeclVarSrc: - ir_print_decl_var_src(irp, (IrInstructionDeclVarSrc *)instruction); + case IrInstSrcIdDeclVar: + ir_print_decl_var_src(irp, (IrInstSrcDeclVar *)instruction); break; - case IrInstructionIdCast: - ir_print_cast(irp, (IrInstructionCast *)instruction); + case IrInstSrcIdCallExtra: + ir_print_call_extra(irp, (IrInstSrcCallExtra *)instruction); break; - case IrInstructionIdCallExtra: - ir_print_call_extra(irp, (IrInstructionCallExtra *)instruction); + case IrInstSrcIdCall: + ir_print_call_src(irp, (IrInstSrcCall *)instruction); break; - case IrInstructionIdCallSrc: - ir_print_call_src(irp, (IrInstructionCallSrc *)instruction); + case IrInstSrcIdCallArgs: + ir_print_call_args(irp, (IrInstSrcCallArgs *)instruction); break; - case IrInstructionIdCallSrcArgs: - ir_print_call_src_args(irp, (IrInstructionCallSrcArgs *)instruction); + case IrInstSrcIdUnOp: + ir_print_un_op(irp, (IrInstSrcUnOp *)instruction); break; - case IrInstructionIdCallGen: - ir_print_call_gen(irp, (IrInstructionCallGen *)instruction); + case IrInstSrcIdCondBr: + ir_print_cond_br(irp, (IrInstSrcCondBr *)instruction); break; - case IrInstructionIdUnOp: - ir_print_un_op(irp, (IrInstructionUnOp *)instruction); + case IrInstSrcIdBr: + ir_print_br(irp, (IrInstSrcBr *)instruction); break; - case IrInstructionIdCondBr: - ir_print_cond_br(irp, (IrInstructionCondBr *)instruction); + case IrInstSrcIdPhi: + ir_print_phi(irp, (IrInstSrcPhi *)instruction); break; - case IrInstructionIdBr: - ir_print_br(irp, (IrInstructionBr *)instruction); + case IrInstSrcIdContainerInitList: + ir_print_container_init_list(irp, (IrInstSrcContainerInitList *)instruction); break; - case IrInstructionIdPhi: - ir_print_phi(irp, (IrInstructionPhi *)instruction); + case IrInstSrcIdContainerInitFields: + ir_print_container_init_fields(irp, (IrInstSrcContainerInitFields *)instruction); break; - case IrInstructionIdContainerInitList: - ir_print_container_init_list(irp, (IrInstructionContainerInitList *)instruction); + case IrInstSrcIdUnreachable: + ir_print_unreachable(irp, (IrInstSrcUnreachable *)instruction); break; - case IrInstructionIdContainerInitFields: - ir_print_container_init_fields(irp, (IrInstructionContainerInitFields *)instruction); + case IrInstSrcIdElemPtr: + ir_print_elem_ptr(irp, (IrInstSrcElemPtr *)instruction); break; - case IrInstructionIdUnreachable: - ir_print_unreachable(irp, (IrInstructionUnreachable *)instruction); + case IrInstSrcIdVarPtr: + ir_print_var_ptr(irp, (IrInstSrcVarPtr *)instruction); break; - case IrInstructionIdElemPtr: - ir_print_elem_ptr(irp, (IrInstructionElemPtr *)instruction); + case IrInstSrcIdLoadPtr: + ir_print_load_ptr(irp, (IrInstSrcLoadPtr *)instruction); break; - case IrInstructionIdVarPtr: - ir_print_var_ptr(irp, (IrInstructionVarPtr *)instruction); + case IrInstSrcIdStorePtr: + ir_print_store_ptr(irp, (IrInstSrcStorePtr *)instruction); break; - case IrInstructionIdReturnPtr: - ir_print_return_ptr(irp, (IrInstructionReturnPtr *)instruction); + case IrInstSrcIdTypeOf: + ir_print_typeof(irp, (IrInstSrcTypeOf *)instruction); break; - case IrInstructionIdLoadPtr: - ir_print_load_ptr(irp, (IrInstructionLoadPtr *)instruction); + case IrInstSrcIdFieldPtr: + ir_print_field_ptr(irp, (IrInstSrcFieldPtr *)instruction); break; - case IrInstructionIdLoadPtrGen: - ir_print_load_ptr_gen(irp, (IrInstructionLoadPtrGen *)instruction); + case IrInstSrcIdSetCold: + ir_print_set_cold(irp, (IrInstSrcSetCold *)instruction); break; - case IrInstructionIdStorePtr: - ir_print_store_ptr(irp, (IrInstructionStorePtr *)instruction); + case IrInstSrcIdSetRuntimeSafety: + ir_print_set_runtime_safety(irp, (IrInstSrcSetRuntimeSafety *)instruction); break; - case IrInstructionIdVectorStoreElem: - ir_print_vector_store_elem(irp, (IrInstructionVectorStoreElem *)instruction); + case IrInstSrcIdSetFloatMode: + ir_print_set_float_mode(irp, (IrInstSrcSetFloatMode *)instruction); break; - case IrInstructionIdTypeOf: - ir_print_typeof(irp, (IrInstructionTypeOf *)instruction); + case IrInstSrcIdArrayType: + ir_print_array_type(irp, (IrInstSrcArrayType *)instruction); break; - case IrInstructionIdFieldPtr: - ir_print_field_ptr(irp, (IrInstructionFieldPtr *)instruction); + case IrInstSrcIdSliceType: + ir_print_slice_type(irp, (IrInstSrcSliceType *)instruction); break; - case IrInstructionIdStructFieldPtr: - ir_print_struct_field_ptr(irp, (IrInstructionStructFieldPtr *)instruction); + case IrInstSrcIdAnyFrameType: + ir_print_any_frame_type(irp, (IrInstSrcAnyFrameType *)instruction); break; - case IrInstructionIdUnionFieldPtr: - ir_print_union_field_ptr(irp, (IrInstructionUnionFieldPtr *)instruction); + case IrInstSrcIdAsm: + ir_print_asm_src(irp, (IrInstSrcAsm *)instruction); break; - case IrInstructionIdSetCold: - ir_print_set_cold(irp, (IrInstructionSetCold *)instruction); + case IrInstSrcIdSizeOf: + ir_print_size_of(irp, (IrInstSrcSizeOf *)instruction); break; - case IrInstructionIdSetRuntimeSafety: - ir_print_set_runtime_safety(irp, (IrInstructionSetRuntimeSafety *)instruction); + case IrInstSrcIdTestNonNull: + ir_print_test_non_null(irp, (IrInstSrcTestNonNull *)instruction); break; - case IrInstructionIdSetFloatMode: - ir_print_set_float_mode(irp, (IrInstructionSetFloatMode *)instruction); + case IrInstSrcIdOptionalUnwrapPtr: + ir_print_optional_unwrap_ptr(irp, (IrInstSrcOptionalUnwrapPtr *)instruction); break; - case IrInstructionIdArrayType: - ir_print_array_type(irp, (IrInstructionArrayType *)instruction); + case IrInstSrcIdPopCount: + ir_print_pop_count(irp, (IrInstSrcPopCount *)instruction); break; - case IrInstructionIdSliceType: - ir_print_slice_type(irp, (IrInstructionSliceType *)instruction); + case IrInstSrcIdCtz: + ir_print_ctz(irp, (IrInstSrcCtz *)instruction); break; - case IrInstructionIdAnyFrameType: - ir_print_any_frame_type(irp, (IrInstructionAnyFrameType *)instruction); + case IrInstSrcIdBswap: + ir_print_bswap(irp, (IrInstSrcBswap *)instruction); break; - case IrInstructionIdAsmSrc: - ir_print_asm_src(irp, (IrInstructionAsmSrc *)instruction); + case IrInstSrcIdBitReverse: + ir_print_bit_reverse(irp, (IrInstSrcBitReverse *)instruction); break; - case IrInstructionIdAsmGen: - ir_print_asm_gen(irp, (IrInstructionAsmGen *)instruction); + case IrInstSrcIdSwitchBr: + ir_print_switch_br(irp, (IrInstSrcSwitchBr *)instruction); break; - case IrInstructionIdSizeOf: - ir_print_size_of(irp, (IrInstructionSizeOf *)instruction); + case IrInstSrcIdSwitchVar: + ir_print_switch_var(irp, (IrInstSrcSwitchVar *)instruction); break; - case IrInstructionIdTestNonNull: - ir_print_test_non_null(irp, (IrInstructionTestNonNull *)instruction); + case IrInstSrcIdSwitchElseVar: + ir_print_switch_else_var(irp, (IrInstSrcSwitchElseVar *)instruction); break; - case IrInstructionIdOptionalUnwrapPtr: - ir_print_optional_unwrap_ptr(irp, (IrInstructionOptionalUnwrapPtr *)instruction); + case IrInstSrcIdSwitchTarget: + ir_print_switch_target(irp, (IrInstSrcSwitchTarget *)instruction); break; - case IrInstructionIdPopCount: - ir_print_pop_count(irp, (IrInstructionPopCount *)instruction); + case IrInstSrcIdImport: + ir_print_import(irp, (IrInstSrcImport *)instruction); break; - case IrInstructionIdClz: - ir_print_clz(irp, (IrInstructionClz *)instruction); + case IrInstSrcIdRef: + ir_print_ref(irp, (IrInstSrcRef *)instruction); break; - case IrInstructionIdCtz: - ir_print_ctz(irp, (IrInstructionCtz *)instruction); + case IrInstSrcIdCompileErr: + ir_print_compile_err(irp, (IrInstSrcCompileErr *)instruction); break; - case IrInstructionIdBswap: - ir_print_bswap(irp, (IrInstructionBswap *)instruction); + case IrInstSrcIdCompileLog: + ir_print_compile_log(irp, (IrInstSrcCompileLog *)instruction); break; - case IrInstructionIdBitReverse: - ir_print_bit_reverse(irp, (IrInstructionBitReverse *)instruction); + case IrInstSrcIdErrName: + ir_print_err_name(irp, (IrInstSrcErrName *)instruction); break; - case IrInstructionIdSwitchBr: - ir_print_switch_br(irp, (IrInstructionSwitchBr *)instruction); + case IrInstSrcIdCImport: + ir_print_c_import(irp, (IrInstSrcCImport *)instruction); break; - case IrInstructionIdSwitchVar: - ir_print_switch_var(irp, (IrInstructionSwitchVar *)instruction); + case IrInstSrcIdCInclude: + ir_print_c_include(irp, (IrInstSrcCInclude *)instruction); break; - case IrInstructionIdSwitchElseVar: - ir_print_switch_else_var(irp, (IrInstructionSwitchElseVar *)instruction); + case IrInstSrcIdCDefine: + ir_print_c_define(irp, (IrInstSrcCDefine *)instruction); break; - case IrInstructionIdSwitchTarget: - ir_print_switch_target(irp, (IrInstructionSwitchTarget *)instruction); + case IrInstSrcIdCUndef: + ir_print_c_undef(irp, (IrInstSrcCUndef *)instruction); break; - case IrInstructionIdUnionTag: - ir_print_union_tag(irp, (IrInstructionUnionTag *)instruction); + case IrInstSrcIdEmbedFile: + ir_print_embed_file(irp, (IrInstSrcEmbedFile *)instruction); break; - case IrInstructionIdImport: - ir_print_import(irp, (IrInstructionImport *)instruction); + case IrInstSrcIdCmpxchg: + ir_print_cmpxchg_src(irp, (IrInstSrcCmpxchg *)instruction); break; - case IrInstructionIdRef: - ir_print_ref(irp, (IrInstructionRef *)instruction); + case IrInstSrcIdFence: + ir_print_fence(irp, (IrInstSrcFence *)instruction); break; - case IrInstructionIdRefGen: - ir_print_ref_gen(irp, (IrInstructionRefGen *)instruction); + case IrInstSrcIdTruncate: + ir_print_truncate(irp, (IrInstSrcTruncate *)instruction); break; - case IrInstructionIdCompileErr: - ir_print_compile_err(irp, (IrInstructionCompileErr *)instruction); + case IrInstSrcIdIntCast: + ir_print_int_cast(irp, (IrInstSrcIntCast *)instruction); break; - case IrInstructionIdCompileLog: - ir_print_compile_log(irp, (IrInstructionCompileLog *)instruction); + case IrInstSrcIdFloatCast: + ir_print_float_cast(irp, (IrInstSrcFloatCast *)instruction); break; - case IrInstructionIdErrName: - ir_print_err_name(irp, (IrInstructionErrName *)instruction); + case IrInstSrcIdErrSetCast: + ir_print_err_set_cast(irp, (IrInstSrcErrSetCast *)instruction); break; - case IrInstructionIdCImport: - ir_print_c_import(irp, (IrInstructionCImport *)instruction); + case IrInstSrcIdFromBytes: + ir_print_from_bytes(irp, (IrInstSrcFromBytes *)instruction); break; - case IrInstructionIdCInclude: - ir_print_c_include(irp, (IrInstructionCInclude *)instruction); + case IrInstSrcIdToBytes: + ir_print_to_bytes(irp, (IrInstSrcToBytes *)instruction); break; - case IrInstructionIdCDefine: - ir_print_c_define(irp, (IrInstructionCDefine *)instruction); + case IrInstSrcIdIntToFloat: + ir_print_int_to_float(irp, (IrInstSrcIntToFloat *)instruction); break; - case IrInstructionIdCUndef: - ir_print_c_undef(irp, (IrInstructionCUndef *)instruction); + case IrInstSrcIdFloatToInt: + ir_print_float_to_int(irp, (IrInstSrcFloatToInt *)instruction); break; - case IrInstructionIdEmbedFile: - ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction); + case IrInstSrcIdBoolToInt: + ir_print_bool_to_int(irp, (IrInstSrcBoolToInt *)instruction); break; - case IrInstructionIdCmpxchgSrc: - ir_print_cmpxchg_src(irp, (IrInstructionCmpxchgSrc *)instruction); + case IrInstSrcIdIntType: + ir_print_int_type(irp, (IrInstSrcIntType *)instruction); break; - case IrInstructionIdCmpxchgGen: - ir_print_cmpxchg_gen(irp, (IrInstructionCmpxchgGen *)instruction); + case IrInstSrcIdVectorType: + ir_print_vector_type(irp, (IrInstSrcVectorType *)instruction); break; - case IrInstructionIdFence: - ir_print_fence(irp, (IrInstructionFence *)instruction); + case IrInstSrcIdShuffleVector: + ir_print_shuffle_vector(irp, (IrInstSrcShuffleVector *)instruction); break; - case IrInstructionIdTruncate: - ir_print_truncate(irp, (IrInstructionTruncate *)instruction); + case IrInstSrcIdSplat: + ir_print_splat_src(irp, (IrInstSrcSplat *)instruction); break; - case IrInstructionIdIntCast: - ir_print_int_cast(irp, (IrInstructionIntCast *)instruction); + case IrInstSrcIdBoolNot: + ir_print_bool_not(irp, (IrInstSrcBoolNot *)instruction); break; - case IrInstructionIdFloatCast: - ir_print_float_cast(irp, (IrInstructionFloatCast *)instruction); + case IrInstSrcIdMemset: + ir_print_memset(irp, (IrInstSrcMemset *)instruction); break; - case IrInstructionIdErrSetCast: - ir_print_err_set_cast(irp, (IrInstructionErrSetCast *)instruction); + case IrInstSrcIdMemcpy: + ir_print_memcpy(irp, (IrInstSrcMemcpy *)instruction); break; - case IrInstructionIdFromBytes: - ir_print_from_bytes(irp, (IrInstructionFromBytes *)instruction); + case IrInstSrcIdSlice: + ir_print_slice_src(irp, (IrInstSrcSlice *)instruction); break; - case IrInstructionIdToBytes: - ir_print_to_bytes(irp, (IrInstructionToBytes *)instruction); + case IrInstSrcIdMemberCount: + ir_print_member_count(irp, (IrInstSrcMemberCount *)instruction); break; - case IrInstructionIdIntToFloat: - ir_print_int_to_float(irp, (IrInstructionIntToFloat *)instruction); + case IrInstSrcIdMemberType: + ir_print_member_type(irp, (IrInstSrcMemberType *)instruction); break; - case IrInstructionIdFloatToInt: - ir_print_float_to_int(irp, (IrInstructionFloatToInt *)instruction); + case IrInstSrcIdMemberName: + ir_print_member_name(irp, (IrInstSrcMemberName *)instruction); break; - case IrInstructionIdBoolToInt: - ir_print_bool_to_int(irp, (IrInstructionBoolToInt *)instruction); + case IrInstSrcIdBreakpoint: + ir_print_breakpoint(irp, (IrInstSrcBreakpoint *)instruction); break; - case IrInstructionIdIntType: - ir_print_int_type(irp, (IrInstructionIntType *)instruction); + case IrInstSrcIdReturnAddress: + ir_print_return_address(irp, (IrInstSrcReturnAddress *)instruction); break; - case IrInstructionIdVectorType: - ir_print_vector_type(irp, (IrInstructionVectorType *)instruction); + case IrInstSrcIdFrameAddress: + ir_print_frame_address(irp, (IrInstSrcFrameAddress *)instruction); break; - case IrInstructionIdShuffleVector: - ir_print_shuffle_vector(irp, (IrInstructionShuffleVector *)instruction); + case IrInstSrcIdFrameHandle: + ir_print_handle(irp, (IrInstSrcFrameHandle *)instruction); break; - case IrInstructionIdSplatSrc: - ir_print_splat_src(irp, (IrInstructionSplatSrc *)instruction); + case IrInstSrcIdFrameType: + ir_print_frame_type(irp, (IrInstSrcFrameType *)instruction); break; - case IrInstructionIdSplatGen: - ir_print_splat_gen(irp, (IrInstructionSplatGen *)instruction); + case IrInstSrcIdFrameSize: + ir_print_frame_size_src(irp, (IrInstSrcFrameSize *)instruction); break; - case IrInstructionIdBoolNot: - ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction); + case IrInstSrcIdAlignOf: + ir_print_align_of(irp, (IrInstSrcAlignOf *)instruction); break; - case IrInstructionIdMemset: - ir_print_memset(irp, (IrInstructionMemset *)instruction); + case IrInstSrcIdOverflowOp: + ir_print_overflow_op(irp, (IrInstSrcOverflowOp *)instruction); break; - case IrInstructionIdMemcpy: - ir_print_memcpy(irp, (IrInstructionMemcpy *)instruction); + case IrInstSrcIdTestErr: + ir_print_test_err_src(irp, (IrInstSrcTestErr *)instruction); break; - case IrInstructionIdSliceSrc: - ir_print_slice_src(irp, (IrInstructionSliceSrc *)instruction); + case IrInstSrcIdUnwrapErrCode: + ir_print_unwrap_err_code(irp, (IrInstSrcUnwrapErrCode *)instruction); break; - case IrInstructionIdSliceGen: - ir_print_slice_gen(irp, (IrInstructionSliceGen *)instruction); + case IrInstSrcIdUnwrapErrPayload: + ir_print_unwrap_err_payload(irp, (IrInstSrcUnwrapErrPayload *)instruction); break; - case IrInstructionIdMemberCount: - ir_print_member_count(irp, (IrInstructionMemberCount *)instruction); + case IrInstSrcIdFnProto: + ir_print_fn_proto(irp, (IrInstSrcFnProto *)instruction); break; - case IrInstructionIdMemberType: - ir_print_member_type(irp, (IrInstructionMemberType *)instruction); + case IrInstSrcIdTestComptime: + ir_print_test_comptime(irp, (IrInstSrcTestComptime *)instruction); break; - case IrInstructionIdMemberName: - ir_print_member_name(irp, (IrInstructionMemberName *)instruction); + case IrInstSrcIdPtrCast: + ir_print_ptr_cast_src(irp, (IrInstSrcPtrCast *)instruction); break; - case IrInstructionIdBreakpoint: - ir_print_breakpoint(irp, (IrInstructionBreakpoint *)instruction); + case IrInstSrcIdBitCast: + ir_print_bit_cast_src(irp, (IrInstSrcBitCast *)instruction); break; - case IrInstructionIdReturnAddress: - ir_print_return_address(irp, (IrInstructionReturnAddress *)instruction); + case IrInstSrcIdPtrToInt: + ir_print_ptr_to_int(irp, (IrInstSrcPtrToInt *)instruction); break; - case IrInstructionIdFrameAddress: - ir_print_frame_address(irp, (IrInstructionFrameAddress *)instruction); + case IrInstSrcIdIntToPtr: + ir_print_int_to_ptr(irp, (IrInstSrcIntToPtr *)instruction); break; - case IrInstructionIdFrameHandle: - ir_print_handle(irp, (IrInstructionFrameHandle *)instruction); + case IrInstSrcIdIntToEnum: + ir_print_int_to_enum(irp, (IrInstSrcIntToEnum *)instruction); break; - case IrInstructionIdFrameType: - ir_print_frame_type(irp, (IrInstructionFrameType *)instruction); + case IrInstSrcIdIntToErr: + ir_print_int_to_err(irp, (IrInstSrcIntToErr *)instruction); break; - case IrInstructionIdFrameSizeSrc: - ir_print_frame_size_src(irp, (IrInstructionFrameSizeSrc *)instruction); + case IrInstSrcIdErrToInt: + ir_print_err_to_int(irp, (IrInstSrcErrToInt *)instruction); break; - case IrInstructionIdFrameSizeGen: - ir_print_frame_size_gen(irp, (IrInstructionFrameSizeGen *)instruction); + case IrInstSrcIdCheckSwitchProngs: + ir_print_check_switch_prongs(irp, (IrInstSrcCheckSwitchProngs *)instruction); break; - case IrInstructionIdAlignOf: - ir_print_align_of(irp, (IrInstructionAlignOf *)instruction); + case IrInstSrcIdCheckStatementIsVoid: + ir_print_check_statement_is_void(irp, (IrInstSrcCheckStatementIsVoid *)instruction); break; - case IrInstructionIdOverflowOp: - ir_print_overflow_op(irp, (IrInstructionOverflowOp *)instruction); + case IrInstSrcIdTypeName: + ir_print_type_name(irp, (IrInstSrcTypeName *)instruction); break; - case IrInstructionIdTestErrSrc: - ir_print_test_err_src(irp, (IrInstructionTestErrSrc *)instruction); + case IrInstSrcIdTagName: + ir_print_tag_name(irp, (IrInstSrcTagName *)instruction); break; - case IrInstructionIdTestErrGen: - ir_print_test_err_gen(irp, (IrInstructionTestErrGen *)instruction); + case IrInstSrcIdPtrType: + ir_print_ptr_type(irp, (IrInstSrcPtrType *)instruction); break; - case IrInstructionIdUnwrapErrCode: - ir_print_unwrap_err_code(irp, (IrInstructionUnwrapErrCode *)instruction); + case IrInstSrcIdDeclRef: + ir_print_decl_ref(irp, (IrInstSrcDeclRef *)instruction); break; - case IrInstructionIdUnwrapErrPayload: - ir_print_unwrap_err_payload(irp, (IrInstructionUnwrapErrPayload *)instruction); + case IrInstSrcIdPanic: + ir_print_panic(irp, (IrInstSrcPanic *)instruction); break; - case IrInstructionIdOptionalWrap: - ir_print_optional_wrap(irp, (IrInstructionOptionalWrap *)instruction); + case IrInstSrcIdFieldParentPtr: + ir_print_field_parent_ptr(irp, (IrInstSrcFieldParentPtr *)instruction); break; - case IrInstructionIdErrWrapCode: - ir_print_err_wrap_code(irp, (IrInstructionErrWrapCode *)instruction); + case IrInstSrcIdByteOffsetOf: + ir_print_byte_offset_of(irp, (IrInstSrcByteOffsetOf *)instruction); break; - case IrInstructionIdErrWrapPayload: - ir_print_err_wrap_payload(irp, (IrInstructionErrWrapPayload *)instruction); + case IrInstSrcIdBitOffsetOf: + ir_print_bit_offset_of(irp, (IrInstSrcBitOffsetOf *)instruction); break; - case IrInstructionIdFnProto: - ir_print_fn_proto(irp, (IrInstructionFnProto *)instruction); + case IrInstSrcIdTypeInfo: + ir_print_type_info(irp, (IrInstSrcTypeInfo *)instruction); break; - case IrInstructionIdTestComptime: - ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction); + case IrInstSrcIdType: + ir_print_type(irp, (IrInstSrcType *)instruction); break; - case IrInstructionIdPtrCastSrc: - ir_print_ptr_cast_src(irp, (IrInstructionPtrCastSrc *)instruction); + case IrInstSrcIdHasField: + ir_print_has_field(irp, (IrInstSrcHasField *)instruction); break; - case IrInstructionIdPtrCastGen: - ir_print_ptr_cast_gen(irp, (IrInstructionPtrCastGen *)instruction); + case IrInstSrcIdTypeId: + ir_print_type_id(irp, (IrInstSrcTypeId *)instruction); break; - case IrInstructionIdBitCastSrc: - ir_print_bit_cast_src(irp, (IrInstructionBitCastSrc *)instruction); + case IrInstSrcIdSetEvalBranchQuota: + ir_print_set_eval_branch_quota(irp, (IrInstSrcSetEvalBranchQuota *)instruction); break; - case IrInstructionIdBitCastGen: - ir_print_bit_cast_gen(irp, (IrInstructionBitCastGen *)instruction); + case IrInstSrcIdAlignCast: + ir_print_align_cast(irp, (IrInstSrcAlignCast *)instruction); break; - case IrInstructionIdWidenOrShorten: - ir_print_widen_or_shorten(irp, (IrInstructionWidenOrShorten *)instruction); + case IrInstSrcIdImplicitCast: + ir_print_implicit_cast(irp, (IrInstSrcImplicitCast *)instruction); break; - case IrInstructionIdPtrToInt: - ir_print_ptr_to_int(irp, (IrInstructionPtrToInt *)instruction); + case IrInstSrcIdResolveResult: + ir_print_resolve_result(irp, (IrInstSrcResolveResult *)instruction); break; - case IrInstructionIdIntToPtr: - ir_print_int_to_ptr(irp, (IrInstructionIntToPtr *)instruction); + case IrInstSrcIdResetResult: + ir_print_reset_result(irp, (IrInstSrcResetResult *)instruction); break; - case IrInstructionIdIntToEnum: - ir_print_int_to_enum(irp, (IrInstructionIntToEnum *)instruction); + case IrInstSrcIdOpaqueType: + ir_print_opaque_type(irp, (IrInstSrcOpaqueType *)instruction); break; - case IrInstructionIdIntToErr: - ir_print_int_to_err(irp, (IrInstructionIntToErr *)instruction); + case IrInstSrcIdSetAlignStack: + ir_print_set_align_stack(irp, (IrInstSrcSetAlignStack *)instruction); break; - case IrInstructionIdErrToInt: - ir_print_err_to_int(irp, (IrInstructionErrToInt *)instruction); + case IrInstSrcIdArgType: + ir_print_arg_type(irp, (IrInstSrcArgType *)instruction); break; - case IrInstructionIdCheckSwitchProngs: - ir_print_check_switch_prongs(irp, (IrInstructionCheckSwitchProngs *)instruction); + case IrInstSrcIdTagType: + ir_print_enum_tag_type(irp, (IrInstSrcTagType *)instruction); break; - case IrInstructionIdCheckStatementIsVoid: - ir_print_check_statement_is_void(irp, (IrInstructionCheckStatementIsVoid *)instruction); + case IrInstSrcIdExport: + ir_print_export(irp, (IrInstSrcExport *)instruction); break; - case IrInstructionIdTypeName: - ir_print_type_name(irp, (IrInstructionTypeName *)instruction); + case IrInstSrcIdErrorReturnTrace: + ir_print_error_return_trace(irp, (IrInstSrcErrorReturnTrace *)instruction); break; - case IrInstructionIdTagName: - ir_print_tag_name(irp, (IrInstructionTagName *)instruction); + case IrInstSrcIdErrorUnion: + ir_print_error_union(irp, (IrInstSrcErrorUnion *)instruction); break; - case IrInstructionIdPtrType: - ir_print_ptr_type(irp, (IrInstructionPtrType *)instruction); + case IrInstSrcIdAtomicRmw: + ir_print_atomic_rmw(irp, (IrInstSrcAtomicRmw *)instruction); break; - case IrInstructionIdDeclRef: - ir_print_decl_ref(irp, (IrInstructionDeclRef *)instruction); + case IrInstSrcIdSaveErrRetAddr: + ir_print_save_err_ret_addr(irp, (IrInstSrcSaveErrRetAddr *)instruction); break; - case IrInstructionIdPanic: - ir_print_panic(irp, (IrInstructionPanic *)instruction); + case IrInstSrcIdAddImplicitReturnType: + ir_print_add_implicit_return_type(irp, (IrInstSrcAddImplicitReturnType *)instruction); break; - case IrInstructionIdFieldParentPtr: - ir_print_field_parent_ptr(irp, (IrInstructionFieldParentPtr *)instruction); + case IrInstSrcIdFloatOp: + ir_print_float_op(irp, (IrInstSrcFloatOp *)instruction); break; - case IrInstructionIdByteOffsetOf: - ir_print_byte_offset_of(irp, (IrInstructionByteOffsetOf *)instruction); + case IrInstSrcIdMulAdd: + ir_print_mul_add(irp, (IrInstSrcMulAdd *)instruction); break; - case IrInstructionIdBitOffsetOf: - ir_print_bit_offset_of(irp, (IrInstructionBitOffsetOf *)instruction); + case IrInstSrcIdAtomicLoad: + ir_print_atomic_load(irp, (IrInstSrcAtomicLoad *)instruction); break; - case IrInstructionIdTypeInfo: - ir_print_type_info(irp, (IrInstructionTypeInfo *)instruction); + case IrInstSrcIdAtomicStore: + ir_print_atomic_store(irp, (IrInstSrcAtomicStore *)instruction); break; - case IrInstructionIdType: - ir_print_type(irp, (IrInstructionType *)instruction); + case IrInstSrcIdEnumToInt: + ir_print_enum_to_int(irp, (IrInstSrcEnumToInt *)instruction); break; - case IrInstructionIdHasField: - ir_print_has_field(irp, (IrInstructionHasField *)instruction); + case IrInstSrcIdCheckRuntimeScope: + ir_print_check_runtime_scope(irp, (IrInstSrcCheckRuntimeScope *)instruction); break; - case IrInstructionIdTypeId: - ir_print_type_id(irp, (IrInstructionTypeId *)instruction); + case IrInstSrcIdHasDecl: + ir_print_has_decl(irp, (IrInstSrcHasDecl *)instruction); break; - case IrInstructionIdSetEvalBranchQuota: - ir_print_set_eval_branch_quota(irp, (IrInstructionSetEvalBranchQuota *)instruction); + case IrInstSrcIdUndeclaredIdent: + ir_print_undeclared_ident(irp, (IrInstSrcUndeclaredIdent *)instruction); break; - case IrInstructionIdAlignCast: - ir_print_align_cast(irp, (IrInstructionAlignCast *)instruction); + case IrInstSrcIdAlloca: + ir_print_alloca_src(irp, (IrInstSrcAlloca *)instruction); break; - case IrInstructionIdImplicitCast: - ir_print_implicit_cast(irp, (IrInstructionImplicitCast *)instruction); + case IrInstSrcIdEndExpr: + ir_print_end_expr(irp, (IrInstSrcEndExpr *)instruction); break; - case IrInstructionIdResolveResult: - ir_print_resolve_result(irp, (IrInstructionResolveResult *)instruction); + case IrInstSrcIdUnionInitNamedField: + ir_print_union_init_named_field(irp, (IrInstSrcUnionInitNamedField *)instruction); break; - case IrInstructionIdResetResult: - ir_print_reset_result(irp, (IrInstructionResetResult *)instruction); + case IrInstSrcIdSuspendBegin: + ir_print_suspend_begin(irp, (IrInstSrcSuspendBegin *)instruction); break; - case IrInstructionIdOpaqueType: - ir_print_opaque_type(irp, (IrInstructionOpaqueType *)instruction); + case IrInstSrcIdSuspendFinish: + ir_print_suspend_finish(irp, (IrInstSrcSuspendFinish *)instruction); break; - case IrInstructionIdSetAlignStack: - ir_print_set_align_stack(irp, (IrInstructionSetAlignStack *)instruction); + case IrInstSrcIdResume: + ir_print_resume(irp, (IrInstSrcResume *)instruction); break; - case IrInstructionIdArgType: - ir_print_arg_type(irp, (IrInstructionArgType *)instruction); + case IrInstSrcIdAwait: + ir_print_await_src(irp, (IrInstSrcAwait *)instruction); break; - case IrInstructionIdTagType: - ir_print_enum_tag_type(irp, (IrInstructionTagType *)instruction); + case IrInstSrcIdSpillBegin: + ir_print_spill_begin(irp, (IrInstSrcSpillBegin *)instruction); break; - case IrInstructionIdExport: - ir_print_export(irp, (IrInstructionExport *)instruction); + case IrInstSrcIdSpillEnd: + ir_print_spill_end(irp, (IrInstSrcSpillEnd *)instruction); break; - case IrInstructionIdErrorReturnTrace: - ir_print_error_return_trace(irp, (IrInstructionErrorReturnTrace *)instruction); - break; - case IrInstructionIdErrorUnion: - ir_print_error_union(irp, (IrInstructionErrorUnion *)instruction); - break; - case IrInstructionIdAtomicRmw: - ir_print_atomic_rmw(irp, (IrInstructionAtomicRmw *)instruction); - break; - case IrInstructionIdSaveErrRetAddr: - ir_print_save_err_ret_addr(irp, (IrInstructionSaveErrRetAddr *)instruction); - break; - case IrInstructionIdAddImplicitReturnType: - ir_print_add_implicit_return_type(irp, (IrInstructionAddImplicitReturnType *)instruction); - break; - case IrInstructionIdFloatOp: - ir_print_float_op(irp, (IrInstructionFloatOp *)instruction); - break; - case IrInstructionIdMulAdd: - ir_print_mul_add(irp, (IrInstructionMulAdd *)instruction); - break; - case IrInstructionIdAtomicLoad: - ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction); - break; - case IrInstructionIdAtomicStore: - ir_print_atomic_store(irp, (IrInstructionAtomicStore *)instruction); - break; - case IrInstructionIdEnumToInt: - ir_print_enum_to_int(irp, (IrInstructionEnumToInt *)instruction); - break; - case IrInstructionIdCheckRuntimeScope: - ir_print_check_runtime_scope(irp, (IrInstructionCheckRuntimeScope *)instruction); - break; - case IrInstructionIdDeclVarGen: - ir_print_decl_var_gen(irp, (IrInstructionDeclVarGen *)instruction); - break; - case IrInstructionIdArrayToVector: - ir_print_array_to_vector(irp, (IrInstructionArrayToVector *)instruction); - break; - case IrInstructionIdVectorToArray: - ir_print_vector_to_array(irp, (IrInstructionVectorToArray *)instruction); - break; - case IrInstructionIdPtrOfArrayToSlice: - ir_print_ptr_of_array_to_slice(irp, (IrInstructionPtrOfArrayToSlice *)instruction); - break; - case IrInstructionIdAssertZero: - ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction); - break; - case IrInstructionIdAssertNonNull: - ir_print_assert_non_null(irp, (IrInstructionAssertNonNull *)instruction); - break; - case IrInstructionIdResizeSlice: - ir_print_resize_slice(irp, (IrInstructionResizeSlice *)instruction); - break; - case IrInstructionIdHasDecl: - ir_print_has_decl(irp, (IrInstructionHasDecl *)instruction); - break; - case IrInstructionIdUndeclaredIdent: - ir_print_undeclared_ident(irp, (IrInstructionUndeclaredIdent *)instruction); - break; - case IrInstructionIdAllocaSrc: - ir_print_alloca_src(irp, (IrInstructionAllocaSrc *)instruction); - break; - case IrInstructionIdAllocaGen: - ir_print_alloca_gen(irp, (IrInstructionAllocaGen *)instruction); - break; - case IrInstructionIdEndExpr: - ir_print_end_expr(irp, (IrInstructionEndExpr *)instruction); - break; - case IrInstructionIdUnionInitNamedField: - ir_print_union_init_named_field(irp, (IrInstructionUnionInitNamedField *)instruction); - break; - case IrInstructionIdSuspendBegin: - ir_print_suspend_begin(irp, (IrInstructionSuspendBegin *)instruction); - break; - case IrInstructionIdSuspendFinish: - ir_print_suspend_finish(irp, (IrInstructionSuspendFinish *)instruction); - break; - case IrInstructionIdResume: - ir_print_resume(irp, (IrInstructionResume *)instruction); - break; - case IrInstructionIdAwaitSrc: - ir_print_await_src(irp, (IrInstructionAwaitSrc *)instruction); - break; - case IrInstructionIdAwaitGen: - ir_print_await_gen(irp, (IrInstructionAwaitGen *)instruction); - break; - case IrInstructionIdSpillBegin: - ir_print_spill_begin(irp, (IrInstructionSpillBegin *)instruction); - break; - case IrInstructionIdSpillEnd: - ir_print_spill_end(irp, (IrInstructionSpillEnd *)instruction); - break; - case IrInstructionIdVectorExtractElem: - ir_print_vector_extract_elem(irp, (IrInstructionVectorExtractElem *)instruction); + case IrInstSrcIdClz: + ir_print_clz(irp, (IrInstSrcClz *)instruction); break; } fprintf(irp->f, "\n"); } -static void irp_print_basic_block(IrPrint *irp, IrBasicBlock *current_block) { - fprintf(irp->f, "%s_%" ZIG_PRI_usize ":\n", current_block->name_hint, current_block->debug_id); +static void ir_print_inst_gen(IrPrintGen *irp, IrInstGen *instruction, bool trailing) { + ir_print_prefix_gen(irp, instruction, trailing); + switch (instruction->id) { + case IrInstGenIdInvalid: + zig_unreachable(); + case IrInstGenIdReturn: + ir_print_return_gen(irp, (IrInstGenReturn *)instruction); + break; + case IrInstGenIdConst: + ir_print_const(irp, (IrInstGenConst *)instruction); + break; + case IrInstGenIdBinOp: + ir_print_bin_op(irp, (IrInstGenBinOp *)instruction); + break; + case IrInstGenIdDeclVar: + ir_print_decl_var_gen(irp, (IrInstGenDeclVar *)instruction); + break; + case IrInstGenIdCast: + ir_print_cast(irp, (IrInstGenCast *)instruction); + break; + case IrInstGenIdCall: + ir_print_call_gen(irp, (IrInstGenCall *)instruction); + break; + case IrInstGenIdCondBr: + ir_print_cond_br(irp, (IrInstGenCondBr *)instruction); + break; + case IrInstGenIdBr: + ir_print_br(irp, (IrInstGenBr *)instruction); + break; + case IrInstGenIdPhi: + ir_print_phi(irp, (IrInstGenPhi *)instruction); + break; + case IrInstGenIdUnreachable: + ir_print_unreachable(irp, (IrInstGenUnreachable *)instruction); + break; + case IrInstGenIdElemPtr: + ir_print_elem_ptr(irp, (IrInstGenElemPtr *)instruction); + break; + case IrInstGenIdVarPtr: + ir_print_var_ptr(irp, (IrInstGenVarPtr *)instruction); + break; + case IrInstGenIdReturnPtr: + ir_print_return_ptr(irp, (IrInstGenReturnPtr *)instruction); + break; + case IrInstGenIdLoadPtr: + ir_print_load_ptr_gen(irp, (IrInstGenLoadPtr *)instruction); + break; + case IrInstGenIdStorePtr: + ir_print_store_ptr(irp, (IrInstGenStorePtr *)instruction); + break; + case IrInstGenIdStructFieldPtr: + ir_print_struct_field_ptr(irp, (IrInstGenStructFieldPtr *)instruction); + break; + case IrInstGenIdUnionFieldPtr: + ir_print_union_field_ptr(irp, (IrInstGenUnionFieldPtr *)instruction); + break; + case IrInstGenIdAsm: + ir_print_asm_gen(irp, (IrInstGenAsm *)instruction); + break; + case IrInstGenIdTestNonNull: + ir_print_test_non_null(irp, (IrInstGenTestNonNull *)instruction); + break; + case IrInstGenIdOptionalUnwrapPtr: + ir_print_optional_unwrap_ptr(irp, (IrInstGenOptionalUnwrapPtr *)instruction); + break; + case IrInstGenIdPopCount: + ir_print_pop_count(irp, (IrInstGenPopCount *)instruction); + break; + case IrInstGenIdClz: + ir_print_clz(irp, (IrInstGenClz *)instruction); + break; + case IrInstGenIdCtz: + ir_print_ctz(irp, (IrInstGenCtz *)instruction); + break; + case IrInstGenIdBswap: + ir_print_bswap(irp, (IrInstGenBswap *)instruction); + break; + case IrInstGenIdBitReverse: + ir_print_bit_reverse(irp, (IrInstGenBitReverse *)instruction); + break; + case IrInstGenIdSwitchBr: + ir_print_switch_br(irp, (IrInstGenSwitchBr *)instruction); + break; + case IrInstGenIdUnionTag: + ir_print_union_tag(irp, (IrInstGenUnionTag *)instruction); + break; + case IrInstGenIdRef: + ir_print_ref_gen(irp, (IrInstGenRef *)instruction); + break; + case IrInstGenIdErrName: + ir_print_err_name(irp, (IrInstGenErrName *)instruction); + break; + case IrInstGenIdCmpxchg: + ir_print_cmpxchg_gen(irp, (IrInstGenCmpxchg *)instruction); + break; + case IrInstGenIdFence: + ir_print_fence(irp, (IrInstGenFence *)instruction); + break; + case IrInstGenIdTruncate: + ir_print_truncate(irp, (IrInstGenTruncate *)instruction); + break; + case IrInstGenIdShuffleVector: + ir_print_shuffle_vector(irp, (IrInstGenShuffleVector *)instruction); + break; + case IrInstGenIdSplat: + ir_print_splat_gen(irp, (IrInstGenSplat *)instruction); + break; + case IrInstGenIdBoolNot: + ir_print_bool_not(irp, (IrInstGenBoolNot *)instruction); + break; + case IrInstGenIdMemset: + ir_print_memset(irp, (IrInstGenMemset *)instruction); + break; + case IrInstGenIdMemcpy: + ir_print_memcpy(irp, (IrInstGenMemcpy *)instruction); + break; + case IrInstGenIdSlice: + ir_print_slice_gen(irp, (IrInstGenSlice *)instruction); + break; + case IrInstGenIdBreakpoint: + ir_print_breakpoint(irp, (IrInstGenBreakpoint *)instruction); + break; + case IrInstGenIdReturnAddress: + ir_print_return_address(irp, (IrInstGenReturnAddress *)instruction); + break; + case IrInstGenIdFrameAddress: + ir_print_frame_address(irp, (IrInstGenFrameAddress *)instruction); + break; + case IrInstGenIdFrameHandle: + ir_print_handle(irp, (IrInstGenFrameHandle *)instruction); + break; + case IrInstGenIdFrameSize: + ir_print_frame_size_gen(irp, (IrInstGenFrameSize *)instruction); + break; + case IrInstGenIdOverflowOp: + ir_print_overflow_op(irp, (IrInstGenOverflowOp *)instruction); + break; + case IrInstGenIdTestErr: + ir_print_test_err_gen(irp, (IrInstGenTestErr *)instruction); + break; + case IrInstGenIdUnwrapErrCode: + ir_print_unwrap_err_code(irp, (IrInstGenUnwrapErrCode *)instruction); + break; + case IrInstGenIdUnwrapErrPayload: + ir_print_unwrap_err_payload(irp, (IrInstGenUnwrapErrPayload *)instruction); + break; + case IrInstGenIdOptionalWrap: + ir_print_optional_wrap(irp, (IrInstGenOptionalWrap *)instruction); + break; + case IrInstGenIdErrWrapCode: + ir_print_err_wrap_code(irp, (IrInstGenErrWrapCode *)instruction); + break; + case IrInstGenIdErrWrapPayload: + ir_print_err_wrap_payload(irp, (IrInstGenErrWrapPayload *)instruction); + break; + case IrInstGenIdPtrCast: + ir_print_ptr_cast_gen(irp, (IrInstGenPtrCast *)instruction); + break; + case IrInstGenIdBitCast: + ir_print_bit_cast_gen(irp, (IrInstGenBitCast *)instruction); + break; + case IrInstGenIdWidenOrShorten: + ir_print_widen_or_shorten(irp, (IrInstGenWidenOrShorten *)instruction); + break; + case IrInstGenIdPtrToInt: + ir_print_ptr_to_int(irp, (IrInstGenPtrToInt *)instruction); + break; + case IrInstGenIdIntToPtr: + ir_print_int_to_ptr(irp, (IrInstGenIntToPtr *)instruction); + break; + case IrInstGenIdIntToEnum: + ir_print_int_to_enum(irp, (IrInstGenIntToEnum *)instruction); + break; + case IrInstGenIdIntToErr: + ir_print_int_to_err(irp, (IrInstGenIntToErr *)instruction); + break; + case IrInstGenIdErrToInt: + ir_print_err_to_int(irp, (IrInstGenErrToInt *)instruction); + break; + case IrInstGenIdTagName: + ir_print_tag_name(irp, (IrInstGenTagName *)instruction); + break; + case IrInstGenIdPanic: + ir_print_panic(irp, (IrInstGenPanic *)instruction); + break; + case IrInstGenIdFieldParentPtr: + ir_print_field_parent_ptr(irp, (IrInstGenFieldParentPtr *)instruction); + break; + case IrInstGenIdAlignCast: + ir_print_align_cast(irp, (IrInstGenAlignCast *)instruction); + break; + case IrInstGenIdErrorReturnTrace: + ir_print_error_return_trace(irp, (IrInstGenErrorReturnTrace *)instruction); + break; + case IrInstGenIdAtomicRmw: + ir_print_atomic_rmw(irp, (IrInstGenAtomicRmw *)instruction); + break; + case IrInstGenIdSaveErrRetAddr: + ir_print_save_err_ret_addr(irp, (IrInstGenSaveErrRetAddr *)instruction); + break; + case IrInstGenIdFloatOp: + ir_print_float_op(irp, (IrInstGenFloatOp *)instruction); + break; + case IrInstGenIdMulAdd: + ir_print_mul_add(irp, (IrInstGenMulAdd *)instruction); + break; + case IrInstGenIdAtomicLoad: + ir_print_atomic_load(irp, (IrInstGenAtomicLoad *)instruction); + break; + case IrInstGenIdAtomicStore: + ir_print_atomic_store(irp, (IrInstGenAtomicStore *)instruction); + break; + case IrInstGenIdArrayToVector: + ir_print_array_to_vector(irp, (IrInstGenArrayToVector *)instruction); + break; + case IrInstGenIdVectorToArray: + ir_print_vector_to_array(irp, (IrInstGenVectorToArray *)instruction); + break; + case IrInstGenIdPtrOfArrayToSlice: + ir_print_ptr_of_array_to_slice(irp, (IrInstGenPtrOfArrayToSlice *)instruction); + break; + case IrInstGenIdAssertZero: + ir_print_assert_zero(irp, (IrInstGenAssertZero *)instruction); + break; + case IrInstGenIdAssertNonNull: + ir_print_assert_non_null(irp, (IrInstGenAssertNonNull *)instruction); + break; + case IrInstGenIdResizeSlice: + ir_print_resize_slice(irp, (IrInstGenResizeSlice *)instruction); + break; + case IrInstGenIdAlloca: + ir_print_alloca_gen(irp, (IrInstGenAlloca *)instruction); + break; + case IrInstGenIdSuspendBegin: + ir_print_suspend_begin(irp, (IrInstGenSuspendBegin *)instruction); + break; + case IrInstGenIdSuspendFinish: + ir_print_suspend_finish(irp, (IrInstGenSuspendFinish *)instruction); + break; + case IrInstGenIdResume: + ir_print_resume(irp, (IrInstGenResume *)instruction); + break; + case IrInstGenIdAwait: + ir_print_await_gen(irp, (IrInstGenAwait *)instruction); + break; + case IrInstGenIdSpillBegin: + ir_print_spill_begin(irp, (IrInstGenSpillBegin *)instruction); + break; + case IrInstGenIdSpillEnd: + ir_print_spill_end(irp, (IrInstGenSpillEnd *)instruction); + break; + case IrInstGenIdVectorExtractElem: + ir_print_vector_extract_elem(irp, (IrInstGenVectorExtractElem *)instruction); + break; + case IrInstGenIdVectorStoreElem: + ir_print_vector_store_elem(irp, (IrInstGenVectorStoreElem *)instruction); + break; + case IrInstGenIdBinaryNot: + ir_print_binary_not(irp, (IrInstGenBinaryNot *)instruction); + break; + case IrInstGenIdNegation: + ir_print_negation(irp, (IrInstGenNegation *)instruction); + break; + case IrInstGenIdNegationWrapping: + ir_print_negation_wrapping(irp, (IrInstGenNegationWrapping *)instruction); + break; + } + fprintf(irp->f, "\n"); +} + +static void irp_print_basic_block_src(IrPrintSrc *irp, IrBasicBlockSrc *current_block) { + fprintf(irp->f, "%s_%" PRIu32 ":\n", current_block->name_hint, current_block->debug_id); for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) { - IrInstruction *instruction = current_block->instruction_list.at(instr_i); - if (irp->pass != IrPassSrc) { - irp->printed.put(instruction, 0); - irp->pending.clear(); - } - ir_print_instruction(irp, instruction, false); - for (size_t j = 0; j < irp->pending.length; ++j) - ir_print_instruction(irp, irp->pending.at(j), true); + IrInstSrc *instruction = current_block->instruction_list.at(instr_i); + ir_print_inst_src(irp, instruction, false); } } -void ir_print_basic_block(CodeGen *codegen, FILE *f, IrBasicBlock *bb, int indent_size, IrPass pass) { - IrPrint ir_print = {}; - ir_print.pass = pass; +static void irp_print_basic_block_gen(IrPrintGen *irp, IrBasicBlockGen *current_block) { + fprintf(irp->f, "%s_%" PRIu32 ":\n", current_block->name_hint, current_block->debug_id); + for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) { + IrInstGen *instruction = current_block->instruction_list.at(instr_i); + irp->printed.put(instruction, 0); + irp->pending.clear(); + ir_print_inst_gen(irp, instruction, false); + for (size_t j = 0; j < irp->pending.length; ++j) + ir_print_inst_gen(irp, irp->pending.at(j), true); + } +} + +void ir_print_basic_block_src(CodeGen *codegen, FILE *f, IrBasicBlockSrc *bb, int indent_size) { + IrPrintSrc ir_print = {}; + ir_print.codegen = codegen; + ir_print.f = f; + ir_print.indent = indent_size; + ir_print.indent_size = indent_size; + + irp_print_basic_block_src(&ir_print, bb); +} + +void ir_print_basic_block_gen(CodeGen *codegen, FILE *f, IrBasicBlockGen *bb, int indent_size) { + IrPrintGen ir_print = {}; ir_print.codegen = codegen; ir_print.f = f; ir_print.indent = indent_size; @@ -2651,16 +3361,28 @@ void ir_print_basic_block(CodeGen *codegen, FILE *f, IrBasicBlock *bb, int inden ir_print.printed.init(64); ir_print.pending = {}; - irp_print_basic_block(&ir_print, bb); + irp_print_basic_block_gen(&ir_print, bb); ir_print.pending.deinit(); ir_print.printed.deinit(); } -void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size, IrPass pass) { - IrPrint ir_print = {}; - IrPrint *irp = &ir_print; - irp->pass = pass; +void ir_print_src(CodeGen *codegen, FILE *f, IrExecutableSrc *executable, int indent_size) { + IrPrintSrc ir_print = {}; + IrPrintSrc *irp = &ir_print; + irp->codegen = codegen; + irp->f = f; + irp->indent = indent_size; + irp->indent_size = indent_size; + + for (size_t bb_i = 0; bb_i < executable->basic_block_list.length; bb_i += 1) { + irp_print_basic_block_src(irp, executable->basic_block_list.at(bb_i)); + } +} + +void ir_print_gen(CodeGen *codegen, FILE *f, IrExecutableGen *executable, int indent_size) { + IrPrintGen ir_print = {}; + IrPrintGen *irp = &ir_print; irp->codegen = codegen; irp->f = f; irp->indent = indent_size; @@ -2670,17 +3392,27 @@ void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_si irp->pending = {}; for (size_t bb_i = 0; bb_i < executable->basic_block_list.length; bb_i += 1) { - irp_print_basic_block(irp, executable->basic_block_list.at(bb_i)); + irp_print_basic_block_gen(irp, executable->basic_block_list.at(bb_i)); } irp->pending.deinit(); irp->printed.deinit(); } -void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size, IrPass pass) { - IrPrint ir_print = {}; - IrPrint *irp = &ir_print; - irp->pass = pass; +void ir_print_inst_src(CodeGen *codegen, FILE *f, IrInstSrc *instruction, int indent_size) { + IrPrintSrc ir_print = {}; + IrPrintSrc *irp = &ir_print; + irp->codegen = codegen; + irp->f = f; + irp->indent = indent_size; + irp->indent_size = indent_size; + + ir_print_inst_src(irp, instruction, false); +} + +void ir_print_inst_gen(CodeGen *codegen, FILE *f, IrInstGen *instruction, int indent_size) { + IrPrintGen ir_print = {}; + IrPrintGen *irp = &ir_print; irp->codegen = codegen; irp->f = f; irp->indent = indent_size; @@ -2689,20 +3421,5 @@ void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, irp->printed.init(4); irp->pending = {}; - ir_print_instruction(irp, instruction, false); -} - -void ir_print_const_expr(CodeGen *codegen, FILE *f, ZigValue *value, int indent_size, IrPass pass) { - IrPrint ir_print = {}; - IrPrint *irp = &ir_print; - irp->pass = pass; - irp->codegen = codegen; - irp->f = f; - irp->indent = indent_size; - irp->indent_size = indent_size; - irp->printed = {}; - irp->printed.init(4); - irp->pending = {}; - - ir_print_const_value(irp, value); + ir_print_inst_gen(irp, instruction, false); } diff --git a/src/ir_print.hpp b/src/ir_print.hpp index 1292779ac4..dde5aaea67 100644 --- a/src/ir_print.hpp +++ b/src/ir_print.hpp @@ -12,11 +12,14 @@ #include -void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size, IrPass pass); -void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size, IrPass pass); -void ir_print_const_expr(CodeGen *codegen, FILE *f, ZigValue *value, int indent_size, IrPass pass); -void ir_print_basic_block(CodeGen *codegen, FILE *f, IrBasicBlock *bb, int indent_size, IrPass pass); +void ir_print_src(CodeGen *codegen, FILE *f, IrExecutableSrc *executable, int indent_size); +void ir_print_gen(CodeGen *codegen, FILE *f, IrExecutableGen *executable, int indent_size); +void ir_print_inst_src(CodeGen *codegen, FILE *f, IrInstSrc *inst, int indent_size); +void ir_print_inst_gen(CodeGen *codegen, FILE *f, IrInstGen *inst, int indent_size); +void ir_print_basic_block_src(CodeGen *codegen, FILE *f, IrBasicBlockSrc *bb, int indent_size); +void ir_print_basic_block_gen(CodeGen *codegen, FILE *f, IrBasicBlockGen *bb, int indent_size); -const char* ir_instruction_type_str(IrInstructionId id); +const char* ir_inst_src_type_str(IrInstSrcId id); +const char* ir_inst_gen_type_str(IrInstGenId id); #endif diff --git a/src/main.cpp b/src/main.cpp index d89ac352a5..a844730014 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -93,6 +93,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { " --verbose-llvm-ir enable compiler debug output for LLVM IR\n" " --verbose-cimport enable compiler debug output for C imports\n" " --verbose-cc enable compiler debug output for C compilation\n" + " --verbose-llvm-cpu-features enable compiler debug output for LLVM CPU features\n" " -dirafter [dir] add directory to AFTER include search path\n" " -isystem [dir] add directory to SYSTEM include search path\n" " -I[dir] add directory to include search path\n" @@ -100,6 +101,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { " --override-lib-dir [arg] override path to Zig lib directory\n" " -ffunction-sections places each function in a separate section\n" " -D[macro]=[value] define C [macro] to [value] (1 if [value] omitted)\n" + " -target-cpu [cpu] target one specific CPU by name\n" + " -target-feature [features] specify the set of CPU features to target\n" "\n" "Link Options:\n" " --bundle-compiler-rt for static libraries, include compiler-rt symbols\n" @@ -141,100 +144,18 @@ static int print_libc_usage(const char *arg0, FILE *file, int return_code) { "You can save this into a file and then edit the paths to create a cross\n" "compilation libc kit. Then you can pass `--libc [file]` for Zig to use it.\n" "\n" - "When compiling natively and no `--libc` argument provided, Zig automatically\n" - "creates zig-cache/native_libc.txt so that it does not have to detect libc\n" - "on every invocation. You can remove this file to have Zig re-detect the\n" - "native libc.\n" + "When compiling natively and no `--libc` argument provided, Zig will create\n" + "`%s/native_libc.txt`\n" + "so that it does not have to detect libc on every invocation. You can remove\n" + "this file to have Zig re-detect the native libc.\n" "\n\n" "Usage: %s libc [file]\n" "\n" "Parse a libc installation text file and validate it.\n" - , arg0, arg0); + , arg0, buf_ptr(get_global_cache_dir()), arg0); return return_code; } -static bool arch_available_in_llvm(ZigLLVM_ArchType arch) { - LLVMTargetRef target_ref; - char *err_msg = nullptr; - char triple_string[128]; - sprintf(triple_string, "%s-unknown-unknown-unknown", ZigLLVMGetArchTypeName(arch)); - return !LLVMGetTargetFromTriple(triple_string, &target_ref, &err_msg); -} - -static int print_target_list(FILE *f) { - ZigTarget native; - get_native_target(&native); - - fprintf(f, "Architectures:\n"); - size_t arch_count = target_arch_count(); - for (size_t arch_i = 0; arch_i < arch_count; arch_i += 1) { - ZigLLVM_ArchType arch = target_arch_enum(arch_i); - if (!arch_available_in_llvm(arch)) - continue; - const char *arch_name = target_arch_name(arch); - SubArchList sub_arch_list = target_subarch_list(arch); - size_t sub_count = target_subarch_count(sub_arch_list); - const char *arch_native_str = (native.arch == arch) ? " (native)" : ""; - fprintf(f, " %s%s\n", arch_name, arch_native_str); - for (size_t sub_i = 0; sub_i < sub_count; sub_i += 1) { - ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i); - const char *sub_name = target_subarch_name(sub); - const char *sub_native_str = (native.arch == arch && native.sub_arch == sub) ? " (native)" : ""; - fprintf(f, " %s%s\n", sub_name, sub_native_str); - } - } - - fprintf(f, "\nOperating Systems:\n"); - size_t os_count = target_os_count(); - for (size_t i = 0; i < os_count; i += 1) { - Os os_type = target_os_enum(i); - const char *native_str = (native.os == os_type) ? " (native)" : ""; - fprintf(f, " %s%s\n", target_os_name(os_type), native_str); - } - - fprintf(f, "\nC ABIs:\n"); - size_t abi_count = target_abi_count(); - for (size_t i = 0; i < abi_count; i += 1) { - ZigLLVM_EnvironmentType abi = target_abi_enum(i); - const char *native_str = (native.abi == abi) ? " (native)" : ""; - fprintf(f, " %s%s\n", target_abi_name(abi), native_str); - } - - fprintf(f, "\nAvailable libcs:\n"); - size_t libc_count = target_libc_count(); - for (size_t i = 0; i < libc_count; i += 1) { - ZigTarget libc_target; - target_libc_enum(i, &libc_target); - bool is_native = native.arch == libc_target.arch && - native.os == libc_target.os && - native.abi == libc_target.abi; - const char *native_str = is_native ? " (native)" : ""; - fprintf(f, " %s-%s-%s%s\n", target_arch_name(libc_target.arch), - target_os_name(libc_target.os), target_abi_name(libc_target.abi), native_str); - } - - fprintf(f, "\nAvailable glibc versions:\n"); - ZigGLibCAbi *glibc_abi; - Error err; - if ((err = glibc_load_metadata(&glibc_abi, get_zig_lib_dir(), true))) { - return EXIT_FAILURE; - } - for (size_t i = 0; i < glibc_abi->all_versions.length; i += 1) { - ZigGLibCVersion *this_ver = &glibc_abi->all_versions.at(i); - bool is_native = native.glibc_version != nullptr && - native.glibc_version->major == this_ver->major && - native.glibc_version->minor == this_ver->minor && - native.glibc_version->patch == this_ver->patch; - const char *native_str = is_native ? " (native)" : ""; - if (this_ver->patch == 0) { - fprintf(f, " %d.%d%s\n", this_ver->major, this_ver->minor, native_str); - } else { - fprintf(f, " %d.%d.%d%s\n", this_ver->major, this_ver->minor, this_ver->patch, native_str); - } - } - return EXIT_SUCCESS; -} - enum Cmd { CmdNone, CmdBuild, @@ -478,6 +399,7 @@ int main(int argc, char **argv) { bool verbose_llvm_ir = false; bool verbose_cimport = false; bool verbose_cc = false; + bool verbose_llvm_cpu_features = false; bool link_eh_frame_hdr = false; ErrColor color = ErrColorAuto; CacheOpt enable_cache = CacheOptAuto; @@ -528,6 +450,8 @@ int main(int argc, char **argv) { WantStackCheck want_stack_check = WantStackCheckAuto; WantCSanitize want_sanitize_c = WantCSanitizeAuto; bool function_sections = false; + const char *cpu = nullptr; + const char *features = nullptr; ZigList llvm_argv = {0}; llvm_argv.append("zig (LLVM option parsing)"); @@ -692,6 +616,8 @@ int main(int argc, char **argv) { verbose_cimport = true; } else if (strcmp(arg, "--verbose-cc") == 0) { verbose_cc = true; + } else if (strcmp(arg, "--verbose-llvm-cpu-features") == 0) { + verbose_llvm_cpu_features = true; } else if (strcmp(arg, "-rdynamic") == 0) { rdynamic = true; } else if (strcmp(arg, "--each-lib-rpath") == 0) { @@ -936,6 +862,10 @@ int main(int argc, char **argv) { , argv[i]); return EXIT_FAILURE; } + } else if (strcmp(arg, "-target-cpu") == 0) { + cpu = argv[i]; + } else if (strcmp(arg, "-target-feature") == 0) { + features = argv[i]; } else { fprintf(stderr, "Invalid argument: %s\n", arg); return print_error_usage(arg0); @@ -1051,15 +981,22 @@ int main(int argc, char **argv) { } } + Buf zig_triple_buf = BUF_INIT; + target_triple_zig(&zig_triple_buf, &target); + + const char *stage2_triple_arg = target.is_native ? nullptr : buf_ptr(&zig_triple_buf); + if ((err = stage2_cpu_features_parse(&target.cpu_features, stage2_triple_arg, cpu, features))) { + fprintf(stderr, "unable to initialize CPU features: %s\n", err_str(err)); + return main_exit(root_progress_node, EXIT_FAILURE); + } + if (output_dir != nullptr && enable_cache == CacheOptOn) { fprintf(stderr, "`--output-dir` is incompatible with --cache on.\n"); return print_error_usage(arg0); } if (target_requires_pic(&target, have_libc) && want_pic == WantPICDisabled) { - Buf triple_buf = BUF_INIT; - target_triple_zig(&triple_buf, &target); - fprintf(stderr, "`--disable-pic` is incompatible with target '%s'\n", buf_ptr(&triple_buf)); + fprintf(stderr, "`--disable-pic` is incompatible with target '%s'\n", buf_ptr(&zig_triple_buf)); return print_error_usage(arg0); } @@ -1226,6 +1163,7 @@ int main(int argc, char **argv) { g->verbose_llvm_ir = verbose_llvm_ir; g->verbose_cimport = verbose_cimport; g->verbose_cc = verbose_cc; + g->verbose_llvm_cpu_features = verbose_llvm_cpu_features; g->output_dir = output_dir; g->disable_gen_h = disable_gen_h; g->bundle_compiler_rt = bundle_compiler_rt; @@ -1233,6 +1171,7 @@ int main(int argc, char **argv) { g->system_linker_hack = system_linker_hack; g->function_sections = function_sections; + for (size_t i = 0; i < lib_dirs.length; i += 1) { codegen_add_lib_dir(g, lib_dirs.at(i)); } @@ -1413,7 +1352,7 @@ int main(int argc, char **argv) { return main_exit(root_progress_node, EXIT_SUCCESS); } case CmdTargets: - return print_target_list(stdout); + return stage2_cmd_targets(buf_ptr(&zig_triple_buf)); case CmdNone: return print_full_usage(arg0, stderr, EXIT_FAILURE); } diff --git a/src/parser.cpp b/src/parser.cpp index 0054c0a0c6..a4dc324b2f 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -147,7 +147,7 @@ static void ast_invalid_token_error(ParseContext *pc, Token *token) { } static AstNode *ast_create_node_no_line_info(ParseContext *pc, NodeType type) { - AstNode *node = allocate(1); + AstNode *node = allocate(1, "AstNode"); node->type = type; node->owner = pc->owner; return node; diff --git a/src/target.cpp b/src/target.cpp index 82d5467e26..53d2e598be 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -57,9 +57,6 @@ static const ZigLLVM_SubArchType subarch_list_arm64[] = { ZigLLVM_ARMSubArch_v8_2a, ZigLLVM_ARMSubArch_v8_1a, ZigLLVM_ARMSubArch_v8, - ZigLLVM_ARMSubArch_v8r, - ZigLLVM_ARMSubArch_v8m_baseline, - ZigLLVM_ARMSubArch_v8m_mainline, }; static const ZigLLVM_SubArchType subarch_list_kalimba[] = { @@ -683,7 +680,7 @@ const char *target_subarch_name(ZigLLVM_SubArchType subarch) { case ZigLLVM_ARMSubArch_v8_1a: return "v8_1a"; case ZigLLVM_ARMSubArch_v8: - return "v8"; + return "v8a"; case ZigLLVM_ARMSubArch_v8r: return "v8r"; case ZigLLVM_ARMSubArch_v8m_baseline: @@ -693,7 +690,7 @@ const char *target_subarch_name(ZigLLVM_SubArchType subarch) { case ZigLLVM_ARMSubArch_v8_1m_mainline: return "v8_1m_mainline"; case ZigLLVM_ARMSubArch_v7: - return "v7"; + return "v7a"; case ZigLLVM_ARMSubArch_v7em: return "v7em"; case ZigLLVM_ARMSubArch_v7m: @@ -832,10 +829,10 @@ void init_all_targets(void) { void target_triple_zig(Buf *triple, const ZigTarget *target) { buf_resize(triple, 0); buf_appendf(triple, "%s%s-%s-%s", - ZigLLVMGetArchTypeName(target->arch), - ZigLLVMGetSubArchTypeName(target->sub_arch), - ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)), - ZigLLVMGetEnvironmentTypeName(target->abi)); + target_arch_name(target->arch), + target_subarch_name(target->sub_arch), + target_os_name(target->os), + target_abi_name(target->abi)); } void target_triple_llvm(Buf *triple, const ZigTarget *target) { diff --git a/src/target.hpp b/src/target.hpp index 50611bc853..3e984e1269 100644 --- a/src/target.hpp +++ b/src/target.hpp @@ -91,6 +91,7 @@ struct ZigTarget { Os os; ZigLLVM_EnvironmentType abi; ZigGLibCVersion *glibc_version; // null means default + Stage2CpuFeatures *cpu_features; bool is_native; }; diff --git a/src/userland.cpp b/src/userland.cpp index 263ef0cbc3..8524be5739 100644 --- a/src/userland.cpp +++ b/src/userland.cpp @@ -2,7 +2,8 @@ // src-self-hosted/stage1.zig #include "userland.h" -#include "ast_render.hpp" +#include "util.hpp" +#include "zig_llvm.h" #include #include #include @@ -88,3 +89,58 @@ void stage2_progress_end(Stage2ProgressNode *node) {} void stage2_progress_complete_one(Stage2ProgressNode *node) {} void stage2_progress_disable_tty(Stage2Progress *progress) {} void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){} + +struct Stage2CpuFeatures { + const char *llvm_cpu_name; + const char *llvm_cpu_features; + const char *builtin_str; + const char *cache_hash; +}; + +Error stage2_cpu_features_parse(struct Stage2CpuFeatures **out, const char *zig_triple, + const char *cpu_name, const char *cpu_features) +{ + if (zig_triple == nullptr) { + Stage2CpuFeatures *result = allocate(1, "Stage2CpuFeatures"); + result->llvm_cpu_name = ZigLLVMGetHostCPUName(); + result->llvm_cpu_features = ZigLLVMGetNativeFeatures(); + result->builtin_str = "arch.getBaselineCpuFeatures();\n"; + result->cache_hash = "native\n\n"; + *out = result; + return ErrorNone; + } + if (cpu_name == nullptr && cpu_features == nullptr) { + Stage2CpuFeatures *result = allocate(1, "Stage2CpuFeatures"); + result->builtin_str = "arch.getBaselineCpuFeatures();\n"; + result->cache_hash = "\n\n"; + *out = result; + return ErrorNone; + } + + const char *msg = "stage0 called stage2_cpu_features_parse with non-null cpu name or features"; + stage2_panic(msg, strlen(msg)); +} + +void stage2_cpu_features_get_cache_hash(const Stage2CpuFeatures *cpu_features, + const char **ptr, size_t *len) +{ + *ptr = cpu_features->cache_hash; + *len = strlen(cpu_features->cache_hash); +} +const char *stage2_cpu_features_get_llvm_cpu(const Stage2CpuFeatures *cpu_features) { + return cpu_features->llvm_cpu_name; +} +const char *stage2_cpu_features_get_llvm_features(const Stage2CpuFeatures *cpu_features) { + return cpu_features->llvm_cpu_features; +} +void stage2_cpu_features_get_builtin_str(const Stage2CpuFeatures *cpu_features, + const char **ptr, size_t *len) +{ + *ptr = cpu_features->builtin_str; + *len = strlen(cpu_features->builtin_str); +} + +int stage2_cmd_targets(const char *zig_triple) { + const char *msg = "stage0 called stage2_cmd_targets"; + stage2_panic(msg, strlen(msg)); +} diff --git a/src/userland.h b/src/userland.h index fe3f072ae5..6b16d2338e 100644 --- a/src/userland.h +++ b/src/userland.h @@ -78,6 +78,12 @@ enum Error { ErrorNotLazy, ErrorIsAsync, ErrorImportOutsidePkgPath, + ErrorUnknownCpu, + ErrorUnknownSubArchitecture, + ErrorUnknownCpuFeature, + ErrorInvalidCpuFeatures, + ErrorInvalidLlvmCpuFeaturesFormat, + ErrorUnknownApplicationBinaryInterface, }; // ABI warning @@ -174,4 +180,29 @@ ZIG_EXTERN_C void stage2_progress_complete_one(Stage2ProgressNode *node); ZIG_EXTERN_C void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items); +// ABI warning +struct Stage2CpuFeatures; + +// ABI warning +ZIG_EXTERN_C Error stage2_cpu_features_parse(struct Stage2CpuFeatures **result, + const char *zig_triple, const char *cpu_name, const char *cpu_features); + +// ABI warning +ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_cpu(const struct Stage2CpuFeatures *cpu_features); + +// ABI warning +ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_features(const struct Stage2CpuFeatures *cpu_features); + +// ABI warning +ZIG_EXTERN_C void stage2_cpu_features_get_builtin_str(const struct Stage2CpuFeatures *cpu_features, + const char **ptr, size_t *len); + +// ABI warning +ZIG_EXTERN_C void stage2_cpu_features_get_cache_hash(const struct Stage2CpuFeatures *cpu_features, + const char **ptr, size_t *len); + +// ABI warning +ZIG_EXTERN_C int stage2_cmd_targets(const char *zig_triple); + + #endif diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index 5769d2fc73..8a1baa2d49 100644 --- a/src/zig_clang.cpp +++ b/src/zig_clang.cpp @@ -1625,6 +1625,10 @@ unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionD return 0; } +ZigClangQualType ZigClangParmVarDecl_getOriginalType(const struct ZigClangParmVarDecl *self) { + return bitcast(reinterpret_cast(self)->getOriginalType()); +} + const ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const ZigClangRecordDecl *zig_record_decl) { const clang::RecordDecl *record_decl = reinterpret_cast(zig_record_decl); const clang::RecordDecl *definition = record_decl->getDefinition(); @@ -1877,6 +1881,11 @@ bool ZigClangType_isRecordType(const ZigClangType *self) { return casted->isRecordType(); } +bool ZigClangType_isConstantArrayType(const ZigClangType *self) { + auto casted = reinterpret_cast(self); + return casted->isConstantArrayType(); +} + const char *ZigClangType_getTypeClassName(const ZigClangType *self) { auto casted = reinterpret_cast(self); return casted->getTypeClassName(); diff --git a/src/zig_clang.h b/src/zig_clang.h index f9ced941cb..f7de9c2cee 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -866,6 +866,8 @@ ZIG_EXTERN_C const char* ZigClangVarDecl_getSectionAttribute(const struct ZigCla ZIG_EXTERN_C unsigned ZigClangVarDecl_getAlignedAttribute(const struct ZigClangVarDecl *self, const ZigClangASTContext* ctx); ZIG_EXTERN_C unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionDecl *self, const ZigClangASTContext* ctx); +ZIG_EXTERN_C struct ZigClangQualType ZigClangParmVarDecl_getOriginalType(const struct ZigClangParmVarDecl *self); + ZIG_EXTERN_C bool ZigClangRecordDecl_getPackedAttribute(const struct ZigClangRecordDecl *); ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangRecordDecl_getDefinition(const struct ZigClangRecordDecl *); ZIG_EXTERN_C const struct ZigClangEnumDecl *ZigClangEnumDecl_getDefinition(const struct ZigClangEnumDecl *); @@ -945,6 +947,7 @@ ZIG_EXTERN_C bool ZigClangType_isBooleanType(const struct ZigClangType *self); ZIG_EXTERN_C bool ZigClangType_isVoidType(const struct ZigClangType *self); ZIG_EXTERN_C bool ZigClangType_isArrayType(const struct ZigClangType *self); ZIG_EXTERN_C bool ZigClangType_isRecordType(const struct ZigClangType *self); +ZIG_EXTERN_C bool ZigClangType_isConstantArrayType(const ZigClangType *self); ZIG_EXTERN_C const char *ZigClangType_getTypeClassName(const struct ZigClangType *self); ZIG_EXTERN_C const struct ZigClangArrayType *ZigClangType_getAsArrayTypeUnsafe(const struct ZigClangType *self); ZIG_EXTERN_C const ZigClangRecordType *ZigClangType_getAsRecordType(const ZigClangType *self); diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index b5c43b632b..614d31dc5a 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -821,7 +821,7 @@ const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch) { case ZigLLVM_ARMSubArch_v8_1a: return "v8.1a"; case ZigLLVM_ARMSubArch_v8: - return "v8"; + return "v8a"; case ZigLLVM_ARMSubArch_v8r: return "v8r"; case ZigLLVM_ARMSubArch_v8m_baseline: @@ -831,7 +831,7 @@ const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch) { case ZigLLVM_ARMSubArch_v8_1m_mainline: return "v8.1m.main"; case ZigLLVM_ARMSubArch_v7: - return "v7"; + return "v7a"; case ZigLLVM_ARMSubArch_v7em: return "v7em"; case ZigLLVM_ARMSubArch_v7m: diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 3ce5bd8801..4a8dde2cdc 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1,7 +1,64 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); +const Target = @import("std").Target; pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.addTest("dependency loop in top-level decl with @TypeInfo", + \\export const foo = @typeInfo(@This()); + , &[_][]const u8{ + "tmp.zig:1:20: error: dependency loop detected", + }); + + cases.addTest("non-exhaustive enums", + \\const A = enum { + \\ a, + \\ b, + \\ _ = 1, + \\}; + \\const B = enum(u1) { + \\ a, + \\ _, + \\ b, + \\}; + \\const C = enum(u1) { + \\ a, + \\ b, + \\ _, + \\}; + \\pub export fn entry() void { + \\ _ = A; + \\ _ = B; + \\ _ = C; + \\} + , &[_][]const u8{ + "tmp.zig:4:5: error: non-exhaustive enum must specify size", + "error: value assigned to '_' field of non-exhaustive enum", + "error: non-exhaustive enum specifies every value", + "error: '_' field of non-exhaustive enum must be last", + }); + + cases.addTest("switching with non-exhaustive enums", + \\const E = enum(u8) { + \\ a, + \\ b, + \\ _, + \\}; + \\pub export fn entry() void { + \\ var e: E = .b; + \\ switch (e) { // error: switch not handling the tag `b` + \\ .a => {}, + \\ _ => {}, + \\ } + \\ switch (e) { // error: switch on non-exhaustive enum must include `else` or `_` prong + \\ .a => {}, + \\ .b => {}, + \\ } + \\} + , &[_][]const u8{ + "tmp.zig:8:5: error: enumeration value 'E.b' not handled in switch", + "tmp.zig:12:5: error: switch on non-exhaustive enum must include `else` or `_` prong", + }); + cases.addTest("@export with empty name string", \\pub export fn entry() void { } \\comptime { @@ -139,25 +196,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:2:13: error: pointer type '[*]align(4) u8' requires aligned address", }); - cases.add("switch on extern enum missing else prong", - \\const i = extern enum { - \\ n = 0, - \\ o = 2, - \\ p = 4, - \\ q = 4, - \\}; - \\pub fn main() void { - \\ var x = @intToEnum(i, 52); - \\ switch (x) { - \\ .n, - \\ .o, - \\ .p => unreachable, - \\ } - \\} - , &[_][]const u8{ - "tmp.zig:9:5: error: switch on an extern enum must have an else prong", - }); - cases.add("invalid float literal", \\const std = @import("std"); \\ @@ -241,9 +279,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { , &[_][]const u8{ "tmp.zig:3:5: error: target arch 'wasm32' does not support calling with a new stack", }); - tc.target = tests.Target{ - .Cross = tests.CrossTarget{ + tc.target = Target{ + .Cross = .{ .arch = .wasm32, + .cpu_features = Target.Arch.wasm32.getBaselineCpuFeatures(), .os = .wasi, .abi = .none, }, @@ -642,9 +681,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { , &[_][]const u8{ "tmp.zig:2:14: error: could not find 'foo' in the inputs or outputs", }); - tc.target = tests.Target{ - .Cross = tests.CrossTarget{ + tc.target = Target{ + .Cross = .{ .arch = .x86_64, + .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(), .os = .linux, .abi = .gnu, }, diff --git a/test/stack_traces.zig b/test/stack_traces.zig index ad4a34fe4e..81e074f01e 100644 --- a/test/stack_traces.zig +++ b/test/stack_traces.zig @@ -51,11 +51,15 @@ pub fn addCases(cases: *tests.StackTracesContext) void { // debug \\error: TheSkyIsFalling \\source.zig:4:5: [address] in main (test) + \\ return error.TheSkyIsFalling; + \\ ^ \\ , // release-safe \\error: TheSkyIsFalling \\source.zig:4:5: [address] in std.start.main (test) + \\ return error.TheSkyIsFalling; + \\ ^ \\ , // release-fast @@ -74,13 +78,21 @@ pub fn addCases(cases: *tests.StackTracesContext) void { // debug \\error: TheSkyIsFalling \\source.zig:4:5: [address] in foo (test) + \\ return error.TheSkyIsFalling; + \\ ^ \\source.zig:8:5: [address] in main (test) + \\ try foo(); + \\ ^ \\ , // release-safe \\error: TheSkyIsFalling \\source.zig:4:5: [address] in std.start.main (test) + \\ return error.TheSkyIsFalling; + \\ ^ \\source.zig:8:5: [address] in std.start.main (test) + \\ try foo(); + \\ ^ \\ , // release-fast @@ -99,17 +111,33 @@ pub fn addCases(cases: *tests.StackTracesContext) void { // debug \\error: TheSkyIsFalling \\source.zig:12:5: [address] in make_error (test) + \\ return error.TheSkyIsFalling; + \\ ^ \\source.zig:8:5: [address] in bar (test) + \\ return make_error(); + \\ ^ \\source.zig:4:5: [address] in foo (test) + \\ try bar(); + \\ ^ \\source.zig:16:5: [address] in main (test) + \\ try foo(); + \\ ^ \\ , // release-safe \\error: TheSkyIsFalling \\source.zig:12:5: [address] in std.start.main (test) + \\ return error.TheSkyIsFalling; + \\ ^ \\source.zig:8:5: [address] in std.start.main (test) + \\ return make_error(); + \\ ^ \\source.zig:4:5: [address] in std.start.main (test) + \\ try bar(); + \\ ^ \\source.zig:16:5: [address] in std.start.main (test) + \\ try foo(); + \\ ^ \\ , // release-fast @@ -130,11 +158,15 @@ pub fn addCases(cases: *tests.StackTracesContext) void { // debug \\error: TheSkyIsFalling \\source.zig:4:5: [address] in main (test) + \\ return error.TheSkyIsFalling; + \\ ^ \\ , // release-safe \\error: TheSkyIsFalling \\source.zig:4:5: [address] in std.start.posixCallMainAndExit (test) + \\ return error.TheSkyIsFalling; + \\ ^ \\ , // release-fast @@ -153,13 +185,21 @@ pub fn addCases(cases: *tests.StackTracesContext) void { // debug \\error: TheSkyIsFalling \\source.zig:4:5: [address] in foo (test) + \\ return error.TheSkyIsFalling; + \\ ^ \\source.zig:8:5: [address] in main (test) + \\ try foo(); + \\ ^ \\ , // release-safe \\error: TheSkyIsFalling \\source.zig:4:5: [address] in std.start.posixCallMainAndExit (test) + \\ return error.TheSkyIsFalling; + \\ ^ \\source.zig:8:5: [address] in std.start.posixCallMainAndExit (test) + \\ try foo(); + \\ ^ \\ , // release-fast @@ -178,17 +218,33 @@ pub fn addCases(cases: *tests.StackTracesContext) void { // debug \\error: TheSkyIsFalling \\source.zig:12:5: [address] in make_error (test) + \\ return error.TheSkyIsFalling; + \\ ^ \\source.zig:8:5: [address] in bar (test) + \\ return make_error(); + \\ ^ \\source.zig:4:5: [address] in foo (test) + \\ try bar(); + \\ ^ \\source.zig:16:5: [address] in main (test) + \\ try foo(); + \\ ^ \\ , // release-safe \\error: TheSkyIsFalling \\source.zig:12:5: [address] in std.start.posixCallMainAndExit (test) + \\ return error.TheSkyIsFalling; + \\ ^ \\source.zig:8:5: [address] in std.start.posixCallMainAndExit (test) + \\ return make_error(); + \\ ^ \\source.zig:4:5: [address] in std.start.posixCallMainAndExit (test) + \\ try bar(); + \\ ^ \\source.zig:16:5: [address] in std.start.posixCallMainAndExit (test) + \\ try foo(); + \\ ^ \\ , // release-fast @@ -209,11 +265,15 @@ pub fn addCases(cases: *tests.StackTracesContext) void { // debug \\error: TheSkyIsFalling \\source.zig:4:5: [address] in _main.0 (test.o) + \\ return error.TheSkyIsFalling; + \\ ^ \\ , // release-safe \\error: TheSkyIsFalling \\source.zig:4:5: [address] in _main (test.o) + \\ return error.TheSkyIsFalling; + \\ ^ \\ , // release-fast @@ -232,13 +292,21 @@ pub fn addCases(cases: *tests.StackTracesContext) void { // debug \\error: TheSkyIsFalling \\source.zig:4:5: [address] in _foo (test.o) + \\ return error.TheSkyIsFalling; + \\ ^ \\source.zig:8:5: [address] in _main.0 (test.o) + \\ try foo(); + \\ ^ \\ , // release-safe \\error: TheSkyIsFalling \\source.zig:4:5: [address] in _main (test.o) + \\ return error.TheSkyIsFalling; + \\ ^ \\source.zig:8:5: [address] in _main (test.o) + \\ try foo(); + \\ ^ \\ , // release-fast @@ -257,17 +325,33 @@ pub fn addCases(cases: *tests.StackTracesContext) void { // debug \\error: TheSkyIsFalling \\source.zig:12:5: [address] in _make_error (test.o) + \\ return error.TheSkyIsFalling; + \\ ^ \\source.zig:8:5: [address] in _bar (test.o) + \\ return make_error(); + \\ ^ \\source.zig:4:5: [address] in _foo (test.o) + \\ try bar(); + \\ ^ \\source.zig:16:5: [address] in _main.0 (test.o) + \\ try foo(); + \\ ^ \\ , // release-safe \\error: TheSkyIsFalling \\source.zig:12:5: [address] in _main (test.o) + \\ return error.TheSkyIsFalling; + \\ ^ \\source.zig:8:5: [address] in _main (test.o) + \\ return make_error(); + \\ ^ \\source.zig:4:5: [address] in _main (test.o) + \\ try bar(); + \\ ^ \\source.zig:16:5: [address] in _main (test.o) + \\ try foo(); + \\ ^ \\ , // release-fast @@ -288,6 +372,8 @@ pub fn addCases(cases: *tests.StackTracesContext) void { // debug \\error: TheSkyIsFalling \\source.zig:4:5: [address] in main (test.obj) + \\ return error.TheSkyIsFalling; + \\ ^ \\ , // release-safe @@ -309,7 +395,11 @@ pub fn addCases(cases: *tests.StackTracesContext) void { // debug \\error: TheSkyIsFalling \\source.zig:4:5: [address] in foo (test.obj) + \\ return error.TheSkyIsFalling; + \\ ^ \\source.zig:8:5: [address] in main (test.obj) + \\ try foo(); + \\ ^ \\ , // release-safe @@ -331,9 +421,17 @@ pub fn addCases(cases: *tests.StackTracesContext) void { // debug \\error: TheSkyIsFalling \\source.zig:12:5: [address] in make_error (test.obj) + \\ return error.TheSkyIsFalling; + \\ ^ \\source.zig:8:5: [address] in bar (test.obj) + \\ return make_error(); + \\ ^ \\source.zig:4:5: [address] in foo (test.obj) + \\ try bar(); + \\ ^ \\source.zig:16:5: [address] in main (test.obj) + \\ try foo(); + \\ ^ \\ , // release-safe diff --git a/test/stage1/behavior/bitcast.zig b/test/stage1/behavior/bitcast.zig index 9c315c169c..bb45fe00bc 100644 --- a/test/stage1/behavior/bitcast.zig +++ b/test/stage1/behavior/bitcast.zig @@ -168,11 +168,11 @@ test "nested bitcast" { comptime S.foo(42); } -test "bitcast passed as tuple element" { - const S = struct { - fn foo(args: var) void { - expect(args[0] == 1.00000e-09); - } - }; - S.foo(.{@bitCast(f32, @as(u32, 814313563))}); -} +//test "bitcast passed as tuple element" { +// const S = struct { +// fn foo(args: var) void { +// expect(args[0] == 1.00000e-09); +// } +// }; +// S.foo(.{@bitCast(f32, @as(u32, 814313563))}); +//} diff --git a/test/stage1/behavior/cast.zig b/test/stage1/behavior/cast.zig index ae2530af61..fe55b445a8 100644 --- a/test/stage1/behavior/cast.zig +++ b/test/stage1/behavior/cast.zig @@ -618,7 +618,6 @@ test "peer resolution of string literals" { .b => "two", .c => "three", .d => "four", - else => unreachable, }; expect(mem.eql(u8, cmd, "two")); } diff --git a/test/stage1/behavior/enum.zig b/test/stage1/behavior/enum.zig index d5bb2ddbb2..6187cee431 100644 --- a/test/stage1/behavior/enum.zig +++ b/test/stage1/behavior/enum.zig @@ -11,16 +11,9 @@ test "extern enum" { }; fn doTheTest(y: c_int) void { var x = i.o; - expect(@enumToInt(x) == 2); - x = @intToEnum(i, 12); - expect(@enumToInt(x) == 12); - x = @intToEnum(i, y); - expect(@enumToInt(x) == 52); switch (x) { - .n, - .o, - .p => unreachable, - else => {}, + .n, .p => unreachable, + .o => {}, } } }; @@ -28,6 +21,70 @@ test "extern enum" { comptime S.doTheTest(52); } +test "non-exhaustive enum" { + const S = struct { + const E = enum(u8) { + a, + b, + _, + }; + fn doTheTest(y: u8) void { + var e: E = .b; + expect(switch (e) { + .a => false, + .b => true, + _ => false, + }); + e = @intToEnum(E, 12); + expect(switch (e) { + .a => false, + .b => false, + _ => true, + }); + + expect(switch (e) { + .a => false, + .b => false, + else => true, + }); + e = .b; + expect(switch (e) { + .a => false, + else => true, + }); + + expect(@typeInfo(E).Enum.fields.len == 2); + e = @intToEnum(E, 12); + expect(@enumToInt(e) == 12); + e = @intToEnum(E, y); + expect(@enumToInt(e) == 52); + expect(@typeInfo(E).Enum.is_exhaustive == false); + } + }; + S.doTheTest(52); + comptime S.doTheTest(52); +} + +test "empty non-exhaustive enum" { + const S = struct { + const E = enum(u8) { + _, + }; + fn doTheTest(y: u8) void { + var e = @intToEnum(E, y); + expect(switch (e) { + _ => true, + }); + expect(@enumToInt(e) == y); + + expect(@typeInfo(E).Enum.fields.len == 0); + expect(@typeInfo(E).Enum.is_exhaustive == false); + } + }; + S.doTheTest(42); + comptime S.doTheTest(42); +} + test "enum type" { const foo1 = Foo{ .One = 13 }; const foo2 = Foo{ @@ -1057,3 +1114,8 @@ test "enum with one member default to u0 tag type" { }; comptime expect(@TagType(E0) == u0); } + +test "tagName on enum literals" { + expect(mem.eql(u8, @tagName(.FooBar), "FooBar")); + comptime expect(mem.eql(u8, @tagName(.FooBar), "FooBar")); +} diff --git a/test/stage1/behavior/math.zig b/test/stage1/behavior/math.zig index e00b1a83fa..2283118787 100644 --- a/test/stage1/behavior/math.zig +++ b/test/stage1/behavior/math.zig @@ -529,6 +529,10 @@ test "comptime_int xor" { } test "f128" { + if (std.Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } test_f128(); comptime test_f128(); } @@ -627,6 +631,10 @@ test "NaN comparison" { // TODO: https://github.com/ziglang/zig/issues/3338 return error.SkipZigTest; } + if (std.Target.current.isWindows()) { + // TODO https://github.com/ziglang/zig/issues/508 + return error.SkipZigTest; + } testNanEqNan(f16); testNanEqNan(f32); testNanEqNan(f64); diff --git a/test/stage1/behavior/union.zig b/test/stage1/behavior/union.zig index a24bee03e6..4625b7573a 100644 --- a/test/stage1/behavior/union.zig +++ b/test/stage1/behavior/union.zig @@ -629,3 +629,12 @@ test "union initializer generates padding only if needed" { var v = U{ .A = 532 }; expect(v.A == 532); } + +test "runtime tag name with single field" { + const U = union(enum) { + A: i32, + }; + + var v = U{ .A = 42 }; + expect(std.mem.eql(u8, @tagName(v), "A")); +} diff --git a/test/tests.zig b/test/tests.zig index 7c97e46e02..f079b4664c 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -38,236 +38,260 @@ const TestTarget = struct { disable_native: bool = false, }; -const test_targets = [_]TestTarget{ - TestTarget{}, - TestTarget{ - .link_libc = true, - }, - TestTarget{ - .single_threaded = true, - }, +const test_targets = blk: { + // getBaselineCpuFeatures calls populateDependencies which has a O(N ^ 2) algorithm + // (where N is roughly 160, which technically makes it O(1), but it adds up to a + // lot of branches) + @setEvalBranchQuota(50000); + break :blk [_]TestTarget{ + TestTarget{}, + TestTarget{ + .link_libc = true, + }, + TestTarget{ + .single_threaded = true, + }, - TestTarget{ - .target = Target{ - .Cross = CrossTarget{ - .os = .linux, - .arch = .x86_64, - .abi = .none, + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .linux, + .arch = .x86_64, + .abi = .none, + .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(), + }, }, }, - }, - TestTarget{ - .target = Target{ - .Cross = CrossTarget{ - .os = .linux, - .arch = .x86_64, - .abi = .gnu, + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .linux, + .arch = .x86_64, + .abi = .gnu, + .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(), + }, }, + .link_libc = true, }, - .link_libc = true, - }, - TestTarget{ - .target = Target{ - .Cross = CrossTarget{ - .os = .linux, - .arch = .x86_64, - .abi = .musl, + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .linux, + .arch = .x86_64, + .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(), + .abi = .musl, + }, }, + .link_libc = true, }, - .link_libc = true, - }, - TestTarget{ - .target = Target{ - .Cross = CrossTarget{ - .os = .linux, - .arch = .i386, - .abi = .none, + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .linux, + .arch = .i386, + .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(), + .abi = .none, + }, }, }, - }, - TestTarget{ - .target = Target{ - .Cross = CrossTarget{ - .os = .linux, - .arch = .i386, - .abi = .musl, + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .linux, + .arch = .i386, + .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(), + .abi = .musl, + }, }, + .link_libc = true, }, - .link_libc = true, - }, - TestTarget{ - .target = Target{ - .Cross = CrossTarget{ - .os = .linux, - .arch = builtin.Arch{ .aarch64 = builtin.Arch.Arm64.v8_5a }, - .abi = .none, + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .linux, + .arch = Target.Arch{ .aarch64 = .v8a }, + .cpu_features = (Target.Arch{ .aarch64 = .v8a }).getBaselineCpuFeatures(), + .abi = .none, + }, }, }, - }, - TestTarget{ - .target = Target{ - .Cross = CrossTarget{ - .os = .linux, - .arch = builtin.Arch{ .aarch64 = builtin.Arch.Arm64.v8_5a }, - .abi = .musl, + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .linux, + .arch = Target.Arch{ .aarch64 = .v8a }, + .cpu_features = (Target.Arch{ .aarch64 = .v8a }).getBaselineCpuFeatures(), + .abi = .musl, + }, }, + .link_libc = true, }, - .link_libc = true, - }, - TestTarget{ - .target = Target{ - .Cross = CrossTarget{ - .os = .linux, - .arch = builtin.Arch{ .aarch64 = builtin.Arch.Arm64.v8_5a }, - .abi = .gnu, + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .linux, + .arch = Target.Arch{ .aarch64 = .v8a }, + .cpu_features = (Target.Arch{ .aarch64 = .v8a }).getBaselineCpuFeatures(), + .abi = .gnu, + }, }, + .link_libc = true, }, - .link_libc = true, - }, - TestTarget{ - .target = Target{ - .Cross = CrossTarget{ - .os = .linux, - .arch = builtin.Arch{ .arm = builtin.Arch.Arm32.v8_5a }, - .abi = .none, + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .linux, + .arch = Target.Arch{ .arm = .v8a }, + .cpu_features = (Target.Arch{ .arm = .v8a }).getBaselineCpuFeatures(), + .abi = .none, + }, }, }, - }, - TestTarget{ - .target = Target{ - .Cross = CrossTarget{ - .os = .linux, - .arch = builtin.Arch{ .arm = builtin.Arch.Arm32.v8_5a }, - .abi = .musleabihf, + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .linux, + .arch = Target.Arch{ .arm = .v8a }, + .cpu_features = (Target.Arch{ .arm = .v8a }).getBaselineCpuFeatures(), + .abi = .musleabihf, + }, + }, + .link_libc = true, + }, + // TODO https://github.com/ziglang/zig/issues/3287 + //TestTarget{ + // .target = Target{ + // .Cross = CrossTarget{ + // .os = .linux, + // .arch = Target.Arch{ .arm = .v8a }, + // .cpu_features = (Target.Arch{ .arm = .v8a }).getBaselineCpuFeatures(), + // .abi = .gnueabihf, + // }, + // }, + // .link_libc = true, + //}, + + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .linux, + .arch = .mipsel, + .cpu_features = Target.Arch.mipsel.getBaselineCpuFeatures(), + .abi = .none, + }, }, }, - .link_libc = true, - }, - // TODO https://github.com/ziglang/zig/issues/3287 - //TestTarget{ - // .target = Target{ - // .Cross = CrossTarget{ - // .os = .linux, - // .arch = builtin.Arch{ .arm = builtin.Arch.Arm32.v8_5a }, - // .abi = .gnueabihf, - // }, - // }, - // .link_libc = true, - //}, + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .linux, + .arch = .mipsel, + .cpu_features = Target.Arch.mipsel.getBaselineCpuFeatures(), + .abi = .musl, + }, + }, + .link_libc = true, + }, - TestTarget{ - .target = Target{ - .Cross = CrossTarget{ - .os = .linux, - .arch = .mipsel, - .abi = .none, + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .macosx, + .arch = .x86_64, + .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(), + .abi = .gnu, + }, + }, + // TODO https://github.com/ziglang/zig/issues/3295 + .disable_native = true, + }, + + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .windows, + .arch = .i386, + .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(), + .abi = .msvc, + }, }, }, - }, - TestTarget{ - .target = Target{ - .Cross = CrossTarget{ - .os = .linux, - .arch = .mipsel, - .abi = .musl, + + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .windows, + .arch = .x86_64, + .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(), + .abi = .msvc, + }, }, }, - .link_libc = true, - }, - TestTarget{ - .target = Target{ - .Cross = CrossTarget{ - .os = .macosx, - .arch = .x86_64, - .abi = .gnu, + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .windows, + .arch = .i386, + .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(), + .abi = .gnu, + }, }, + .link_libc = true, }, - // TODO https://github.com/ziglang/zig/issues/3295 - .disable_native = true, - }, - TestTarget{ - .target = Target{ - .Cross = CrossTarget{ - .os = .windows, - .arch = .i386, - .abi = .msvc, + TestTarget{ + .target = Target{ + .Cross = CrossTarget{ + .os = .windows, + .arch = .x86_64, + .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(), + .abi = .gnu, + }, }, + .link_libc = true, }, - }, - TestTarget{ - .target = Target{ - .Cross = CrossTarget{ - .os = .windows, - .arch = .x86_64, - .abi = .msvc, - }, + // Do the release tests last because they take a long time + TestTarget{ + .mode = .ReleaseFast, }, - }, - - TestTarget{ - .target = Target{ - .Cross = CrossTarget{ - .os = .windows, - .arch = .i386, - .abi = .gnu, - }, + TestTarget{ + .link_libc = true, + .mode = .ReleaseFast, }, - .link_libc = true, - }, - - TestTarget{ - .target = Target{ - .Cross = CrossTarget{ - .os = .windows, - .arch = .x86_64, - .abi = .gnu, - }, + TestTarget{ + .mode = .ReleaseFast, + .single_threaded = true, }, - .link_libc = true, - }, - // Do the release tests last because they take a long time - TestTarget{ - .mode = .ReleaseFast, - }, - TestTarget{ - .link_libc = true, - .mode = .ReleaseFast, - }, - TestTarget{ - .mode = .ReleaseFast, - .single_threaded = true, - }, + TestTarget{ + .mode = .ReleaseSafe, + }, + TestTarget{ + .link_libc = true, + .mode = .ReleaseSafe, + }, + TestTarget{ + .mode = .ReleaseSafe, + .single_threaded = true, + }, - TestTarget{ - .mode = .ReleaseSafe, - }, - TestTarget{ - .link_libc = true, - .mode = .ReleaseSafe, - }, - TestTarget{ - .mode = .ReleaseSafe, - .single_threaded = true, - }, - - TestTarget{ - .mode = .ReleaseSmall, - }, - TestTarget{ - .link_libc = true, - .mode = .ReleaseSmall, - }, - TestTarget{ - .mode = .ReleaseSmall, - .single_threaded = true, - }, + TestTarget{ + .mode = .ReleaseSmall, + }, + TestTarget{ + .link_libc = true, + .mode = .ReleaseSmall, + }, + TestTarget{ + .mode = .ReleaseSmall, + .single_threaded = true, + }, + }; }; const max_stdout_size = 1 * 1024 * 1024; // 1 MB @@ -598,6 +622,9 @@ pub const StackTracesContext = struct { child.stderr_behavior = .Pipe; child.env_map = b.env_map; + if (b.verbose) { + printInvocation(args.toSliceConst()); + } child.spawn() catch |err| debug.panic("Unable to spawn {}: {}\n", .{ full_exe_path, @errorName(err) }); var stdout = Buffer.initNull(b.allocator); diff --git a/test/translate_c.zig b/test/translate_c.zig index 16caa6e323..1bc54badf3 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -1,7 +1,33 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); +const Target = @import("std").Target; pub fn addCases(cases: *tests.TranslateCContext) void { + cases.add("array initializer w/ typedef", + \\typedef unsigned char uuid_t[16]; + \\static const uuid_t UUID_NULL __attribute__ ((unused)) = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + , &[_][]const u8{ + \\pub const uuid_t = [16]u8; + \\pub const UUID_NULL: uuid_t = .{ + \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))), + \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))), + \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))), + \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))), + \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))), + \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))), + \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))), + \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))), + \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))), + \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))), + \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))), + \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))), + \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))), + \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))), + \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))), + \\ @bitCast(u8, @truncate(i8, @as(c_int, 0))), + \\}; + }); + cases.add("empty declaration", \\; , &[_][]const u8{""}); @@ -629,6 +655,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ VAL21 = 6917529027641081853, \\ VAL22 = 0, \\ VAL23 = -1, + \\ _, \\}; }); } @@ -988,8 +1015,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\enum enum_ty { FOO }; , &[_][]const u8{ \\pub const FOO = @enumToInt(enum_enum_ty.FOO); - \\pub const enum_enum_ty = extern enum { + \\pub const enum_enum_ty = extern enum(c_int) { \\ FOO, + \\ _, \\}; \\pub extern var my_enum: enum_enum_ty; }); @@ -1003,7 +1031,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }); cases.addWithTarget("Calling convention", tests.Target{ - .Cross = .{ .os = .linux, .arch = .i386, .abi = .none }, + .Cross = .{ + .os = .linux, + .arch = .i386, + .abi = .none, + .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(), + }, }, \\void __attribute__((fastcall)) foo1(float *a); \\void __attribute__((stdcall)) foo2(float *a); @@ -1019,7 +1052,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }); cases.addWithTarget("Calling convention", tests.Target{ - .Cross = .{ .os = .linux, .arch = .{ .arm = .v8_5a }, .abi = .none }, + .Cross = .{ + .os = .linux, + .arch = .{ .arm = .v8_5a }, + .abi = .none, + .cpu_features = (Target.Arch{ .arm = .v8_5a }).getBaselineCpuFeatures(), + }, }, \\void __attribute__((pcs("aapcs"))) foo1(float *a); \\void __attribute__((pcs("aapcs-vfp"))) foo2(float *a); @@ -1029,7 +1067,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { }); cases.addWithTarget("Calling convention", tests.Target{ - .Cross = .{ .os = .linux, .arch = .{ .aarch64 = .v8_5a }, .abi = .none }, + .Cross = .{ + .os = .linux, + .arch = .{ .aarch64 = .v8_5a }, + .abi = .none, + .cpu_features = (Target.Arch{ .aarch64 = .v8_5a }).getBaselineCpuFeatures(), + }, }, \\void __attribute__((aarch64_vector_pcs)) foo1(float *a); , &[_][]const u8{ @@ -1102,28 +1145,31 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub const a = @enumToInt(enum_unnamed_1.a); \\pub const b = @enumToInt(enum_unnamed_1.b); \\pub const c = @enumToInt(enum_unnamed_1.c); - \\const enum_unnamed_1 = extern enum { + \\const enum_unnamed_1 = extern enum(c_int) { \\ a, \\ b, \\ c, + \\ _, \\}; \\pub const d = enum_unnamed_1; \\pub const e = @enumToInt(enum_unnamed_2.e); \\pub const f = @enumToInt(enum_unnamed_2.f); \\pub const g = @enumToInt(enum_unnamed_2.g); - \\const enum_unnamed_2 = extern enum { + \\const enum_unnamed_2 = extern enum(c_int) { \\ e = 0, \\ f = 4, \\ g = 5, + \\ _, \\}; \\pub export var h: enum_unnamed_2 = @intToEnum(enum_unnamed_2, e); \\pub const i = @enumToInt(enum_unnamed_3.i); \\pub const j = @enumToInt(enum_unnamed_3.j); \\pub const k = @enumToInt(enum_unnamed_3.k); - \\const enum_unnamed_3 = extern enum { + \\const enum_unnamed_3 = extern enum(c_int) { \\ i, \\ j, \\ k, + \\ _, \\}; \\pub const struct_Baz = extern struct { \\ l: enum_unnamed_3, @@ -1132,10 +1178,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub const n = @enumToInt(enum_i.n); \\pub const o = @enumToInt(enum_i.o); \\pub const p = @enumToInt(enum_i.p); - \\pub const enum_i = extern enum { + \\pub const enum_i = extern enum(c_int) { \\ n, \\ o, \\ p, + \\ _, \\}; , \\pub const Baz = struct_Baz; @@ -1563,9 +1610,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void { , &[_][]const u8{ \\pub const One = @enumToInt(enum_unnamed_1.One); \\pub const Two = @enumToInt(enum_unnamed_1.Two); - \\const enum_unnamed_1 = extern enum { + \\const enum_unnamed_1 = extern enum(c_int) { \\ One, \\ Two, + \\ _, \\}; }); @@ -1665,10 +1713,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p); \\} , &[_][]const u8{ - \\pub const enum_Foo = extern enum { + \\pub const enum_Foo = extern enum(c_int) { \\ A, \\ B, \\ C, + \\ _, \\}; \\pub const SomeTypedef = c_int; \\pub export fn and_or_non_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void) c_int { @@ -1710,9 +1759,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ y: c_int, \\}; , - \\pub const enum_Bar = extern enum { + \\pub const enum_Bar = extern enum(c_int) { \\ A, \\ B, + \\ _, \\}; \\pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void; , @@ -1973,10 +2023,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return 4; \\} , &[_][]const u8{ - \\pub const enum_SomeEnum = extern enum { + \\pub const enum_SomeEnum = extern enum(c_int) { \\ A, \\ B, \\ C, + \\ _, \\}; \\pub export fn if_none_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void, arg_d: enum_SomeEnum) c_int { \\ var a = arg_a; @@ -2414,10 +2465,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub const FooA = @enumToInt(enum_Foo.A); \\pub const FooB = @enumToInt(enum_Foo.B); \\pub const Foo1 = @enumToInt(enum_Foo.@"1"); - \\pub const enum_Foo = extern enum { + \\pub const enum_Foo = extern enum(c_int) { \\ A = 2, \\ B = 5, \\ @"1" = 6, + \\ _, \\}; , \\pub const Foo = enum_Foo; @@ -2579,4 +2631,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return foo((@intCast(c_int, @bitCast(i1, @intCast(u1, @boolToInt(c)))) != @intCast(c_int, @bitCast(i1, @intCast(u1, @boolToInt(b)))))); \\} }); + + cases.add("Don't make const parameters mutable", + \\int max(const int x, int y) { + \\ return (x > y) ? x : y; + \\} + , &[_][]const u8{ + \\pub export fn max(x: c_int, arg_y: c_int) c_int { + \\ var y = arg_y; + \\ return if (x > y) x else y; + \\} + }); + }